diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSArrayBufferView.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSArrayBufferView.cpp | 168 |
1 files changed, 94 insertions, 74 deletions
diff --git a/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp b/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp index c9812688e..76b7fcd1f 100644 --- a/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp +++ b/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,15 +27,32 @@ #include "JSArrayBufferView.h" #include "JSArrayBuffer.h" -#include "Operations.h" -#include "Reject.h" +#include "JSCInlines.h" +#include "TypeError.h" +#include "TypedArrayController.h" namespace JSC { const ClassInfo JSArrayBufferView::s_info = { - "ArrayBufferView", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSArrayBufferView) + "ArrayBufferView", &Base::s_info, 0, CREATE_METHOD_TABLE(JSArrayBufferView) }; +String JSArrayBufferView::toStringName(const JSObject*, ExecState*) +{ + return ASCIILiteral("Object"); +} + +JSArrayBufferView::ConstructionContext::ConstructionContext( + Structure* structure, uint32_t length, void* vector) + : m_structure(structure) + , m_vector(vector) + , m_length(length) + , m_mode(FastTypedArray) + , m_butterfly(nullptr) +{ + RELEASE_ASSERT(length <= fastSizeLimit); +} + JSArrayBufferView::ConstructionContext::ConstructionContext( VM& vm, Structure* structure, uint32_t length, uint32_t elementSize, InitializationMode mode) @@ -45,23 +62,24 @@ JSArrayBufferView::ConstructionContext::ConstructionContext( { if (length <= fastSizeLimit) { // Attempt GC allocation. - void* temp = 0; + void* temp; size_t size = sizeOf(length, elementSize); - // CopiedSpace only allows non-zero size allocations. - if (size && !vm.heap.tryAllocateStorage(0, size, &temp)) - return; + if (size) { + temp = vm.auxiliarySpace.tryAllocate(nullptr, size); + if (!temp) + return; + } else + temp = nullptr; m_structure = structure; m_vector = temp; m_mode = FastTypedArray; -#if USE(JSVALUE32_64) if (mode == ZeroFill) { uint64_t* asWords = static_cast<uint64_t*>(m_vector); for (unsigned i = size / sizeof(uint64_t); i--;) asWords[i] = 0; } -#endif // USE(JSVALUE32_64) return; } @@ -78,42 +96,42 @@ JSArrayBufferView::ConstructionContext::ConstructionContext( return; } - vm.heap.reportExtraMemoryCost(static_cast<size_t>(length) * elementSize); + vm.heap.reportExtraMemoryAllocated(static_cast<size_t>(length) * elementSize); m_structure = structure; m_mode = OversizeTypedArray; } JSArrayBufferView::ConstructionContext::ConstructionContext( - VM& vm, Structure* structure, PassRefPtr<ArrayBuffer> arrayBuffer, + VM& vm, Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer, unsigned byteOffset, unsigned length) : m_structure(structure) - , m_vector(static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset) , m_length(length) , m_mode(WastefulTypedArray) { + m_vector = static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset; IndexingHeader indexingHeader; indexingHeader.setArrayBuffer(arrayBuffer.get()); m_butterfly = Butterfly::create(vm, 0, 0, 0, true, indexingHeader, 0); } JSArrayBufferView::ConstructionContext::ConstructionContext( - Structure* structure, PassRefPtr<ArrayBuffer> arrayBuffer, + Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer, unsigned byteOffset, unsigned length, DataViewTag) : m_structure(structure) - , m_vector(static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset) , m_length(length) , m_mode(DataViewMode) , m_butterfly(0) { + m_vector = static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset; } JSArrayBufferView::JSArrayBufferView(VM& vm, ConstructionContext& context) : Base(vm, context.structure(), context.butterfly()) - , m_vector(context.vector()) , m_length(context.length()) , m_mode(context.mode()) { + m_vector.setWithoutBarrier(context.vector()); } void JSArrayBufferView::finishCreation(VM& vm) @@ -130,93 +148,95 @@ void JSArrayBufferView::finishCreation(VM& vm) return; case DataViewMode: ASSERT(!butterfly()); - vm.heap.addReference(this, jsCast<JSDataView*>(this)->buffer()); + vm.heap.addReference(this, jsCast<JSDataView*>(this)->possiblySharedBuffer()); return; } RELEASE_ASSERT_NOT_REACHED(); } -bool JSArrayBufferView::getOwnPropertySlot( - JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) +void JSArrayBufferView::visitChildren(JSCell* cell, SlotVisitor& visitor) { - JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object); - if (propertyName == exec->propertyNames().byteOffset) { - slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->byteOffset())); - return true; - } - - if (propertyName == exec->propertyNames().buffer) { - slot.setValue( - thisObject, DontDelete | ReadOnly, exec->vm().m_typedArrayController->toJS( - exec, thisObject->globalObject(), thisObject->buffer())); - return true; + JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell); + + if (thisObject->hasArrayBuffer()) { + WTF::loadLoadFence(); + ArrayBuffer* buffer = thisObject->possiblySharedBuffer(); + RELEASE_ASSERT(buffer); + visitor.addOpaqueRoot(buffer); } - return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); + Base::visitChildren(thisObject, visitor); } -void JSArrayBufferView::put( +bool JSArrayBufferView::put( JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell); - if (propertyName == exec->propertyNames().byteLength - || propertyName == exec->propertyNames().byteOffset - || propertyName == exec->propertyNames().buffer) { - reject(exec, slot.isStrictMode(), "Attempting to write to read-only typed array property."); - return; - } + + if (UNLIKELY(isThisValueAltered(slot, thisObject))) + return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode()); - Base::put(thisObject, exec, propertyName, value, slot); + return Base::put(thisObject, exec, propertyName, value, slot); } -bool JSArrayBufferView::defineOwnProperty( - JSObject* object, ExecState* exec, PropertyName propertyName, - const PropertyDescriptor& descriptor, bool shouldThrow) +ArrayBuffer* JSArrayBufferView::unsharedBuffer() { - JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object); - if (propertyName == exec->propertyNames().byteLength - || propertyName == exec->propertyNames().byteOffset - || propertyName == exec->propertyNames().buffer) - return reject(exec, shouldThrow, "Attempting to define read-only typed array property."); + ArrayBuffer* result = possiblySharedBuffer(); + RELEASE_ASSERT(!result->isShared()); + return result; +} - return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); +void JSArrayBufferView::finalize(JSCell* cell) +{ + JSArrayBufferView* thisObject = static_cast<JSArrayBufferView*>(cell); + ASSERT(thisObject->m_mode == OversizeTypedArray || thisObject->m_mode == WastefulTypedArray); + if (thisObject->m_mode == OversizeTypedArray) + fastFree(thisObject->m_vector.get()); } -bool JSArrayBufferView::deleteProperty( - JSCell* cell, ExecState* exec, PropertyName propertyName) +JSArrayBuffer* JSArrayBufferView::unsharedJSBuffer(ExecState* exec) { - JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell); - if (propertyName == exec->propertyNames().byteLength - || propertyName == exec->propertyNames().byteOffset - || propertyName == exec->propertyNames().buffer) - return false; - - return Base::deleteProperty(thisObject, exec, propertyName); + return exec->vm().m_typedArrayController->toJS(exec, globalObject(), unsharedBuffer()); } -void JSArrayBufferView::getOwnNonIndexPropertyNames( - JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode) +JSArrayBuffer* JSArrayBufferView::possiblySharedJSBuffer(ExecState* exec) { - JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object); - - // length/byteOffset/byteLength are DontEnum, at least in Firefox. - if (mode == IncludeDontEnumProperties) { - array.add(exec->propertyNames().byteOffset); - array.add(exec->propertyNames().byteLength); - array.add(exec->propertyNames().buffer); - } - - Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode); + return exec->vm().m_typedArrayController->toJS(exec, globalObject(), possiblySharedBuffer()); } -void JSArrayBufferView::finalize(JSCell* cell) +void JSArrayBufferView::neuter() { - JSArrayBufferView* thisObject = static_cast<JSArrayBufferView*>(cell); - ASSERT(thisObject->m_mode == OversizeTypedArray || thisObject->m_mode == WastefulTypedArray); - if (thisObject->m_mode == OversizeTypedArray) - fastFree(thisObject->m_vector); + RELEASE_ASSERT(hasArrayBuffer()); + RELEASE_ASSERT(!isShared()); + m_length = 0; + m_vector.clear(); } } // namespace JSC +namespace WTF { + +using namespace JSC; + +void printInternal(PrintStream& out, TypedArrayMode mode) +{ + switch (mode) { + case FastTypedArray: + out.print("FastTypedArray"); + return; + case OversizeTypedArray: + out.print("OversizeTypedArray"); + return; + case WastefulTypedArray: + out.print("WastefulTypedArray"); + return; + case DataViewMode: + out.print("DataViewMode"); + return; + } + RELEASE_ASSERT_NOT_REACHED(); +} + +} // namespace WTF + |