Title: [229053] trunk
Revision
229053
Author
[email protected]
Date
2018-02-26 23:32:14 -0800 (Mon, 26 Feb 2018)

Log Message

[FTL] Support PutByVal(ArrayStorage/SlowPutArrayStorage)
https://bugs.webkit.org/show_bug.cgi?id=182965

Reviewed by Saam Barati.

JSTests:

* stress/put-by-val-array-storage.js: Added.
(shouldBe):
(testArrayStorageInBounds):
* stress/put-by-val-direct-out-of-bounds-setter.js: Added.
(shouldBe):
(testInt32.createBuiltin):
(set for):
* stress/put-by-val-slow-put-array-storage.js: Added.
(shouldBe):
(testArrayStorageInBounds):

Source/_javascript_Core:

This patch extends FTL coverage for PutByVal by adding ArrayStorage and SlwoPutArrayStorage support.
Basically large part of the patch is porting from DFG code. Since PutByVal already emits CheckInBounds
for InBounds case, we do not have OutOfBounds check for that case.
This is the last change for FTL to support all the types of DFG nodes except for CreateThis.

* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileDoublePutByVal):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
(JSC::FTL::DFG::LowerDFGToB3::contiguousPutByValOutOfBounds):
For consistency, we use operationPutByValXXX and operationPutByValDirectXXX.
But except for SlowPutArrayStorage case, basically it is meaningless since
we do not have indexed accessors.

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (229052 => 229053)


--- trunk/JSTests/ChangeLog	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/JSTests/ChangeLog	2018-02-27 07:32:14 UTC (rev 229053)
@@ -1,3 +1,21 @@
+2018-02-25  Yusuke Suzuki  <[email protected]>
+
+        [FTL] Support PutByVal(ArrayStorage/SlowPutArrayStorage)
+        https://bugs.webkit.org/show_bug.cgi?id=182965
+
+        Reviewed by Saam Barati.
+
+        * stress/put-by-val-array-storage.js: Added.
+        (shouldBe):
+        (testArrayStorageInBounds):
+        * stress/put-by-val-direct-out-of-bounds-setter.js: Added.
+        (shouldBe):
+        (testInt32.createBuiltin):
+        (set for):
+        * stress/put-by-val-slow-put-array-storage.js: Added.
+        (shouldBe):
+        (testArrayStorageInBounds):
+
 2018-02-26  Saam Barati  <[email protected]>
 
         validateStackAccess should not validate if the offset is within the stack bounds

Added: trunk/JSTests/stress/put-by-val-array-storage.js (0 => 229053)


--- trunk/JSTests/stress/put-by-val-array-storage.js	                        (rev 0)
+++ trunk/JSTests/stress/put-by-val-array-storage.js	2018-02-27 07:32:14 UTC (rev 229053)
@@ -0,0 +1,40 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testArrayStorageInBounds(array, index, value)
+{
+    array[index] = value;
+}
+noInline(testArrayStorageInBounds);
+
+for (var i = 0; i < 1e5; ++i) {
+    var array = [1, 2, 3, 4, 5];
+    ensureArrayStorage(array);
+    shouldBe(array[0], 1);
+    testArrayStorageInBounds(array, 0, 42);
+    shouldBe(array[0], 42);
+}
+for (var i = 0; i < 1e5; ++i) {
+    var array = [, 2, 3, 4];
+    ensureArrayStorage(array);
+    shouldBe(array[0], undefined);
+    shouldBe(array[1], 2);
+    testArrayStorageInBounds(array, 0, 42);
+    testArrayStorageInBounds(array, 1, 40);
+    shouldBe(array[0], 42);
+    shouldBe(array[1], 40);
+    shouldBe(array.length, 4);
+    testArrayStorageInBounds(array, 4, 42);
+    shouldBe(array[4], 42);
+    shouldBe(array.length, 5);
+}
+for (var i = 0; i < 1e5; ++i) {
+    var array = [, 2, 3, 4];
+    ensureArrayStorage(array);
+    shouldBe(array[6], undefined);
+    testArrayStorageInBounds(array, 6, 42);
+    shouldBe(array.length, 7);
+    shouldBe(array[6], 42);
+}

Added: trunk/JSTests/stress/put-by-val-direct-out-of-bounds-setter.js (0 => 229053)


--- trunk/JSTests/stress/put-by-val-direct-out-of-bounds-setter.js	                        (rev 0)
+++ trunk/JSTests/stress/put-by-val-direct-out-of-bounds-setter.js	2018-02-27 07:32:14 UTC (rev 229053)
@@ -0,0 +1,26 @@
+var createBuiltin = $vm.createBuiltin;
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var testInt32 = createBuiltin(`(function (array, index, value) {
+    @putByValDirect(array, index, value);
+})`);
+noInline(testInt32);
+
+Object.defineProperty(Array.prototype, 42, {
+    get() {
+        return 30;
+    },
+    set(value) {
+    }
+});
+for (var i = 0; i < 1e5; ++i) {
+    var array = [1, 2, 3, 4, 5];
+    shouldBe(array[42], 30);
+    testInt32(array, 42, 42);
+    shouldBe(array[42], 42);
+    shouldBe(Array.prototype[42], 30);
+}

Added: trunk/JSTests/stress/put-by-val-slow-put-array-storage.js (0 => 229053)


--- trunk/JSTests/stress/put-by-val-slow-put-array-storage.js	                        (rev 0)
+++ trunk/JSTests/stress/put-by-val-slow-put-array-storage.js	2018-02-27 07:32:14 UTC (rev 229053)
@@ -0,0 +1,67 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testArrayStorageInBounds(array, index, value)
+{
+    array[index] = value;
+}
+noInline(testArrayStorageInBounds);
+
+for (var i = 0; i < 1e4; ++i) {
+    var array = [1, 2, 3, 4, 5];
+    var object = { a: 10 };
+    Object.defineProperties(object, {
+        "1": {
+            get: function() { return this.a; },
+            set: function(x) { this.a = x; },
+        },
+    });
+    array.__proto__ = object;
+    ensureArrayStorage(array);
+    shouldBe(array[0], 1);
+    testArrayStorageInBounds(array, 0, 42);
+    shouldBe(array[0], 42);
+}
+for (var i = 0; i < 1e4; ++i) {
+    var array = [, 2, 3, 4];
+    var object = { a: 10 };
+    Object.defineProperties(object, {
+        "1": {
+            get: function() { return this.a; },
+            set: function(x) { this.a = x + 20; },
+        },
+    });
+    array.__proto__ = object;
+    ensureArrayStorage(array);
+    shouldBe(array[0], undefined);
+    shouldBe(array[1], 2);
+    testArrayStorageInBounds(array, 0, 42);
+    testArrayStorageInBounds(array, 1, 40);
+    shouldBe(array[0], 42);
+    shouldBe(array[1], 40);
+    testArrayStorageInBounds(array, 4, 42);
+    shouldBe(array[4], 42);
+    shouldBe(array.length, 5);
+}
+for (var i = 0; i < 1e4; ++i) {
+    var array = [, , 3, 4];
+    var object = { a: 10 };
+    Object.defineProperties(object, {
+        "1": {
+            get: function() { return this.a; },
+            set: function(x) { this.a = x + 20; },
+        },
+    });
+    array.__proto__ = object;
+    ensureArrayStorage(array);
+    shouldBe(array[0], undefined);
+    shouldBe(array[1], 10);
+    shouldBe(array[6], undefined);
+    testArrayStorageInBounds(array, 6, 42);
+    testArrayStorageInBounds(array, 1, 42);
+    shouldBe(array.length, 7);
+    shouldBe(array[1], 62);
+    shouldBe(array[6], 42);
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (229052 => 229053)


--- trunk/Source/_javascript_Core/ChangeLog	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-02-27 07:32:14 UTC (rev 229053)
@@ -1,3 +1,30 @@
+2018-02-25  Yusuke Suzuki  <[email protected]>
+
+        [FTL] Support PutByVal(ArrayStorage/SlowPutArrayStorage)
+        https://bugs.webkit.org/show_bug.cgi?id=182965
+
+        Reviewed by Saam Barati.
+
+        This patch extends FTL coverage for PutByVal by adding ArrayStorage and SlwoPutArrayStorage support.
+        Basically large part of the patch is porting from DFG code. Since PutByVal already emits CheckInBounds
+        for InBounds case, we do not have OutOfBounds check for that case.
+        This is the last change for FTL to support all the types of DFG nodes except for CreateThis.
+
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileDoublePutByVal):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
+        (JSC::FTL::DFG::LowerDFGToB3::contiguousPutByValOutOfBounds):
+        For consistency, we use operationPutByValXXX and operationPutByValDirectXXX.
+        But except for SlowPutArrayStorage case, basically it is meaningless since
+        we do not have indexed accessors.
+
 2018-02-26  Saam Barati  <[email protected]>
 
         validateStackAccess should not validate if the offset is within the stack bounds

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (229052 => 229053)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2018-02-27 07:32:14 UTC (rev 229053)
@@ -743,37 +743,37 @@
     putByValCellInternal<false, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
 }
 
-void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
+void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
     
     if (index >= 0) {
-        array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
+        object->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
         return;
     }
     
-    PutPropertySlot slot(array, true);
-    array->methodTable(vm)->put(
-        array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
+    PutPropertySlot slot(object, true);
+    object->methodTable(vm)->put(
+        object, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
 }
 
-void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
+void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
     
     if (index >= 0) {
-        array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
+        object->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
         return;
     }
     
-    PutPropertySlot slot(array, false);
-    array->methodTable(*vm)->put(
-        array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
+    PutPropertySlot slot(object, false);
+    object->methodTable(*vm)->put(
+        object, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
 }
 
-void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
+void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, double value)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
@@ -781,16 +781,16 @@
     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
     
     if (index >= 0) {
-        array->putByIndexInline(exec, index, jsValue, true);
+        object->putByIndexInline(exec, index, jsValue, true);
         return;
     }
     
-    PutPropertySlot slot(array, true);
-    array->methodTable(*vm)->put(
-        array, exec, Identifier::from(exec, index), jsValue, slot);
+    PutPropertySlot slot(object, true);
+    object->methodTable(*vm)->put(
+        object, exec, Identifier::from(exec, index), jsValue, slot);
 }
 
-void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
+void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* object, int32_t index, double value)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
@@ -798,15 +798,47 @@
     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
     
     if (index >= 0) {
-        array->putByIndexInline(exec, index, jsValue, false);
+        object->putByIndexInline(exec, index, jsValue, false);
         return;
     }
     
-    PutPropertySlot slot(array, false);
-    array->methodTable(*vm)->put(
-        array, exec, Identifier::from(exec, index), jsValue, slot);
+    PutPropertySlot slot(object, false);
+    object->methodTable(*vm)->put(
+        object, exec, Identifier::from(exec, index), jsValue, slot);
 }
 
+void JIT_OPERATION operationPutDoubleByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, double value)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
+
+    if (index >= 0) {
+        object->putDirectIndex(exec, index, jsValue, 0, PutDirectIndexShouldThrow);
+        return;
+    }
+
+    PutPropertySlot slot(object, true);
+    object->putDirect(vm, Identifier::from(exec, index), jsValue, slot);
+}
+
+void JIT_OPERATION operationPutDoubleByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* object, int32_t index, double value)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
+
+    if (index >= 0) {
+        object->putDirectIndex(exec, index, jsValue);
+        return;
+    }
+
+    PutPropertySlot slot(object, false);
+    object->putDirect(vm, Identifier::from(exec, index), jsValue, slot);
+}
+
 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
 {
     VM& vm = exec->vm();
@@ -871,31 +903,31 @@
     putByValCellInternal<false, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
 }
 
-void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
+void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
     if (index >= 0) {
-        array->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
+        object->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
         return;
     }
     
-    PutPropertySlot slot(array, true);
-    array->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
+    PutPropertySlot slot(object, true);
+    object->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
 }
 
-void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
+void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
     
     if (index >= 0) {
-        array->putDirectIndex(exec, index, JSValue::decode(encodedValue));
+        object->putDirectIndex(exec, index, JSValue::decode(encodedValue));
         return;
     }
     
-    PutPropertySlot slot(array, false);
-    array->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
+    PutPropertySlot slot(object, false);
+    object->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
 }
 
 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (229052 => 229053)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2018-02-27 07:32:14 UTC (rev 229053)
@@ -131,6 +131,8 @@
 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState*, JSObject*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL;
 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState*, JSObject*, int32_t index, double value) WTF_INTERNAL;
 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState*, JSObject*, int32_t index, double value) WTF_INTERNAL;
+void JIT_OPERATION operationPutDoubleByValDirectBeyondArrayBoundsStrict(ExecState*, JSObject*, int32_t index, double value) WTF_INTERNAL;
+void JIT_OPERATION operationPutDoubleByValDirectBeyondArrayBoundsNonStrict(ExecState*, JSObject*, int32_t index, double value) WTF_INTERNAL;
 void JIT_OPERATION operationPutByIdWithThis(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
 void JIT_OPERATION operationPutByIdWithThisStrict(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
 void JIT_OPERATION operationPutByValWithThis(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (229052 => 229053)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2018-02-27 07:32:14 UTC (rev 229053)
@@ -2079,7 +2079,9 @@
         addSlowPathGenerator(
             slowPathCall(
                 slowCase, this,
-                m_jit.codeBlock()->isStrictMode() ? operationPutDoubleByValBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict,
+                m_jit.codeBlock()->isStrictMode()
+                    ? (node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsStrict)
+                    : (node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsNonStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict),
                 NoResult, baseReg, propertyReg, valueReg));
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (229052 => 229053)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2018-02-27 07:32:14 UTC (rev 229053)
@@ -3070,17 +3070,12 @@
             storage.use();
             
             if (arrayMode.isOutOfBounds()) {
-                if (node->op() == PutByValDirect) {
-                    addSlowPathGenerator(slowPathCall(
-                        slowCase, this,
-                        m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
-                        NoResult, baseReg, propertyReg, valueReg));
-                } else {
-                    addSlowPathGenerator(slowPathCall(
-                        slowCase, this,
-                        m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
-                        NoResult, baseReg, propertyReg, valueReg));
-                }
+                addSlowPathGenerator(slowPathCall(
+                    slowCase, this,
+                    m_jit.codeBlock()->isStrictMode()
+                        ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
+                        : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
+                    NoResult, baseReg, propertyReg, valueReg));
             }
 
             noResult(node, UseChildrenCalledExplicitly);
@@ -3159,17 +3154,12 @@
             storage.use();
             
             if (!slowCases.empty()) {
-                if (node->op() == PutByValDirect) {
-                    addSlowPathGenerator(slowPathCall(
-                        slowCases, this,
-                        m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
-                        NoResult, baseReg, propertyReg, valueReg));
-                } else {
-                    addSlowPathGenerator(slowPathCall(
-                        slowCases, this,
-                        m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
-                        NoResult, baseReg, propertyReg, valueReg));
-                }
+                addSlowPathGenerator(slowPathCall(
+                    slowCases, this,
+                    m_jit.codeBlock()->isStrictMode()
+                        ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
+                        : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
+                    NoResult, baseReg, propertyReg, valueReg));
             }
 
             noResult(node, UseChildrenCalledExplicitly);

Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.cpp (229052 => 229053)


--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.cpp	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.cpp	2018-02-27 07:32:14 UTC (rev 229053)
@@ -59,6 +59,8 @@
 #undef ABSTRACT_FIELD_INITIALIZATION
     
     , JSCell_freeListNext(JSCell_header)
+    , ArrayStorage_publicLength(Butterfly_publicLength)
+    , ArrayStorage_vectorLength(Butterfly_vectorLength)
     
 #define INDEXED_ABSTRACT_HEAP_INITIALIZATION(name, offset, size) , name(&root, #name, offset, size)
     FOR_EACH_INDEXED_ABSTRACT_HEAP(INDEXED_ABSTRACT_HEAP_INITIALIZATION)

Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (229052 => 229053)


--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2018-02-27 07:32:14 UTC (rev 229053)
@@ -175,6 +175,8 @@
 #undef ABSTRACT_FIELD_DECLARATION
     
     AbstractHeap& JSCell_freeListNext;
+    AbstractHeap& ArrayStorage_publicLength;
+    AbstractHeap& ArrayStorage_vectorLength;
     
 #define INDEXED_ABSTRACT_HEAP_DECLARATION(name, offset, size) IndexedAbstractHeap name;
     FOR_EACH_INDEXED_ABSTRACT_HEAP(INDEXED_ABSTRACT_HEAP_DECLARATION)

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (229052 => 229053)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2018-02-27 07:32:14 UTC (rev 229053)
@@ -420,6 +420,8 @@
         case Array::Int32:
         case Array::Double:
         case Array::Contiguous:
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage:
             break;
         default:
             if (isTypedView(node->arrayMode().typedArrayType()))

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (229052 => 229053)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2018-02-27 03:02:39 UTC (rev 229052)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2018-02-27 07:32:14 UTC (rev 229053)
@@ -3650,7 +3650,7 @@
 
         case Array::ArrayStorage:
         case Array::SlowPutArrayStorage: {
-            LValue length = m_out.load32(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength);
+            LValue length = m_out.load32(lowStorage(m_node->child2()), m_heaps.ArrayStorage_publicLength);
             speculate(Uncountable, noValue(), nullptr, m_out.lessThan(length, m_out.int32Zero));
             setInt32(length);
             return;
@@ -3697,7 +3697,7 @@
         switch (m_node->arrayMode().type()) {
         case Array::ArrayStorage:
         case Array::SlowPutArrayStorage:
-            setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.Butterfly_vectorLength));
+            setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.ArrayStorage_vectorLength));
             return;
         default:
             return;
@@ -3964,7 +3964,7 @@
             LBasicBlock continuation = m_out.newBlock();
 
             m_out.branch(
-                m_out.aboveOrEqual(index, m_out.load32NonNegative(storage, m_heaps.Butterfly_vectorLength)),
+                m_out.aboveOrEqual(index, m_out.load32NonNegative(storage, m_heaps.ArrayStorage_vectorLength)),
                 rarely(slowCase), usually(inBounds));
 
             LBasicBlock lastNext = m_out.appendTo(inBounds, slowCase);
@@ -4195,8 +4195,8 @@
                 
                 contiguousPutByValOutOfBounds(
                     codeBlock()->isStrictMode()
-                    ? operationPutByValBeyondArrayBoundsStrict
-                    : operationPutByValBeyondArrayBoundsNonStrict,
+                        ? (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
+                        : (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
                     base, storage, index, value, continuation);
                 
                 m_out.store64(value, elementPointer);
@@ -4221,8 +4221,8 @@
                 
                 contiguousPutByValOutOfBounds(
                     codeBlock()->isStrictMode()
-                    ? operationPutDoubleByValBeyondArrayBoundsStrict
-                    : operationPutDoubleByValBeyondArrayBoundsNonStrict,
+                        ? (m_node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsStrict)
+                        : (m_node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsNonStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict),
                     base, storage, index, value, continuation);
                 
                 m_out.storeDouble(value, elementPointer);
@@ -4237,8 +4237,85 @@
             m_out.appendTo(continuation, outerLastNext);
             return;
         }
+
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage: {
+            LValue value = lowJSValue(child3);
+
+            TypedPointer elementPointer = m_out.baseIndex(
+                m_heaps.ArrayStorage_vector, storage, m_out.zeroExtPtr(index),
+                provenValue(child2));
+
+            if (m_node->op() == PutByValAlias) {
+                m_out.store64(value, elementPointer);
+                return;
+            }
+
+            if (m_node->arrayMode().isInBounds()) {
+                speculate(StoreToHole, noValue(), 0, m_out.isZero64(m_out.load64(elementPointer)));
+                m_out.store64(value, elementPointer);
+                return;
+            }
+
+            LValue isOutOfBounds = m_out.aboveOrEqual(
+                index, m_out.load32NonNegative(storage, m_heaps.ArrayStorage_vectorLength));
+
+            auto slowPathFunction = codeBlock()->isStrictMode()
+                ? (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
+                : (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict);
+            if (!m_node->arrayMode().isOutOfBounds()) {
+                speculate(OutOfBounds, noValue(), 0, isOutOfBounds);
+                isOutOfBounds = m_out.booleanFalse;
+            }
+
+            LBasicBlock inBoundCase = m_out.newBlock();
+            LBasicBlock slowCase = m_out.newBlock();
+            LBasicBlock holeCase = m_out.newBlock();
+            LBasicBlock doStoreCase = m_out.newBlock();
+            LBasicBlock lengthUpdateCase = m_out.newBlock();
+            LBasicBlock continuation = m_out.newBlock();
+
+            m_out.branch(isOutOfBounds, rarely(slowCase), usually(inBoundCase));
+
+            LBasicBlock lastNext = m_out.appendTo(slowCase, inBoundCase);
+            vmCall(
+                Void, m_out.operation(slowPathFunction),
+                m_callFrame, base, index, value);
+            m_out.jump(continuation);
+
+
+            if (m_node->arrayMode().isSlowPut()) {
+                m_out.appendTo(inBoundCase, doStoreCase);
+                m_out.branch(m_out.isZero64(m_out.load64(elementPointer)), rarely(slowCase), usually(doStoreCase));
+            } else {
+                m_out.appendTo(inBoundCase, holeCase);
+                m_out.branch(m_out.isZero64(m_out.load64(elementPointer)), rarely(holeCase), usually(doStoreCase));
+
+                m_out.appendTo(holeCase, lengthUpdateCase);
+                m_out.store32(
+                    m_out.add(m_out.load32(storage, m_heaps.ArrayStorage_numValuesInVector), m_out.int32One),
+                    storage, m_heaps.ArrayStorage_numValuesInVector);
+                m_out.branch(
+                    m_out.below(
+                        index, m_out.load32NonNegative(storage, m_heaps.ArrayStorage_publicLength)),
+                    unsure(doStoreCase), unsure(lengthUpdateCase));
+
+                m_out.appendTo(lengthUpdateCase, doStoreCase);
+                m_out.store32(
+                    m_out.add(index, m_out.int32One),
+                    storage, m_heaps.ArrayStorage_publicLength);
+                m_out.jump(doStoreCase);
+            }
+
+            m_out.appendTo(doStoreCase, continuation);
+            m_out.store64(value, elementPointer);
+            m_out.jump(continuation);
+
+            m_out.appendTo(continuation, lastNext);
+            return;
+        }
             
-        default:
+        default: {
             TypedArrayType type = m_node->arrayMode().typedArrayType();
             
             if (isTypedView(type)) {
@@ -4298,6 +4375,7 @@
             DFG_CRASH(m_graph, m_node, "Bad array type");
             break;
         }
+        }
     }
 
     void compilePutAccessorById()
@@ -4482,7 +4560,7 @@
             // This ensures that the result of ArrayPush is Int32 in AI.
             int32_t largestPositiveInt32Length = 0x7fffffff - elementCount;
 
-            LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
+            LValue prevLength = m_out.load32(storage, m_heaps.ArrayStorage_publicLength);
             // Refuse to handle bizarre lengths.
             speculate(Uncountable, noValue(), nullptr, m_out.above(prevLength, m_out.constInt32(largestPositiveInt32Length)));
 
@@ -4497,7 +4575,7 @@
 
                 m_out.branch(
                     m_out.aboveOrEqual(
-                        prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
+                        prevLength, m_out.load32(storage, m_heaps.ArrayStorage_vectorLength)),
                     rarely(slowPath), usually(fastPath));
 
                 LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
@@ -4504,7 +4582,7 @@
                 m_out.store64(
                     value, m_out.baseIndex(m_heaps.ArrayStorage_vector, storage, m_out.zeroExtPtr(prevLength)));
                 LValue newLength = m_out.add(prevLength, m_out.int32One);
-                m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
+                m_out.store32(newLength, storage, m_heaps.ArrayStorage_publicLength);
                 m_out.store32(
                     m_out.add(m_out.load32(storage, m_heaps.ArrayStorage_numValuesInVector), m_out.int32One),
                     storage, m_heaps.ArrayStorage_numValuesInVector);
@@ -4530,12 +4608,12 @@
             LBasicBlock slowCallPath = m_out.newBlock();
             LBasicBlock continuation = m_out.newBlock();
 
-            LValue beyondVectorLength = m_out.above(newLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength));
+            LValue beyondVectorLength = m_out.above(newLength, m_out.load32(storage, m_heaps.ArrayStorage_vectorLength));
 
             m_out.branch(beyondVectorLength, rarely(slowPath), usually(fastPath));
 
             LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
-            m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
+            m_out.store32(newLength, storage, m_heaps.ArrayStorage_publicLength);
             m_out.store32(
                 m_out.add(m_out.load32(storage, m_heaps.ArrayStorage_numValuesInVector), m_out.constInt32(elementCount)),
                 storage, m_heaps.ArrayStorage_numValuesInVector);
@@ -4852,7 +4930,7 @@
             LBasicBlock slowCase = m_out.newBlock();
             LBasicBlock continuation = m_out.newBlock();
 
-            LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
+            LValue prevLength = m_out.load32(storage, m_heaps.ArrayStorage_publicLength);
 
             Vector<ValueFromBlock, 3> results;
             results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
@@ -4862,7 +4940,7 @@
             LBasicBlock lastNext = m_out.appendTo(vectorLengthCheckCase, popCheckCase);
             LValue newLength = m_out.sub(prevLength, m_out.int32One);
             m_out.branch(
-                m_out.aboveOrEqual(newLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)), rarely(slowCase), usually(popCheckCase));
+                m_out.aboveOrEqual(newLength, m_out.load32(storage, m_heaps.ArrayStorage_vectorLength)), rarely(slowCase), usually(popCheckCase));
 
             m_out.appendTo(popCheckCase, fastCase);
             TypedPointer pointer = m_out.baseIndex(m_heaps.ArrayStorage_vector, storage, m_out.zeroExtPtr(newLength));
@@ -4870,7 +4948,7 @@
             m_out.branch(m_out.notZero64(result), usually(fastCase), rarely(slowCase));
 
             m_out.appendTo(fastCase, slowCase);
-            m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
+            m_out.store32(newLength, storage, m_heaps.ArrayStorage_publicLength);
             m_out.store64(m_out.int64Zero, pointer);
             m_out.store32(
                 m_out.sub(m_out.load32(storage, m_heaps.ArrayStorage_numValuesInVector), m_out.int32One),
@@ -9968,7 +10046,7 @@
                 LBasicBlock checkHole = m_out.newBlock();
                 m_out.branch(
                     m_out.aboveOrEqual(
-                        index, m_out.load32NonNegative(storage, m_heaps.Butterfly_vectorLength)),
+                        index, m_out.load32NonNegative(storage, m_heaps.ArrayStorage_vectorLength)),
                     rarely(slowCase), usually(checkHole));
                 lastNext = m_out.appendTo(checkHole, slowCase);
             } else
@@ -13000,8 +13078,6 @@
         FunctionType slowPathFunction, LValue base, LValue storage, LValue index, LValue value,
         LBasicBlock continuation)
     {
-        LValue isNotInBounds = m_out.aboveOrEqual(
-            index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength));
         if (!m_node->arrayMode().isInBounds()) {
             LBasicBlock notInBoundsCase =
                 m_out.newBlock();
@@ -13008,6 +13084,8 @@
             LBasicBlock performStore =
                 m_out.newBlock();
                 
+            LValue isNotInBounds = m_out.aboveOrEqual(
+                index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength));
             m_out.branch(isNotInBounds, unsure(notInBoundsCase), unsure(performStore));
                 
             LBasicBlock lastNext = m_out.appendTo(notInBoundsCase, performStore);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to