Diff
Modified: trunk/JSTests/ChangeLog (222657 => 222658)
--- trunk/JSTests/ChangeLog 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/ChangeLog 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,3 +1,25 @@
+2017-09-29 Commit Queue <[email protected]>
+
+ Unreviewed, rolling out r222563, r222565, and r222581.
+ https://bugs.webkit.org/show_bug.cgi?id=177675
+
+ "It causes a crash when playing youtube videos" (Requested by
+ saamyjoon on #webkit).
+
+ Reverted changesets:
+
+ "[DFG] Support ArrayPush with multiple args"
+ https://bugs.webkit.org/show_bug.cgi?id=175823
+ http://trac.webkit.org/changeset/222563
+
+ "Unreviewed, build fix after r222563"
+ https://bugs.webkit.org/show_bug.cgi?id=175823
+ http://trac.webkit.org/changeset/222565
+
+ "Unreviewed, fix x86 breaking due to exhausted registers"
+ https://bugs.webkit.org/show_bug.cgi?id=175823
+ http://trac.webkit.org/changeset/222581
+
2017-09-28 Mark Lam <[email protected]>
test262: Unexpected passes after r222617 and r222618.
Deleted: trunk/JSTests/microbenchmarks/array-push-0.js (222657 => 222658)
--- trunk/JSTests/microbenchmarks/array-push-0.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/microbenchmarks/array-push-0.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,9 +0,0 @@
-function arrayPush0() {
- var ret = [1];
- ret.push();
- return ret;
-}
-noInline(arrayPush0);
-
-for (var i = 0; i < 1e7; ++i)
- arrayPush0();
Deleted: trunk/JSTests/microbenchmarks/array-push-1.js (222657 => 222658)
--- trunk/JSTests/microbenchmarks/array-push-1.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/microbenchmarks/array-push-1.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,9 +0,0 @@
-function arrayPush1() {
- var ret = [1];
- ret.push(1);
- return ret;
-}
-noInline(arrayPush1);
-
-for (var i = 0; i < 1e7; ++i)
- arrayPush1();
Deleted: trunk/JSTests/microbenchmarks/array-push-2.js (222657 => 222658)
--- trunk/JSTests/microbenchmarks/array-push-2.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/microbenchmarks/array-push-2.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,9 +0,0 @@
-function arrayPush2() {
- var ret = [1];
- ret.push(1, 2);
- return ret;
-}
-noInline(arrayPush2);
-
-for (var i = 0; i < 1e7; ++i)
- arrayPush2();
Deleted: trunk/JSTests/microbenchmarks/array-push-3.js (222657 => 222658)
--- trunk/JSTests/microbenchmarks/array-push-3.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/microbenchmarks/array-push-3.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,9 +0,0 @@
-function arrayPush3() {
- var ret = [1];
- ret.push(1, 2, 3);
- return ret;
-}
-noInline(arrayPush3);
-
-for (var i = 0; i < 1e7; ++i)
- arrayPush3();
Deleted: trunk/JSTests/stress/array-push-multiple-contiguous.js (222657 => 222658)
--- trunk/JSTests/stress/array-push-multiple-contiguous.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/stress/array-push-multiple-contiguous.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,19 +0,0 @@
-function shouldBe(actual, expected)
-{
- if (actual !== expected)
- throw new Error('bad value: ' + actual);
-}
-
-function test(array, val1, val2, val3)
-{
- return array.push(val1, val2, val3);
-}
-noInline(test);
-
-for (var i = 0; i < 1e5; ++i) {
- var array = [];
- shouldBe(test(array, "Cocoa", "Cappuccino", "Matcha"), 3);
- shouldBe(array[0], "Cocoa");
- shouldBe(array[1], "Cappuccino");
- shouldBe(array[2], "Matcha");
-}
Deleted: trunk/JSTests/stress/array-push-multiple-double-nan.js (222657 => 222658)
--- trunk/JSTests/stress/array-push-multiple-double-nan.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/stress/array-push-multiple-double-nan.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,25 +0,0 @@
-function shouldBe(actual, expected)
-{
- if (actual !== expected)
- throw new Error('bad value: ' + actual);
-}
-
-function test(array, val1, val2, val3)
-{
- return array.push(val1, val2, val3);
-}
-noInline(test);
-
-for (var i = 0; i < 1e5; ++i) {
- var array = [];
- var value = 3.3;
- if (i === 1e5 - 1)
- value = NaN;
- shouldBe(test(array, 1.1, 2.2, value), 3);
- shouldBe(array[0], 1.1);
- shouldBe(array[1], 2.2);
- if (i === 1e5 - 1)
- shouldBe(Number.isNaN(array[2]), true);
- else
- shouldBe(array[2], 3.3);
-}
Deleted: trunk/JSTests/stress/array-push-multiple-double.js (222657 => 222658)
--- trunk/JSTests/stress/array-push-multiple-double.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/stress/array-push-multiple-double.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,32 +0,0 @@
-function shouldBe(actual, expected)
-{
- if (actual !== expected)
- throw new Error('bad value: ' + actual);
-}
-
-function test(array, val1, val2, val3)
-{
- return array.push(val1, val2, val3);
-}
-noInline(test);
-
-for (var i = 0; i < 1e5; ++i) {
- var array = [];
- shouldBe(test(array, 1.1, 2.2, 3.3), 3);
- shouldBe(array[0], 1.1);
- shouldBe(array[1], 2.2);
- shouldBe(array[2], 3.3);
-}
-
-for (var i = 0; i < 1e5; ++i) {
- var array = [];
- shouldBe(test(array, 1.1, 2.2, 4), 3);
- shouldBe(array[0], 1.1);
- shouldBe(array[1], 2.2);
- shouldBe(array[2], 4);
-}
-var array = [];
-shouldBe(test(array, 1.1, 2.2, "String"), 3);
-shouldBe(array[0], 1.1);
-shouldBe(array[1], 2.2);
-shouldBe(array[2], "String");
Deleted: trunk/JSTests/stress/array-push-multiple-int32.js (222657 => 222658)
--- trunk/JSTests/stress/array-push-multiple-int32.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/stress/array-push-multiple-int32.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,24 +0,0 @@
-function shouldBe(actual, expected)
-{
- if (actual !== expected)
- throw new Error('bad value: ' + actual);
-}
-
-function test(array, val1, val2, val3)
-{
- return array.push(val1, val2, val3);
-}
-noInline(test);
-
-for (var i = 0; i < 1e7; ++i) {
- var array = [];
- shouldBe(test(array, 1, 2, 3), 3);
- shouldBe(array[0], 1);
- shouldBe(array[1], 2);
- shouldBe(array[2], 3);
-}
-var array = [];
-shouldBe(test(array, 1, 2, 3.3), 3);
-shouldBe(array[0], 1);
-shouldBe(array[1], 2);
-shouldBe(array[2], 3.3);
Deleted: trunk/JSTests/stress/array-push-multiple-many-contiguous.js (222657 => 222658)
--- trunk/JSTests/stress/array-push-multiple-many-contiguous.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/stress/array-push-multiple-many-contiguous.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,20 +0,0 @@
-function shouldBe(actual, expected)
-{
- if (actual !== expected)
- throw new Error('bad value: ' + actual);
-}
-
-function test(array, val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12)
-{
- return array.push(val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12);
-}
-noInline(test);
-
-var values = [ "AB", "BC", "CD", "DE", "EF", "FG", "GH", "HI", "IJ", "JK", "KL", "LM" ];
-shouldBe(values.length, 12);
-for (var i = 0; i < 1e5; ++i) {
- var array = [];
- shouldBe(test(array, values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11]), 12);
- for (var j = 0; j < values.length; ++j)
- shouldBe(array[j], values[j]);
-}
Deleted: trunk/JSTests/stress/array-push-multiple-many-double.js (222657 => 222658)
--- trunk/JSTests/stress/array-push-multiple-many-double.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/stress/array-push-multiple-many-double.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,20 +0,0 @@
-function shouldBe(actual, expected)
-{
- if (actual !== expected)
- throw new Error('bad value: ' + actual);
-}
-
-function test(array, val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12)
-{
- return array.push(val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12);
-}
-noInline(test);
-
-var values = [ 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2 ];
-shouldBe(values.length, 12);
-for (var i = 0; i < 1e5; ++i) {
- var array = [];
- shouldBe(test(array, values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11]), 12);
- for (var j = 0; j < values.length; ++j)
- shouldBe(array[j], values[j]);
-}
Deleted: trunk/JSTests/stress/array-push-multiple-many-int32.js (222657 => 222658)
--- trunk/JSTests/stress/array-push-multiple-many-int32.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/stress/array-push-multiple-many-int32.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,20 +0,0 @@
-function shouldBe(actual, expected)
-{
- if (actual !== expected)
- throw new Error('bad value: ' + actual);
-}
-
-function test(array, val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12)
-{
- return array.push(val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12);
-}
-noInline(test);
-
-var values = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ];
-shouldBe(values.length, 12);
-for (var i = 0; i < 1e5; ++i) {
- var array = [];
- shouldBe(test(array, values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11]), 12);
- for (var j = 0; j < values.length; ++j)
- shouldBe(array[j], values[j]);
-}
Deleted: trunk/JSTests/stress/array-push-multiple-many-storage.js (222657 => 222658)
--- trunk/JSTests/stress/array-push-multiple-many-storage.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/stress/array-push-multiple-many-storage.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,21 +0,0 @@
-function shouldBe(actual, expected)
-{
- if (actual !== expected)
- throw new Error('bad value: ' + actual);
-}
-
-function test(array, val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12)
-{
- return array.push(val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12);
-}
-noInline(test);
-
-var values = [ "AB", "BC", "CD", "DE", "EF", "FG", "GH", "HI", "IJ", "JK", "KL", "LM" ];
-shouldBe(values.length, 12);
-for (var i = 0; i < 1e5; ++i) {
- var array = [];
- ensureArrayStorage(array);
- shouldBe(test(array, values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11]), 12);
- for (var j = 0; j < values.length; ++j)
- shouldBe(array[j], values[j]);
-}
Deleted: trunk/JSTests/stress/array-push-multiple-storage.js (222657 => 222658)
--- trunk/JSTests/stress/array-push-multiple-storage.js 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/JSTests/stress/array-push-multiple-storage.js 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,29 +0,0 @@
-function shouldBe(actual, expected)
-{
- if (actual !== expected)
- throw new Error('bad value: ' + actual);
-}
-
-function test(array, val1, val2, val3)
-{
- return array.push(val1, val2, val3);
-}
-noInline(test);
-
-for (var i = 0; i < 1e5; ++i) {
- var array = [];
- ensureArrayStorage(array);
- shouldBe(test(array, "Cocoa", "Cappuccino", "Matcha"), 3);
- shouldBe(array[0], "Cocoa");
- shouldBe(array[1], "Cappuccino");
- shouldBe(array[2], "Matcha");
-}
-for (var i = 0; i < 1e5; ++i) {
- var array = [0];
- ensureArrayStorage(array);
- shouldBe(test(array, "Cocoa", "Cappuccino", "Matcha"), 4);
- shouldBe(array[0], 0);
- shouldBe(array[1], "Cocoa");
- shouldBe(array[2], "Cappuccino");
- shouldBe(array[3], "Matcha");
-}
Modified: trunk/Source/_javascript_Core/ChangeLog (222657 => 222658)
--- trunk/Source/_javascript_Core/ChangeLog 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1,5 +1,27 @@
2017-09-29 Commit Queue <[email protected]>
+ Unreviewed, rolling out r222563, r222565, and r222581.
+ https://bugs.webkit.org/show_bug.cgi?id=177675
+
+ "It causes a crash when playing youtube videos" (Requested by
+ saamyjoon on #webkit).
+
+ Reverted changesets:
+
+ "[DFG] Support ArrayPush with multiple args"
+ https://bugs.webkit.org/show_bug.cgi?id=175823
+ http://trac.webkit.org/changeset/222563
+
+ "Unreviewed, build fix after r222563"
+ https://bugs.webkit.org/show_bug.cgi?id=175823
+ http://trac.webkit.org/changeset/222565
+
+ "Unreviewed, fix x86 breaking due to exhausted registers"
+ https://bugs.webkit.org/show_bug.cgi?id=175823
+ http://trac.webkit.org/changeset/222581
+
+2017-09-29 Commit Queue <[email protected]>
+
Unreviewed, rolling out r222625.
https://bugs.webkit.org/show_bug.cgi?id=177664
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -2334,14 +2334,7 @@
}
case ArrayPushIntrinsic: {
-#if USE(JSVALUE32_64)
- if (isX86() || isMIPS()) {
- if (argumentCountIncludingThis > 2)
- return false;
- }
-#endif
-
- if (static_cast<unsigned>(argumentCountIncludingThis) >= MIN_SPARSE_ARRAY_INDEX)
+ if (argumentCountIncludingThis != 2)
return false;
ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
@@ -2353,11 +2346,7 @@
case Array::Contiguous:
case Array::ArrayStorage: {
insertChecks();
-
- addVarArgChild(nullptr); // For storage.
- for (int i = 0; i < argumentCountIncludingThis; ++i)
- addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
- Node* arrayPush = addToGraph(Node::VarArg, ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction));
+ Node* arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
set(VirtualRegister(resultOperand), arrayPush);
return true;
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1008,54 +1008,29 @@
// ignored. That's because ArrayPush can't handle any array modes that aren't
// array-related - so if refine() turned this into a "Generic" ArrayPush then
// that would break things.
- Edge& storageEdge = m_graph.varArgChild(node, 0);
- Edge& arrayEdge = m_graph.varArgChild(node, 1);
- unsigned elementOffset = 2;
- unsigned elementCount = node->numChildren() - elementOffset;
- for (unsigned i = 0; i < elementCount; ++i) {
- Edge& element = m_graph.varArgChild(node, i + elementOffset);
- node->setArrayMode(
- node->arrayMode().refine(
- m_graph, node,
- arrayEdge->prediction() & SpecCell,
- SpecInt32Only,
- element->prediction()));
- }
- blessArrayOperation(arrayEdge, Edge(), storageEdge);
- fixEdge<KnownCellUse>(arrayEdge);
-
- // Convert `array.push()` to GetArrayLength.
- ASSERT(node->arrayMode().supportsSelfLength());
- if (!elementCount) {
- node->setOpAndDefaultFlags(GetArrayLength);
- node->child1() = arrayEdge;
- node->child2() = storageEdge;
- fixEdge<KnownCellUse>(node->child1());
+ node->setArrayMode(
+ node->arrayMode().refine(
+ m_graph, node,
+ node->child1()->prediction() & SpecCell,
+ SpecInt32Only,
+ node->child2()->prediction()));
+ blessArrayOperation(node->child1(), Edge(), node->child3());
+ fixEdge<KnownCellUse>(node->child1());
+
+ switch (node->arrayMode().type()) {
+ case Array::Int32:
+ fixEdge<Int32Use>(node->child2());
break;
+ case Array::Double:
+ fixEdge<DoubleRepRealUse>(node->child2());
+ break;
+ case Array::Contiguous:
+ case Array::ArrayStorage:
+ speculateForBarrier(node->child2());
+ break;
+ default:
+ break;
}
-
- // We do not want to perform osr exit and retry for ArrayPush. We insert Check with appropriate type,
- // and ArrayPush uses the edge as known typed edge. Therefore, ArrayPush do not need to perform type checks.
- for (unsigned i = 0; i < elementCount; ++i) {
- Edge& element = m_graph.varArgChild(node, i + elementOffset);
- switch (node->arrayMode().type()) {
- case Array::Int32:
- insertCheck<Int32Use>(element.node());
- fixEdge<KnownInt32Use>(element);
- break;
- case Array::Double:
- insertCheck<DoubleRepRealUse>(element.node());
- fixEdge<DoubleRepUse>(element);
- break;
- case Array::Contiguous:
- case Array::ArrayStorage:
- speculateForBarrier(element);
- break;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
- ASSERT(shouldNotHaveTypeCheck(element.useKind()));
- }
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2017-09-29 18:49:37 UTC (rev 222658)
@@ -265,7 +265,7 @@
macro(AtomicsXor, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
\
/* Optimizations for array mutation. */\
- macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
+ macro(ArrayPush, NodeResultJS | NodeMustGenerate) \
macro(ArrayPop, NodeResultJS | NodeMustGenerate) \
macro(ArraySlice, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
macro(ArrayIndexOf, NodeResultInt32 | NodeHasVarArgs) \
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -869,7 +869,7 @@
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- array->pushInline(exec, JSValue::decode(encodedValue));
+ array->push(exec, JSValue::decode(encodedValue));
return JSValue::encode(jsNumber(array->length()));
}
@@ -878,54 +878,10 @@
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, value));
+ array->push(exec, JSValue(JSValue::EncodeAsDouble, value));
return JSValue::encode(jsNumber(array->length()));
}
-EncodedJSValue JIT_OPERATION operationArrayPushMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- // We assume that multiple JSArray::push calls with ArrayWithInt32/ArrayWithContiguous do not cause JS traps.
- // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
- // content of ScratchBuffer. If the IndexingType is now ArrayWithInt32/ArrayWithContiguous, we can ensure
- // that there is no indexed accessors in this object and its prototype chain.
- //
- // ArrayWithArrayStorage is also OK. It can have indexed accessors. But if you define an indexed accessor, the array's length
- // becomes larger than that index. So Array#push never overlaps with this accessor. So accessors are never called unless
- // the IndexingType is ArrayWithSlowPutArrayStorage which could have an indexed accessor in a prototype chain.
- RELEASE_ASSERT(!shouldUseSlowPut(array->indexingType()));
-
- EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
- for (int32_t i = 0; i < elementCount; ++i) {
- array->pushInline(exec, JSValue::decode(values[i]));
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- }
- return JSValue::encode(jsNumber(array->length()));
-}
-
-EncodedJSValue JIT_OPERATION operationArrayPushDoubleMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- // We assume that multiple JSArray::push calls with ArrayWithDouble do not cause JS traps.
- // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
- // content of ScratchBuffer. If the IndexingType is now ArrayWithDouble, we can ensure
- // that there is no indexed accessors in this object and its prototype chain.
- ASSERT(array->indexingType() == ArrayWithDouble);
-
- double* values = static_cast<double*>(buffer);
- for (int32_t i = 0; i < elementCount; ++i) {
- array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, values[i]));
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- }
- return JSValue::encode(jsNumber(array->length()));
-}
-
EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
{
VM* vm = &exec->vm();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2017-09-29 18:49:37 UTC (rev 222658)
@@ -136,9 +136,7 @@
void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState*, JSObject*, UniquedStringImpl*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState*, JSObject*, Symbol*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationArrayPushMultiple(ExecState*, JSArray*, void* buffer, int32_t elementCount) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState*, double value, JSArray*) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationArrayPushDoubleMultiple(ExecState*, JSArray*, void* buffer, int32_t elementCount) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationArrayPop(ExecState*, JSArray*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState*, JSArray*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState*, JSGlobalObject*, RegExpObject*, JSString*) WTF_INTERNAL;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -7871,278 +7871,6 @@
}
}
-void SpeculativeJIT::compileArrayPush(Node* node)
-{
- ASSERT(node->arrayMode().isJSArray());
-
- Edge& storageEdge = m_jit.graph().varArgChild(node, 0);
- Edge& arrayEdge = m_jit.graph().varArgChild(node, 1);
-
- SpeculateCellOperand base(this, arrayEdge);
- GPRTemporary storageLength(this);
-
- GPRReg baseGPR = base.gpr();
- GPRReg storageLengthGPR = storageLength.gpr();
-
- StorageOperand storage(this, storageEdge);
- GPRReg storageGPR = storage.gpr();
- unsigned elementOffset = 2;
- unsigned elementCount = node->numChildren() - elementOffset;
-
-#if USE(JSVALUE32_64)
- GPRTemporary tag(this);
- GPRReg tagGPR = tag.gpr();
- JSValueRegs resultRegs { tagGPR, storageLengthGPR };
-#else
- JSValueRegs resultRegs { storageLengthGPR };
-#endif
-
- auto getStorageBufferAddress = [&] (GPRReg storageGPR, GPRReg indexGPR, int32_t offset, GPRReg bufferGPR) {
-#if USE(JSVALUE32_64)
- static_assert(sizeof(JSValue) == 8 && 1 << 3 == 8, "This is strongly assumed in the code below.");
- m_jit.move(indexGPR, bufferGPR);
- m_jit.lshift32(TrustedImm32(3), bufferGPR);
- m_jit.add32(storageGPR, bufferGPR);
- if (offset)
- m_jit.add32(TrustedImm32(offset), bufferGPR);
-#else
- m_jit.getEffectiveAddress64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, offset), bufferGPR);
-#endif
- };
-
- switch (node->arrayMode().type()) {
- case Array::Int32:
- case Array::Contiguous: {
- if (elementCount == 1) {
- Edge& element = m_jit.graph().varArgChild(node, elementOffset);
- JSValueOperand value(this, element, ManualOperandSpeculation);
- JSValueRegs valueRegs = value.jsValueRegs();
-
- if (node->arrayMode().type() == Array::Int32)
- RELEASE_ASSERT(!needsTypeCheck(element, SpecInt32Only));
-
- m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
- m_jit.storeValue(valueRegs, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
- m_jit.add32(TrustedImm32(1), storageLengthGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.boxInt32(storageLengthGPR, resultRegs);
-
- addSlowPathGenerator(
- slowPathCall(slowPath, this, operationArrayPush, resultRegs, valueRegs, baseGPR));
-
- jsValueResult(resultRegs, node);
- return;
- }
-
- GPRTemporary buffer(this);
- GPRReg bufferGPR = buffer.gpr();
-
- m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
- m_jit.move(storageLengthGPR, bufferGPR);
- m_jit.add32(TrustedImm32(elementCount), bufferGPR);
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::Above, bufferGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-
- m_jit.store32(bufferGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- getStorageBufferAddress(storageGPR, storageLengthGPR, 0, bufferGPR);
- m_jit.add32(TrustedImm32(elementCount), storageLengthGPR);
- m_jit.boxInt32(storageLengthGPR, resultRegs);
- auto storageDone = m_jit.jump();
-
- slowPath.link(&m_jit);
-
- size_t scratchSize = sizeof(EncodedJSValue) * elementCount;
- ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(scratchSize);
- m_jit.move(TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())), bufferGPR);
- m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), storageLengthGPR);
- m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(storageLengthGPR));
-
- storageDone.link(&m_jit);
- for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) {
- Edge& element = m_jit.graph().varArgChild(node, elementIndex + elementOffset);
- JSValueOperand value(this, element, ManualOperandSpeculation);
- JSValueRegs valueRegs = value.jsValueRegs();
-
- if (node->arrayMode().type() == Array::Int32)
- RELEASE_ASSERT(!needsTypeCheck(element, SpecInt32Only));
-
- m_jit.storeValue(valueRegs, MacroAssembler::Address(bufferGPR, sizeof(EncodedJSValue) * elementIndex));
- value.use();
- }
-
- MacroAssembler::Jump fastPath = m_jit.branchPtr(MacroAssembler::NotEqual, bufferGPR, TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())));
-
- addSlowPathGenerator(slowPathCall(m_jit.jump(), this, operationArrayPushMultiple, resultRegs, baseGPR, bufferGPR, TrustedImm32(elementCount)));
-
- m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), bufferGPR);
- m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(bufferGPR));
-
- base.use();
- storage.use();
-
- fastPath.link(&m_jit);
- jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
- return;
- }
-
- case Array::Double: {
- if (elementCount == 1) {
- Edge& element = m_jit.graph().varArgChild(node, elementOffset);
- SpeculateDoubleOperand value(this, element);
- FPRReg valueFPR = value.fpr();
-
- RELEASE_ASSERT(!needsTypeCheck(element, SpecDoubleReal));
-
- m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
- m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
- m_jit.add32(TrustedImm32(1), storageLengthGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.boxInt32(storageLengthGPR, resultRegs);
-
- addSlowPathGenerator(
- slowPathCall(slowPath, this, operationArrayPushDouble, resultRegs, valueFPR, baseGPR));
-
- jsValueResult(resultRegs, node);
- return;
- }
-
- GPRTemporary buffer(this);
- GPRReg bufferGPR = buffer.gpr();
-
- m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
- m_jit.move(storageLengthGPR, bufferGPR);
- m_jit.add32(TrustedImm32(elementCount), bufferGPR);
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::Above, bufferGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-
- m_jit.store32(bufferGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- getStorageBufferAddress(storageGPR, storageLengthGPR, 0, bufferGPR);
- m_jit.add32(TrustedImm32(elementCount), storageLengthGPR);
- m_jit.boxInt32(storageLengthGPR, resultRegs);
- auto storageDone = m_jit.jump();
-
- slowPath.link(&m_jit);
-
- size_t scratchSize = sizeof(double) * elementCount;
- ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(scratchSize);
- m_jit.move(TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())), bufferGPR);
- m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), storageLengthGPR);
- m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(storageLengthGPR));
-
- storageDone.link(&m_jit);
- for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) {
- Edge& element = m_jit.graph().varArgChild(node, elementIndex + elementOffset);
- SpeculateDoubleOperand value(this, element);
- FPRReg valueFPR = value.fpr();
-
- RELEASE_ASSERT(!needsTypeCheck(element, SpecDoubleReal));
-
- m_jit.storeDouble(valueFPR, MacroAssembler::Address(bufferGPR, sizeof(double) * elementIndex));
- value.use();
- }
-
- MacroAssembler::Jump fastPath = m_jit.branchPtr(MacroAssembler::NotEqual, bufferGPR, TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())));
-
- addSlowPathGenerator(slowPathCall(m_jit.jump(), this, operationArrayPushDoubleMultiple, resultRegs, baseGPR, bufferGPR, TrustedImm32(elementCount)));
-
- m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), bufferGPR);
- m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(bufferGPR));
-
- base.use();
- storage.use();
-
- fastPath.link(&m_jit);
- jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
- return;
- }
-
- case Array::ArrayStorage: {
- // This ensures that the result of ArrayPush is Int32 in AI.
- int32_t largestPositiveInt32Length = 0x7fffffff - elementCount;
- if (elementCount == 1) {
- Edge& element = m_jit.graph().varArgChild(node, elementOffset);
- JSValueOperand value(this, element);
- JSValueRegs valueRegs = value.jsValueRegs();
-
- m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
-
- // Refuse to handle bizarre lengths.
- speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(largestPositiveInt32Length)));
-
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
-
- m_jit.storeValue(valueRegs, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
-
- m_jit.add32(TrustedImm32(1), storageLengthGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
- m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
- m_jit.boxInt32(storageLengthGPR, resultRegs);
-
- addSlowPathGenerator(
- slowPathCall(slowPath, this, operationArrayPush, resultRegs, valueRegs, baseGPR));
-
- jsValueResult(resultRegs, node);
- return;
- }
-
- GPRTemporary buffer(this);
- GPRReg bufferGPR = buffer.gpr();
-
- m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
-
- // Refuse to handle bizarre lengths.
- speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(largestPositiveInt32Length)));
-
- m_jit.move(storageLengthGPR, bufferGPR);
- m_jit.add32(TrustedImm32(elementCount), bufferGPR);
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::Above, bufferGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
-
- m_jit.store32(bufferGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
- getStorageBufferAddress(storageGPR, storageLengthGPR, ArrayStorage::vectorOffset(), bufferGPR);
- m_jit.add32(TrustedImm32(elementCount), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
- m_jit.add32(TrustedImm32(elementCount), storageLengthGPR);
- m_jit.boxInt32(storageLengthGPR, resultRegs);
- auto storageDone = m_jit.jump();
-
- slowPath.link(&m_jit);
-
- size_t scratchSize = sizeof(EncodedJSValue) * elementCount;
- ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(scratchSize);
- m_jit.move(TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())), bufferGPR);
- m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), storageLengthGPR);
- m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(storageLengthGPR));
-
- storageDone.link(&m_jit);
- for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) {
- Edge& element = m_jit.graph().varArgChild(node, elementIndex + elementOffset);
- JSValueOperand value(this, element);
- JSValueRegs valueRegs = value.jsValueRegs();
-
- m_jit.storeValue(valueRegs, MacroAssembler::Address(bufferGPR, sizeof(EncodedJSValue) * elementIndex));
- value.use();
- }
-
- MacroAssembler::Jump fastPath = m_jit.branchPtr(MacroAssembler::NotEqual, bufferGPR, TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())));
-
- addSlowPathGenerator(
- slowPathCall(m_jit.jump(), this, operationArrayPushMultiple, resultRegs, baseGPR, bufferGPR, TrustedImm32(elementCount)));
-
- m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), bufferGPR);
- m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(bufferGPR));
-
- base.use();
- storage.use();
-
- fastPath.link(&m_jit);
- jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
- return;
- }
-
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
-}
-
void SpeculativeJIT::compileNotifyWrite(Node* node)
{
WatchpointSet* set = node->watchpointSet();
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-09-29 18:49:37 UTC (rev 222658)
@@ -1613,14 +1613,9 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(J_JITOperation_EJA operation, JSValueRegs result, JSValueRegs arg1, GPRReg arg2)
+ JITCompiler::Call callOperation(J_JITOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
- m_jit.setupArgumentsWithExecState(arg1.gpr(), arg2);
- return appendCallSetResult(operation, result.payloadGPR());
- }
- JITCompiler::Call callOperation(J_JITOperation_EJA operation, GPRReg result, JSValueRegs arg1, GPRReg arg2)
- {
- m_jit.setupArgumentsWithExecState(arg1.gpr(), arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
JITCompiler::Call callOperation(J_JITOperation_EP operation, GPRReg result, GPRReg arg1)
@@ -1794,16 +1789,6 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(J_JITOperation_EAPZ operation, JSValueRegs result, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
- return appendCallSetResult(operation, result.payloadGPR());
- }
- JITCompiler::Call callOperation(J_JITOperation_EAPZ operation, GPRReg result, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
- return appendCallSetResult(operation, result);
- }
JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -2129,11 +2114,6 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
}
- JITCompiler::Call callOperation(J_JITOperation_EAPZ operation, JSValueRegs result, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
- return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
- }
JITCompiler::Call callOperation(J_JITOperation_EP operation, JSValueRegs result, GPRReg arg1)
{
m_jit.setupArgumentsWithExecState(arg1);
@@ -2948,7 +2928,6 @@
void compileGetRestLength(Node*);
void compileArraySlice(Node*);
void compileArrayIndexOf(Node*);
- void compileArrayPush(Node*);
void compileNotifyWrite(Node*);
bool compileRegExpExec(Node*);
void compileIsObjectOrNull(Node*);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -3384,7 +3384,119 @@
}
case ArrayPush: {
- compileArrayPush(node);
+ ASSERT(node->arrayMode().isJSArray());
+
+ SpeculateCellOperand base(this, node->child1());
+ GPRTemporary storageLength(this);
+
+ GPRReg baseGPR = base.gpr();
+ GPRReg storageLengthGPR = storageLength.gpr();
+
+ StorageOperand storage(this, node->child3());
+ GPRReg storageGPR = storage.gpr();
+
+ switch (node->arrayMode().type()) {
+ case Array::Int32: {
+ SpeculateInt32Operand value(this, node->child2());
+ GPRReg valuePayloadGPR = value.gpr();
+
+ m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
+ MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+ m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+ m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+ m_jit.add32(TrustedImm32(1), storageLengthGPR);
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+ m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
+
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationArrayPush,
+ JSValueRegs(storageGPR, storageLengthGPR),
+ TrustedImm32(JSValue::Int32Tag), valuePayloadGPR, baseGPR));
+
+ jsValueResult(storageGPR, storageLengthGPR, node);
+ break;
+ }
+
+ case Array::Contiguous: {
+ JSValueOperand value(this, node->child2());
+ GPRReg valueTagGPR = value.tagGPR();
+ GPRReg valuePayloadGPR = value.payloadGPR();
+
+ m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
+ MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+ m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+ m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+ m_jit.add32(TrustedImm32(1), storageLengthGPR);
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+ m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
+
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationArrayPush,
+ JSValueRegs(storageGPR, storageLengthGPR),
+ JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
+
+ jsValueResult(storageGPR, storageLengthGPR, node);
+ break;
+ }
+
+ case Array::Double: {
+ SpeculateDoubleOperand value(this, node->child2());
+ FPRReg valueFPR = value.fpr();
+
+ DFG_TYPE_CHECK(
+ JSValueRegs(), node->child2(), SpecDoubleReal,
+ m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
+
+ m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
+ MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+ m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
+ m_jit.add32(TrustedImm32(1), storageLengthGPR);
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+ m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
+
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationArrayPushDouble,
+ JSValueRegs(storageGPR, storageLengthGPR),
+ valueFPR, baseGPR));
+
+ jsValueResult(storageGPR, storageLengthGPR, node);
+ break;
+ }
+
+ case Array::ArrayStorage: {
+ JSValueOperand value(this, node->child2());
+ GPRReg valueTagGPR = value.tagGPR();
+ GPRReg valuePayloadGPR = value.payloadGPR();
+
+ m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
+
+ // Refuse to handle bizarre lengths.
+ speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
+
+ MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
+
+ m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+ m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+
+ m_jit.add32(TrustedImm32(1), storageLengthGPR);
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
+ m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+ m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
+
+ addSlowPathGenerator(slowPathCall(slowPath, this, operationArrayPush, JSValueRegs(storageGPR, storageLengthGPR),
+ JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
+
+ jsValueResult(storageGPR, storageLengthGPR, node);
+ break;
+ }
+
+ default:
+ CRASH();
+ break;
+ }
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -3663,7 +3663,101 @@
}
case ArrayPush: {
- compileArrayPush(node);
+ ASSERT(node->arrayMode().isJSArray());
+
+ SpeculateCellOperand base(this, node->child1());
+ GPRTemporary storageLength(this);
+
+ GPRReg baseGPR = base.gpr();
+ GPRReg storageLengthGPR = storageLength.gpr();
+
+ StorageOperand storage(this, node->child3());
+ GPRReg storageGPR = storage.gpr();
+
+ switch (node->arrayMode().type()) {
+ case Array::Int32:
+ case Array::Contiguous: {
+ JSValueOperand value(this, node->child2(), ManualOperandSpeculation);
+ GPRReg valueGPR = value.gpr();
+
+ if (node->arrayMode().type() == Array::Int32) {
+ DFG_TYPE_CHECK(
+ JSValueRegs(valueGPR), node->child2(), SpecInt32Only,
+ m_jit.branch64(
+ MacroAssembler::Below, valueGPR, GPRInfo::tagTypeNumberRegister));
+ }
+
+ m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
+ MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+ m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
+ m_jit.add32(TrustedImm32(1), storageLengthGPR);
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+ m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
+
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationArrayPush, storageLengthGPR,
+ valueGPR, baseGPR));
+
+ jsValueResult(storageLengthGPR, node);
+ break;
+ }
+
+ case Array::Double: {
+ SpeculateDoubleOperand value(this, node->child2());
+ FPRReg valueFPR = value.fpr();
+
+ DFG_TYPE_CHECK(
+ JSValueRegs(), node->child2(), SpecDoubleReal,
+ m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
+
+ m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
+ MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+ m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
+ m_jit.add32(TrustedImm32(1), storageLengthGPR);
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+ m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
+
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationArrayPushDouble, storageLengthGPR,
+ valueFPR, baseGPR));
+
+ jsValueResult(storageLengthGPR, node);
+ break;
+ }
+
+ case Array::ArrayStorage: {
+ JSValueOperand value(this, node->child2());
+ GPRReg valueGPR = value.gpr();
+
+ m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
+
+ // Refuse to handle bizarre lengths.
+ speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
+
+ MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
+
+ m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
+
+ m_jit.add32(TrustedImm32(1), storageLengthGPR);
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
+ m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+ m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
+
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationArrayPush, NoResult, storageLengthGPR,
+ valueGPR, baseGPR));
+
+ jsValueResult(storageLengthGPR, node);
+ break;
+ }
+
+ default:
+ CRASH();
+ break;
+ }
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -250,16 +250,9 @@
case ArrayPush: {
switch (m_node->arrayMode().type()) {
case Array::Contiguous:
- case Array::ArrayStorage: {
- unsigned elementOffset = 2;
- unsigned elementCount = m_node->numChildren() - elementOffset;
- Edge& arrayEdge = m_graph.varArgChild(m_node, 1);
- for (unsigned i = 0; i < elementCount; ++i) {
- Edge& element = m_graph.varArgChild(m_node, i + elementOffset);
- considerBarrier(arrayEdge, element);
- }
+ case Array::ArrayStorage:
+ considerBarrier(m_node->child1(), m_node->child2());
break;
- }
default:
break;
}
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -4088,134 +4088,68 @@
void compileArrayPush()
{
- LValue base = lowCell(m_graph.varArgChild(m_node, 1));
- LValue storage = lowStorage(m_graph.varArgChild(m_node, 0));
- unsigned elementOffset = 2;
- unsigned elementCount = m_node->numChildren() - elementOffset;
-
+ LValue base = lowCell(m_node->child1());
+ LValue storage = lowStorage(m_node->child3());
+
switch (m_node->arrayMode().type()) {
case Array::Int32:
case Array::Contiguous:
case Array::Double: {
- IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
-
- if (elementCount == 1) {
- LValue value;
- Output::StoreType storeType;
-
- Edge& element = m_graph.varArgChild(m_node, elementOffset);
- if (m_node->arrayMode().type() != Array::Double) {
- value = lowJSValue(element, ManualOperandSpeculation);
- if (m_node->arrayMode().type() == Array::Int32)
- RELEASE_ASSERT(!m_interpreter.needsTypeCheck(element, SpecInt32Only));
- storeType = Output::Store64;
- } else {
- value = lowDouble(element);
- RELEASE_ASSERT(!m_interpreter.needsTypeCheck(element, SpecDoubleReal));
- storeType = Output::StoreDouble;
+ LValue value;
+ Output::StoreType storeType;
+
+ if (m_node->arrayMode().type() != Array::Double) {
+ value = lowJSValue(m_node->child2(), ManualOperandSpeculation);
+ if (m_node->arrayMode().type() == Array::Int32) {
+ FTL_TYPE_CHECK(
+ jsValueValue(value), m_node->child2(), SpecInt32Only, isNotInt32(value));
}
-
- LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
-
- LBasicBlock fastPath = m_out.newBlock();
- LBasicBlock slowPath = m_out.newBlock();
- LBasicBlock continuation = m_out.newBlock();
-
- m_out.branch(
- m_out.aboveOrEqual(
- prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
- unsure(slowPath), unsure(fastPath));
-
- LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
- m_out.store(
- value, m_out.baseIndex(heap, storage, m_out.zeroExtPtr(prevLength)), storeType);
- LValue newLength = m_out.add(prevLength, m_out.int32One);
- m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
-
- ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
- m_out.jump(continuation);
-
- m_out.appendTo(slowPath, continuation);
- LValue operation;
- if (m_node->arrayMode().type() != Array::Double)
- operation = m_out.operation(operationArrayPush);
- else
- operation = m_out.operation(operationArrayPushDouble);
- ValueFromBlock slowResult = m_out.anchor(
- vmCall(Int64, operation, m_callFrame, value, base));
- m_out.jump(continuation);
-
- m_out.appendTo(continuation, lastNext);
- setJSValue(m_out.phi(Int64, fastResult, slowResult));
- return;
+ storeType = Output::Store64;
+ } else {
+ value = lowDouble(m_node->child2());
+ FTL_TYPE_CHECK(
+ doubleValue(value), m_node->child2(), SpecDoubleReal,
+ m_out.doubleNotEqualOrUnordered(value, value));
+ storeType = Output::StoreDouble;
}
+
+ IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
- LValue newLength = m_out.add(prevLength, m_out.constInt32(elementCount));
-
+
LBasicBlock fastPath = m_out.newBlock();
LBasicBlock slowPath = m_out.newBlock();
- LBasicBlock setup = m_out.newBlock();
- LBasicBlock slowCallPath = m_out.newBlock();
LBasicBlock continuation = m_out.newBlock();
-
- LValue beyondVectorLength = m_out.above(newLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength));
-
- m_out.branch(beyondVectorLength, unsure(slowPath), unsure(fastPath));
-
+
+ m_out.branch(
+ m_out.aboveOrEqual(
+ prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
+ unsure(slowPath), unsure(fastPath));
+
LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
+ m_out.store(
+ value, m_out.baseIndex(heap, storage, m_out.zeroExtPtr(prevLength)), storeType);
+ LValue newLength = m_out.add(prevLength, m_out.int32One);
m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
- ValueFromBlock fastBufferResult = m_out.anchor(m_out.baseIndex(storage, m_out.zeroExtPtr(prevLength), ScaleEight));
- m_out.jump(setup);
-
- m_out.appendTo(slowPath, setup);
- size_t scratchSize = sizeof(EncodedJSValue) * elementCount;
- static_assert(sizeof(EncodedJSValue) == sizeof(double), "");
- ASSERT(scratchSize);
- ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
- m_out.storePtr(m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->addressOfActiveLength()));
- ValueFromBlock slowBufferResult = m_out.anchor(m_out.constIntPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())));
- m_out.jump(setup);
-
- m_out.appendTo(setup, slowCallPath);
- LValue buffer = m_out.phi(pointerType(), fastBufferResult, slowBufferResult);
- for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) {
- Edge& element = m_graph.varArgChild(m_node, elementIndex + elementOffset);
-
- LValue value;
- Output::StoreType storeType;
- if (m_node->arrayMode().type() != Array::Double) {
- value = lowJSValue(element, ManualOperandSpeculation);
- if (m_node->arrayMode().type() == Array::Int32)
- RELEASE_ASSERT(!m_interpreter.needsTypeCheck(element, SpecInt32Only));
- storeType = Output::Store64;
- } else {
- value = lowDouble(element);
- RELEASE_ASSERT(!m_interpreter.needsTypeCheck(element, SpecDoubleReal));
- storeType = Output::StoreDouble;
- }
-
- m_out.store(value, m_out.baseIndex(heap, buffer, m_out.constInt32(elementIndex), jsNumber(elementIndex)), storeType);
- }
+
ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
-
- m_out.branch(beyondVectorLength, unsure(slowCallPath), unsure(continuation));
-
- m_out.appendTo(slowCallPath, continuation);
+ m_out.jump(continuation);
+
+ m_out.appendTo(slowPath, continuation);
LValue operation;
if (m_node->arrayMode().type() != Array::Double)
- operation = m_out.operation(operationArrayPushMultiple);
+ operation = m_out.operation(operationArrayPush);
else
- operation = m_out.operation(operationArrayPushDoubleMultiple);
- ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, operation, m_callFrame, base, buffer, m_out.constInt32(elementCount)));
- m_out.storePtr(m_out.constIntPtr(0), m_out.absolute(scratchBuffer->addressOfActiveLength()));
+ operation = m_out.operation(operationArrayPushDouble);
+ ValueFromBlock slowResult = m_out.anchor(
+ vmCall(Int64, operation, m_callFrame, value, base));
m_out.jump(continuation);
-
+
m_out.appendTo(continuation, lastNext);
setJSValue(m_out.phi(Int64, fastResult, slowResult));
return;
}
-
+
default:
DFG_CRASH(m_graph, m_node, "Bad array type");
return;
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (222657 => 222658)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2017-09-29 18:49:37 UTC (rev 222658)
@@ -141,7 +141,6 @@
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJC)(ExecState*, EncodedJSValue, JSCell*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJA)(ExecState*, EncodedJSValue, JSArray*);
-typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EAPZ)(ExecState*, JSArray*, void*, int32_t);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJArp)(ExecState*, EncodedJSValue, ArithProfile*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJI)(ExecState*, EncodedJSValue, UniquedStringImpl*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -764,10 +764,10 @@
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
- if (LIKELY(isJSArray(thisValue) && exec->argumentCount() == 1)) {
+ if (isJSArray(thisValue) && exec->argumentCount() == 1) {
JSArray* array = asArray(thisValue);
scope.release();
- array->pushInline(exec, exec->uncheckedArgument(0));
+ array->push(exec, exec->uncheckedArgument(0));
return JSValue::encode(jsNumber(array->length()));
}
Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (222657 => 222658)
--- trunk/Source/_javascript_Core/runtime/JSArray.cpp 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp 2017-09-29 18:49:37 UTC (rev 222658)
@@ -40,7 +40,7 @@
namespace JSC {
-const char* const LengthExceededTheMaximumArrayLengthError = "Length exceeded the maximum array length";
+static const char* const LengthExceededTheMaximumArrayLengthError = "Length exceeded the maximum array length";
STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSArray);
@@ -725,9 +725,153 @@
// Push & putIndex are almost identical, with two small differences.
// - we always are writing beyond the current array bounds, so it is always necessary to update m_length & m_numValuesInVector.
// - pushing to an array of length 2^32-1 stores the property, but throws a range error.
-NEVER_INLINE void JSArray::push(ExecState* exec, JSValue value)
+void JSArray::push(ExecState* exec, JSValue value)
{
- pushInline(exec, value);
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Butterfly* butterfly = m_butterfly.getMayBeNull();
+
+ switch (indexingType()) {
+ case ArrayClass: {
+ createInitialUndecided(vm, 0);
+ FALLTHROUGH;
+ }
+
+ case ArrayWithUndecided: {
+ convertUndecidedForValue(vm, value);
+ scope.release();
+ push(exec, value);
+ return;
+ }
+
+ case ArrayWithInt32: {
+ if (!value.isInt32()) {
+ convertInt32ForValue(vm, value);
+ scope.release();
+ push(exec, value);
+ return;
+ }
+
+ unsigned length = butterfly->publicLength();
+ ASSERT(length <= butterfly->vectorLength());
+ if (length < butterfly->vectorLength()) {
+ butterfly->contiguousInt32()[length].setWithoutWriteBarrier(value);
+ butterfly->setPublicLength(length + 1);
+ return;
+ }
+
+ if (UNLIKELY(length > MAX_ARRAY_INDEX)) {
+ methodTable(vm)->putByIndex(this, exec, length, value, true);
+ if (!scope.exception())
+ throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError)));
+ return;
+ }
+
+ scope.release();
+ putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, length, value);
+ return;
+ }
+
+ case ArrayWithContiguous: {
+ unsigned length = butterfly->publicLength();
+ ASSERT(length <= butterfly->vectorLength());
+ if (length < butterfly->vectorLength()) {
+ butterfly->contiguous()[length].set(vm, this, value);
+ butterfly->setPublicLength(length + 1);
+ return;
+ }
+
+ if (UNLIKELY(length > MAX_ARRAY_INDEX)) {
+ methodTable(vm)->putByIndex(this, exec, length, value, true);
+ if (!scope.exception())
+ throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError)));
+ return;
+ }
+
+ scope.release();
+ putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, length, value);
+ return;
+ }
+
+ case ArrayWithDouble: {
+ if (!value.isNumber()) {
+ convertDoubleToContiguous(vm);
+ scope.release();
+ push(exec, value);
+ return;
+ }
+ double valueAsDouble = value.asNumber();
+ if (valueAsDouble != valueAsDouble) {
+ convertDoubleToContiguous(vm);
+ scope.release();
+ push(exec, value);
+ return;
+ }
+
+ unsigned length = butterfly->publicLength();
+ ASSERT(length <= butterfly->vectorLength());
+ if (length < butterfly->vectorLength()) {
+ butterfly->contiguousDouble()[length] = valueAsDouble;
+ butterfly->setPublicLength(length + 1);
+ return;
+ }
+
+ if (UNLIKELY(length > MAX_ARRAY_INDEX)) {
+ methodTable(vm)->putByIndex(this, exec, length, value, true);
+ if (!scope.exception())
+ throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError)));
+ return;
+ }
+
+ scope.release();
+ putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, length, value);
+ return;
+ }
+
+ case ArrayWithSlowPutArrayStorage: {
+ unsigned oldLength = length();
+ bool putResult = false;
+ if (attemptToInterceptPutByIndexOnHole(exec, oldLength, value, true, putResult)) {
+ if (!scope.exception() && oldLength < 0xFFFFFFFFu) {
+ scope.release();
+ setLength(exec, oldLength + 1, true);
+ }
+ return;
+ }
+ FALLTHROUGH;
+ }
+
+ case ArrayWithArrayStorage: {
+ ArrayStorage* storage = butterfly->arrayStorage();
+
+ // Fast case - push within vector, always update m_length & m_numValuesInVector.
+ unsigned length = storage->length();
+ if (length < storage->vectorLength()) {
+ storage->m_vector[length].set(vm, this, value);
+ storage->setLength(length + 1);
+ ++storage->m_numValuesInVector;
+ return;
+ }
+
+ // Pushing to an array of invalid length (2^31-1) stores the property, but throws a range error.
+ if (UNLIKELY(storage->length() > MAX_ARRAY_INDEX)) {
+ methodTable(vm)->putByIndex(this, exec, storage->length(), value, true);
+ // Per ES5.1 15.4.4.7 step 6 & 15.4.5.1 step 3.d.
+ if (!scope.exception())
+ throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError)));
+ return;
+ }
+
+ // Handled the same as putIndex.
+ scope.release();
+ putByIndexBeyondVectorLengthWithArrayStorage(exec, storage->length(), value, true, storage);
+ return;
+ }
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
}
JSArray* JSArray::fastSlice(ExecState& exec, unsigned startIndex, unsigned count)
Modified: trunk/Source/_javascript_Core/runtime/JSArray.h (222657 => 222658)
--- trunk/Source/_javascript_Core/runtime/JSArray.h 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/runtime/JSArray.h 2017-09-29 18:49:37 UTC (rev 222658)
@@ -31,8 +31,6 @@
class JSArray;
class LLIntOffsetsExtractor;
-extern const char* const LengthExceededTheMaximumArrayLengthError;
-
class JSArray : public JSNonFinalObject {
friend class LLIntOffsetsExtractor;
friend class Walker;
@@ -92,7 +90,6 @@
// OK to use on new arrays, but not if it might be a RegExpMatchArray or RuntimeArray.
JS_EXPORT_PRIVATE bool setLength(ExecState*, unsigned, bool throwException = false);
- void pushInline(ExecState*, JSValue);
JS_EXPORT_PRIVATE void push(ExecState*, JSValue);
JS_EXPORT_PRIVATE JSValue pop(ExecState*);
Modified: trunk/Source/_javascript_Core/runtime/JSArrayInlines.h (222657 => 222658)
--- trunk/Source/_javascript_Core/runtime/JSArrayInlines.h 2017-09-29 18:48:30 UTC (rev 222657)
+++ trunk/Source/_javascript_Core/runtime/JSArrayInlines.h 2017-09-29 18:49:37 UTC (rev 222658)
@@ -19,7 +19,6 @@
#pragma once
-#include "Error.h"
#include "JSArray.h"
#include "JSCellInlines.h"
#include "Structure.h"
@@ -83,153 +82,4 @@
return lengthValue.toLength(exec);
}
-ALWAYS_INLINE void JSArray::pushInline(ExecState* exec, JSValue value)
-{
- VM& vm = exec->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- Butterfly* butterfly = m_butterfly.getMayBeNull();
-
- switch (indexingType()) {
- case ArrayClass: {
- createInitialUndecided(vm, 0);
- FALLTHROUGH;
- }
-
- case ArrayWithUndecided: {
- convertUndecidedForValue(vm, value);
- scope.release();
- push(exec, value);
- return;
- }
-
- case ArrayWithInt32: {
- if (!value.isInt32()) {
- convertInt32ForValue(vm, value);
- scope.release();
- push(exec, value);
- return;
- }
-
- unsigned length = butterfly->publicLength();
- ASSERT(length <= butterfly->vectorLength());
- if (length < butterfly->vectorLength()) {
- butterfly->contiguousInt32()[length].setWithoutWriteBarrier(value);
- butterfly->setPublicLength(length + 1);
- return;
- }
-
- if (UNLIKELY(length > MAX_ARRAY_INDEX)) {
- methodTable(vm)->putByIndex(this, exec, length, value, true);
- if (!scope.exception())
- throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError)));
- return;
- }
-
- scope.release();
- putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, length, value);
- return;
- }
-
- case ArrayWithContiguous: {
- unsigned length = butterfly->publicLength();
- ASSERT(length <= butterfly->vectorLength());
- if (length < butterfly->vectorLength()) {
- butterfly->contiguous()[length].set(vm, this, value);
- butterfly->setPublicLength(length + 1);
- return;
- }
-
- if (UNLIKELY(length > MAX_ARRAY_INDEX)) {
- methodTable(vm)->putByIndex(this, exec, length, value, true);
- if (!scope.exception())
- throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError)));
- return;
- }
-
- scope.release();
- putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, length, value);
- return;
- }
-
- case ArrayWithDouble: {
- if (!value.isNumber()) {
- convertDoubleToContiguous(vm);
- scope.release();
- push(exec, value);
- return;
- }
- double valueAsDouble = value.asNumber();
- if (valueAsDouble != valueAsDouble) {
- convertDoubleToContiguous(vm);
- scope.release();
- push(exec, value);
- return;
- }
-
- unsigned length = butterfly->publicLength();
- ASSERT(length <= butterfly->vectorLength());
- if (length < butterfly->vectorLength()) {
- butterfly->contiguousDouble()[length] = valueAsDouble;
- butterfly->setPublicLength(length + 1);
- return;
- }
-
- if (UNLIKELY(length > MAX_ARRAY_INDEX)) {
- methodTable(vm)->putByIndex(this, exec, length, value, true);
- if (!scope.exception())
- throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError)));
- return;
- }
-
- scope.release();
- putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, length, value);
- return;
- }
-
- case ArrayWithSlowPutArrayStorage: {
- unsigned oldLength = length();
- bool putResult = false;
- if (attemptToInterceptPutByIndexOnHole(exec, oldLength, value, true, putResult)) {
- if (!scope.exception() && oldLength < 0xFFFFFFFFu) {
- scope.release();
- setLength(exec, oldLength + 1, true);
- }
- return;
- }
- FALLTHROUGH;
- }
-
- case ArrayWithArrayStorage: {
- ArrayStorage* storage = butterfly->arrayStorage();
-
- // Fast case - push within vector, always update m_length & m_numValuesInVector.
- unsigned length = storage->length();
- if (length < storage->vectorLength()) {
- storage->m_vector[length].set(vm, this, value);
- storage->setLength(length + 1);
- ++storage->m_numValuesInVector;
- return;
- }
-
- // Pushing to an array of invalid length (2^31-1) stores the property, but throws a range error.
- if (UNLIKELY(storage->length() > MAX_ARRAY_INDEX)) {
- methodTable(vm)->putByIndex(this, exec, storage->length(), value, true);
- // Per ES5.1 15.4.4.7 step 6 & 15.4.5.1 step 3.d.
- if (!scope.exception())
- throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError)));
- return;
- }
-
- // Handled the same as putIndex.
- scope.release();
- putByIndexBeyondVectorLengthWithArrayStorage(exec, storage->length(), value, true, storage);
- return;
- }
-
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
-}
-
} // namespace JSC