Remove poisoning of typed array vector
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSArrayBufferView.cpp
index d4b5cc0..b374454 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2016 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
 
 #include "JSArrayBuffer.h"
 #include "JSCInlines.h"
-#include "Reject.h"
+#include "TypeError.h"
+#include "TypedArrayController.h"
+#include <wtf/Gigacage.h>
 
 namespace JSC {
 
 const ClassInfo JSArrayBufferView::s_info = {
-    "ArrayBufferView", &Base::s_info, 0, CREATE_METHOD_TABLE(JSArrayBufferView)
+    "ArrayBufferView", &Base::s_info, nullptr, nullptr, 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 +63,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.primitiveGigacageAuxiliarySpace.allocateNonVirtual(vm, size, nullptr, AllocationFailureMode::ReturnNull);
+            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);
+            uint64_t* asWords = static_cast<uint64_t*>(m_vector.getMayBeNull());
             for (unsigned i = size / sizeof(uint64_t); i--;)
                 asWords[i] = 0;
         }
-#endif // USE(JSVALUE32_64)
         
         return;
     }
@@ -70,13 +89,12 @@ JSArrayBufferView::ConstructionContext::ConstructionContext(
     if (length > static_cast<unsigned>(INT_MAX) / elementSize)
         return;
     
-    if (mode == ZeroFill) {
-        if (!tryFastCalloc(length, elementSize).getValue(m_vector))
-            return;
-    } else {
-        if (!tryFastMalloc(length * elementSize).getValue(m_vector))
-            return;
-    }
+    size_t size = static_cast<size_t>(length) * static_cast<size_t>(elementSize);
+    m_vector = Gigacage::tryMalloc(Gigacage::Primitive, size);
+    if (!m_vector)
+        return;
+    if (mode == ZeroFill)
+        memset(m_vector.get(), 0, size);
     
     vm.heap.reportExtraMemoryAllocated(static_cast<size_t>(length) * elementSize);
     
@@ -85,7 +103,7 @@ JSArrayBufferView::ConstructionContext::ConstructionContext(
 }
 
 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_length(length)
@@ -98,7 +116,7 @@ JSArrayBufferView::ConstructionContext::ConstructionContext(
 }
 
 JSArrayBufferView::ConstructionContext::ConstructionContext(
-    Structure* structure, PassRefPtr<ArrayBuffer> arrayBuffer,
+    Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer,
     unsigned byteOffset, unsigned length, DataViewTag)
     : m_structure(structure)
     , m_length(length)
@@ -109,16 +127,18 @@ JSArrayBufferView::ConstructionContext::ConstructionContext(
 }
 
 JSArrayBufferView::JSArrayBufferView(VM& vm, ConstructionContext& context)
-    : Base(vm, context.structure(), context.butterfly())
+    : Base(vm, context.structure(), nullptr)
     , m_length(context.length())
     , m_mode(context.mode())
 {
-    m_vector.setWithoutBarrier(static_cast<char*>(context.vector()));
+    setButterfly(vm, context.butterfly());
+    m_vector.setWithoutBarrier(context.vector());
 }
 
 void JSArrayBufferView::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
+    ASSERT(jsDynamicCast<JSArrayBufferView*>(vm, this));
     switch (m_mode) {
     case FastTypedArray:
         return;
@@ -130,33 +150,19 @@ 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)
-{
-    JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object);
-    
-    if (propertyName == exec->propertyNames().buffer) {
-        slot.setValue(
-            thisObject, DontDelete | ReadOnly, exec->vm().m_typedArrayController->toJS(
-                exec, thisObject->globalObject(), thisObject->buffer()));
-        return true;
-    }
-    
-    return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
-}
-
 void JSArrayBufferView::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell);
 
     if (thisObject->hasArrayBuffer()) {
-        ArrayBuffer* buffer = thisObject->buffer();
+        WTF::loadLoadFence();
+        ArrayBuffer* buffer = thisObject->possiblySharedBuffer();
         RELEASE_ASSERT(buffer);
         visitor.addOpaqueRoot(buffer);
     }
@@ -169,51 +175,44 @@ bool JSArrayBufferView::put(
     PutPropertySlot& slot)
 {
     JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell);
-    if (propertyName == exec->propertyNames().buffer)
-        return reject(exec, slot.isStrictMode(), "Attempting to write to read-only typed array property.");
+
+    if (UNLIKELY(isThisValueAltered(slot, thisObject)))
+        return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
     
     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().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)
+        Gigacage::free(Gigacage::Primitive, 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().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);
-    
-    if (mode.includeDontEnumProperties())
-        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.getWithoutBarrier());
+    RELEASE_ASSERT(hasArrayBuffer());
+    RELEASE_ASSERT(!isShared());
+    m_length = 0;
+    m_vector.clear();
 }
 
 } // namespace JSC