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);