Diff
Modified: trunk/JSTests/ChangeLog (204438 => 204439)
--- trunk/JSTests/ChangeLog 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/JSTests/ChangeLog 2016-08-13 02:14:42 UTC (rev 204439)
@@ -1,3 +1,14 @@
+2016-08-12 Saam Barati <sbar...@apple.com>
+
+ Inline store loop for CopyRest in DFG and FTL for certain array modes
+ https://bugs.webkit.org/show_bug.cgi?id=159612
+
+ Reviewed by Filip Pizlo.
+
+ * stress/rest-parameter-having-a-bad-time.js: Added.
+ * stress/rest-parameter-many-arguments.js: Added.
+ * stress/rest-parameter-various-types.js: Added.
+
2016-08-12 Skachkov Oleksandr <gskach...@gmail.com>
[ES2016] Implement Object.entries
Added: trunk/JSTests/stress/rest-parameter-having-a-bad-time.js (0 => 204439)
--- trunk/JSTests/stress/rest-parameter-having-a-bad-time.js (rev 0)
+++ trunk/JSTests/stress/rest-parameter-having-a-bad-time.js 2016-08-13 02:14:42 UTC (rev 204439)
@@ -0,0 +1,68 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad!")
+}
+noInline(assert);
+
+function test1() {
+ function foo(...c) {
+ return c;
+ }
+ noInline(foo);
+
+ let arr = [1,2,3];
+ for (let i = 0; i < 10000; i++) {
+ let result = foo(...arr);
+ assert(result.length === 3);
+ assert(result.length === arr.length);
+ assert(result[0] === arr[0]);
+ assert(result[1] === arr[1]);
+ assert(result[2] === arr[2]);
+ }
+
+ let called = false;
+ Reflect.defineProperty(Array.prototype, "10", {
+ get() { return 35; },
+ set(x) { called = true; }
+ });
+ let called2 = false;
+ Reflect.defineProperty(Array.prototype, "0", {
+ get: function() { print("In get!"); return 35; },
+ set: function(x) { called2 = true; }
+ });
+
+ for (let i = 0; i < 10000; i++) {
+ let result = foo(...arr);
+ assert(result.length === 3);
+ assert(result[0] === arr[0]);
+ assert(result[0] === 1);
+ assert(result[1] === arr[1]);
+ assert(result[2] === arr[2]);
+ result[10] = 25;
+ assert(result[10] === 35);
+ assert(called);
+ called = false;
+
+ result[0] = "foo";
+ assert(!called2); // Creating a rest should defineProperty, ensuring we don't call the setter.
+ }
+
+ for (let i = 0; i < 10000; i++) {
+ let result = foo(...arr);
+ assert(result.length === 3);
+ assert(result[0] === arr[0]);
+ assert(result[0] === 1);
+ assert(result[1] === arr[1]);
+ assert(result[2] === arr[2]);
+ result[11] = 35;
+ assert(result.length === 12);
+ result[10] = 25;
+ assert(result[10] === 35);
+ assert(called);
+ called = false;
+
+ result[0] = "foo";
+ assert(!called2); // Creating a rest should defineProperty, ensuring we don't call the setter.
+ }
+}
+test1();
Added: trunk/JSTests/stress/rest-parameter-many-arguments.js (0 => 204439)
--- trunk/JSTests/stress/rest-parameter-many-arguments.js (rev 0)
+++ trunk/JSTests/stress/rest-parameter-many-arguments.js 2016-08-13 02:14:42 UTC (rev 204439)
@@ -0,0 +1,49 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad!")
+}
+noInline(assert);
+
+let calledGet = false;
+let definedAccessor = false;
+function test() {
+ function foo(...rest) {
+ return rest;
+ }
+ noInline(foo);
+
+ for (let i = 0; i < 10000; i++) {
+ const size = 800;
+ let arr = new Array(size);
+ for (let i = 0; i < size; i++)
+ arr[i] = i;
+ let result = foo(...arr);
+
+ assert(result.length === arr.length);
+ assert(result.length === size);
+ for (let i = 0; i < arr.length; i++) {
+ assert(arr[i] === result[i]);
+ assert(result[i] === i);
+ }
+ if (definedAccessor) {
+ calledGet = false;
+ result[0];
+ assert(!calledGet);
+ arr[0];
+ assert(calledGet);
+
+ let testArr = [...arr];
+ calledGet = false;
+ testArr[0];
+ assert(!calledGet);
+ }
+ }
+}
+test();
+
+definedAccessor = true;
+Reflect.defineProperty(Array.prototype, "0", {
+ get() { calledGet = true; return 0; },
+ set(x) { }
+});
+test();
Added: trunk/JSTests/stress/rest-parameter-various-types.js (0 => 204439)
--- trunk/JSTests/stress/rest-parameter-various-types.js (rev 0)
+++ trunk/JSTests/stress/rest-parameter-various-types.js 2016-08-13 02:14:42 UTC (rev 204439)
@@ -0,0 +1,98 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad!");
+}
+noInline(assert);
+
+function foo(a, b, ...c) {
+ return c;
+}
+noInline(foo);
+function bar(a, b, ...c) {
+ return c;
+}
+noInline(bar);
+
+function baz(a, b, ...c) { // allow this to be inlined
+ return c;
+}
+
+noInline(isNaN);
+
+function test1(f, iters) {
+ for (let i = 0; i < iters; i++) {
+ let result = f(10, 20, 20.5, 22.45, 23.50);
+ assert(result.length === 3);
+ assert(result[0] === 20.5)
+ assert(result[1] === 22.45)
+ assert(result[2] === 23.50);
+ }
+
+ let o = {};
+ let result = f(10, 20, 20.4, o, 20.2);
+ assert(result.length === 3);
+ assert(result[0] === 20.4)
+ assert(result[1] === o)
+ assert(result[2] === 20.2);
+
+ result = f(10, 20, 20.4, 20.45, NaN);
+ assert(result.length === 3);
+ assert(result[0] === 20.4)
+ assert(result[1] === 20.45)
+ assert(isNaN(result[2]));
+}
+test1(foo, 1000);
+test1(bar, 10000);
+test1(baz, 10000);
+
+function makeTest2() {
+ return eval(`${Math.random()};
+ ;(function test2(f, iters) {
+ let a = 10;
+ let b = 20;
+ for (let i = 0; i < iters; i++) {
+ if (i === iters - 2) {
+ b = {};
+ } else if (i === iters - 1) {
+ b = NaN;
+ }
+
+ let r = f(a, b);
+ assert(r.length === 2);
+ assert(r[0] === a || (isNaN(a) && isNaN(r[0])));
+ assert(r[1] === b || (isNaN(b) && isNaN(r[1])));
+ }
+ })`);
+}
+function f1(...rest) { return rest; }
+function f2(...rest) { return rest; }
+function f3(...rest) { return rest; }
+makeTest2()(f1, 1000);
+makeTest2()(f2, 10000);
+makeTest2()(f3, 500000);
+
+function test3(f, iters) {
+ let o = {};
+ for (let i = 0; i < iters; i++) {
+ let r = f(i, o, 25);
+ assert(r.length === 2 || r.length === 10000);
+ assert(r[0] === o);
+ assert(r[1] === 25);
+ if (r.length === 10000)
+ assert(r[9999] === 30);
+ }
+}
+
+function f11(i, ...rest) {
+ if (i === 999)
+ rest[9999] = 30;
+ return rest;
+}
+function f22(i, ...rest) {
+ if (i === 49999)
+ rest[9999] = 30;
+ return rest;
+}
+test3(f11, 1000);
+test3(f22, 50000);
+
Modified: trunk/LayoutTests/ChangeLog (204438 => 204439)
--- trunk/LayoutTests/ChangeLog 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/LayoutTests/ChangeLog 2016-08-13 02:14:42 UTC (rev 204439)
@@ -1,3 +1,18 @@
+2016-08-12 Saam Barati <sbar...@apple.com>
+
+ Inline store loop for CopyRest in DFG and FTL for certain array modes
+ https://bugs.webkit.org/show_bug.cgi?id=159612
+
+ Reviewed by Filip Pizlo.
+
+ * js/regress/rest-parameter-construction-performance-expected.txt: Added.
+ * js/regress/rest-parameter-construction-performance.html: Added.
+ * js/regress/script-tests/rest-parameter-construction-performance.js: Added.
+ (foo):
+ (test1):
+ (test2.foo):
+ (test2):
+
2016-08-12 Ryan Haddad <ryanhad...@apple.com>
Add mac-wk1 baseline for js/dom/global-constructors-attributes.html after r204396.
Added: trunk/LayoutTests/js/regress/rest-parameter-construction-performance-expected.txt (0 => 204439)
--- trunk/LayoutTests/js/regress/rest-parameter-construction-performance-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/rest-parameter-construction-performance-expected.txt 2016-08-13 02:14:42 UTC (rev 204439)
@@ -0,0 +1,10 @@
+JSRegress/rest-parameter-construction-performance
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/regress/rest-parameter-construction-performance.html (0 => 204439)
--- trunk/LayoutTests/js/regress/rest-parameter-construction-performance.html (rev 0)
+++ trunk/LayoutTests/js/regress/rest-parameter-construction-performance.html 2016-08-13 02:14:42 UTC (rev 204439)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/regress/script-tests/rest-parameter-construction-performance.js (0 => 204439)
--- trunk/LayoutTests/js/regress/script-tests/rest-parameter-construction-performance.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/rest-parameter-construction-performance.js 2016-08-13 02:14:42 UTC (rev 204439)
@@ -0,0 +1,27 @@
+"use strict";
+
+function foo(...rest) {
+ return rest;
+}
+noInline(foo);
+
+const iters = 900000;
+function test1() {
+ let o = {};
+ let a = [];
+ for (let i = 0; i < iters; i++)
+ foo(10, 20, o, 55, a, 120.341, a, o);
+}
+
+function test2() {
+ function foo(...rest) { // Allow this to be inlined.
+ return rest;
+ }
+ let o = {};
+ let a = [];
+ for (let i = 0; i < iters; i++)
+ foo(10, 20, o, 55, a, 120.341, a, o);
+}
+
+test1();
+test2();
Modified: trunk/Source/_javascript_Core/ChangeLog (204438 => 204439)
--- trunk/Source/_javascript_Core/ChangeLog 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-08-13 02:14:42 UTC (rev 204439)
@@ -1,3 +1,97 @@
+2016-08-12 Saam Barati <sbar...@apple.com>
+
+ Inline store loop for CopyRest in DFG and FTL for certain array modes
+ https://bugs.webkit.org/show_bug.cgi?id=159612
+
+ Reviewed by Filip Pizlo.
+
+ This patch changes the old copy_rest bytecode to actually allocate the rest array itself.
+ The bytecode is now called create_rest with an analogous CreateRest node in the DFG/FTL.
+ This allows the bytecode to be in control of what type of indexingType the array is allocated
+ with. We always allocate using ArrayWithContiguous storage unless we're havingABadTime().
+ This also makes allocating and writing into the array fast. On the fast path, the DFG/FTL
+ JIT will fast allocate the array and its storage, and we will do a memmove from the rest
+ region of arguments into the array's storage.
+
+ I'm seeing a 1-2% speedup on ES6SampleBench, and about a 2x speedup
+ on micro benchmarks that just test rest creation speed.
+
+ * bytecode/BytecodeList.json:
+ * bytecode/BytecodeUseDef.h:
+ (JSC::computeUsesForBytecodeOffset):
+ (JSC::computeDefsForBytecodeOffset):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dumpBytecode):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitRestParameter):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCallArrayAllocatorSlowPathGenerator.h:
+ (JSC::DFG::CallArrayAllocatorWithVariableSizeSlowPathGenerator::CallArrayAllocatorWithVariableSizeSlowPathGenerator):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::uses):
+ (JSC::DFG::Graph::isWatchingHavingABadTimeWatchpoint):
+ (JSC::DFG::Graph::compilation):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::numberOfArgumentsToSkip):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
+ (JSC::DFG::SpeculativeJIT::compileCreateRest):
+ (JSC::DFG::SpeculativeJIT::compileGetRestLength):
+ (JSC::DFG::SpeculativeJIT::compileCopyRest): Deleted.
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ (JSC::DFG::SpeculativeJIT::compileArithRandom):
+ (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ (JSC::DFG::SpeculativeJIT::compileArithRandom):
+ (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileCreateClonedArguments):
+ (JSC::FTL::DFG::LowerDFGToB3::compileCreateRest):
+ (JSC::FTL::DFG::LowerDFGToB3::compileGetRestLength):
+ (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayBuffer):
+ (JSC::FTL::DFG::LowerDFGToB3::compileAllocateArrayWithSize):
+ (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
+ (JSC::FTL::DFG::LowerDFGToB3::compileCopyRest): Deleted.
+ * interpreter/CallFrame.h:
+ (JSC::ExecState::addressOfArgumentsStart):
+ (JSC::ExecState::argument):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_argument_count):
+ (JSC::JIT::emit_op_create_rest):
+ (JSC::JIT::emit_op_copy_rest): Deleted.
+ * jit/JITOperations.h:
+ * llint/LowLevelInterpreter.asm:
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::SLOW_PATH_DECL):
+ * runtime/CommonSlowPaths.h:
+
2016-08-12 Ryosuke Niwa <rn...@webkit.org>
Add a helper class for enumerating elements in an iterable object
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (204438 => 204439)
--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2016-08-13 02:14:42 UTC (rev 204439)
@@ -141,7 +141,7 @@
{ "name" : "op_enumerator_generic_pname", "length" : 4 },
{ "name" : "op_to_index_string", "length" : 3 },
{ "name" : "op_assert", "length" : 3 },
- { "name" : "op_copy_rest", "length": 4 },
+ { "name" : "op_create_rest", "length": 4 },
{ "name" : "op_get_rest_length", "length": 3 },
{ "name" : "op_save", "length" : 4 },
{ "name" : "op_resume", "length" : 3 },
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (204438 => 204439)
--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -90,8 +90,7 @@
case op_jngreatereq:
case op_jless:
case op_set_function_name:
- case op_log_shadow_chicken_tail:
- case op_copy_rest: {
+ case op_log_shadow_chicken_tail: {
ASSERT(opcodeLengths[opcodeID] > 2);
functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
@@ -190,6 +189,7 @@
case op_new_generator_func:
case op_get_parent_scope:
case op_create_scoped_arguments:
+ case op_create_rest:
case op_get_from_arguments: {
ASSERT(opcodeLengths[opcodeID] > 2);
functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
@@ -318,7 +318,6 @@
OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode);
switch (opcodeID) {
// These don't define anything.
- case op_copy_rest:
case op_put_to_scope:
case op_end:
case op_throw:
@@ -464,6 +463,7 @@
case op_del_by_val:
case op_unsigned:
case op_get_from_arguments:
+ case op_create_rest:
case op_get_rest_length: {
ASSERT(opcodeLengths[opcodeID] > 1);
functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -832,11 +832,11 @@
printLocationOpAndRegisterOperand(out, exec, location, it, "argument_count", r0);
break;
}
- case op_copy_rest: {
+ case op_create_rest: {
int r0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
unsigned argumentOffset = (++it)->u.unsignedValue;
- printLocationAndOp(out, exec, location, it, "copy_rest");
+ printLocationAndOp(out, exec, location, it, "create_rest");
out.printf("%s, %s, ", registerName(r0).data(), registerName(r1).data());
out.printf("ArgumentsOffset: %u", argumentOffset);
break;
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -4435,9 +4435,7 @@
instructions().append(restArrayLength->index());
instructions().append(numParametersToSkip);
- emitNewArrayWithSize(result, restArrayLength.get());
-
- emitOpcode(op_copy_rest);
+ emitOpcode(op_create_rest);
instructions().append(result->index());
instructions().append(restArrayLength->index());
instructions().append(numParametersToSkip);
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -2861,7 +2861,10 @@
case CheckTypeInfoFlags:
break;
- case CopyRest:
+ case CreateRest:
+ if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) // This means we're already having a bad time.
+ clobberWorld(node->origin.semantic, clobberLimit);
+ forNode(node).setType(m_graph, SpecArray);
break;
case Check: {
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -3734,13 +3734,12 @@
NEXT_OPCODE(op_get_rest_length);
}
- case op_copy_rest: {
+ case op_create_rest: {
noticeArgumentsUse();
- Node* array = get(VirtualRegister(currentInstruction[1].u.operand));
Node* arrayLength = get(VirtualRegister(currentInstruction[2].u.operand));
- addToGraph(CopyRest, OpInfo(currentInstruction[3].u.unsignedValue),
- array, arrayLength);
- NEXT_OPCODE(op_copy_rest);
+ set(VirtualRegister(currentInstruction[1].u.operand),
+ addToGraph(CreateRest, OpInfo(currentInstruction[3].u.unsignedValue), arrayLength));
+ NEXT_OPCODE(op_create_rest);
}
// === Bitwise operations ===
Modified: trunk/Source/_javascript_Core/dfg/DFGCallArrayAllocatorSlowPathGenerator.h (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGCallArrayAllocatorSlowPathGenerator.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGCallArrayAllocatorSlowPathGenerator.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -84,7 +84,7 @@
, m_function(function)
, m_resultGPR(resultGPR)
, m_contiguousStructure(contiguousStructure)
- , m_arrayStorageStructure(arrayStorageStructure)
+ , m_arrayStorageOrContiguousStructure(arrayStorageStructure)
, m_sizeGPR(sizeGPR)
{
jit->silentSpillAllRegistersImpl(false, m_plans, resultGPR);
@@ -97,12 +97,15 @@
for (unsigned i = 0; i < m_plans.size(); ++i)
jit->silentSpill(m_plans[i]);
GPRReg scratchGPR = AssemblyHelpers::selectScratchGPR(m_sizeGPR);
- MacroAssembler::Jump bigLength = jit->m_jit.branch32(MacroAssembler::AboveOrEqual, m_sizeGPR, MacroAssembler::TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
- jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
- MacroAssembler::Jump done = jit->m_jit.jump();
- bigLength.link(&jit->m_jit);
- jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_arrayStorageStructure), scratchGPR);
- done.link(&jit->m_jit);
+ if (m_contiguousStructure != m_arrayStorageOrContiguousStructure) {
+ MacroAssembler::Jump bigLength = jit->m_jit.branch32(MacroAssembler::AboveOrEqual, m_sizeGPR, MacroAssembler::TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
+ jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
+ MacroAssembler::Jump done = jit->m_jit.jump();
+ bigLength.link(&jit->m_jit);
+ jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_arrayStorageOrContiguousStructure), scratchGPR);
+ done.link(&jit->m_jit);
+ } else
+ jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
jit->callOperation(m_function, m_resultGPR, scratchGPR, m_sizeGPR);
GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
for (unsigned i = m_plans.size(); i--;)
@@ -115,7 +118,7 @@
P_JITOperation_EStZ m_function;
GPRReg m_resultGPR;
Structure* m_contiguousStructure;
- Structure* m_arrayStorageStructure;
+ Structure* m_arrayStorageOrContiguousStructure;
GPRReg m_sizeGPR;
Vector<SilentRegisterSavePlan, 2> m_plans;
};
Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -235,7 +235,7 @@
case op_create_lexical_environment:
case op_get_parent_scope:
case op_catch:
- case op_copy_rest:
+ case op_create_rest:
case op_get_rest_length:
case op_log_shadow_chicken_prologue:
case op_log_shadow_chicken_tail:
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -1097,9 +1097,16 @@
return;
}
- case CopyRest: {
+ case CreateRest: {
+ if (!graph.isWatchingHavingABadTimeWatchpoint(node)) {
+ // This means we're already having a bad time.
+ read(World);
+ write(Heap);
+ return;
+ }
read(Stack);
- write(Heap);
+ read(HeapObjectCount);
+ write(HeapObjectCount);
return;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -245,7 +245,6 @@
case GetStack:
case GetFromArguments:
case PutToArguments:
- case CopyRest:
case LogShadowChickenPrologue:
case LogShadowChickenTail:
case GetDynamicVar:
@@ -285,6 +284,7 @@
case StrCat:
case StringReplace:
case StringReplaceRegExp:
+ case CreateRest:
return true;
case MultiPutByOffset:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -1500,9 +1500,9 @@
break;
}
- case CopyRest: {
- fixEdge<KnownCellUse>(node->child1());
- fixEdge<KnownInt32Use>(node->child2());
+ case CreateRest: {
+ watchHavingABadTime(node);
+ fixEdge<KnownInt32Use>(node->child1());
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -659,6 +659,12 @@
doToChildren(node, [&] (Edge edge) { result |= edge == child; });
return result;
}
+
+ bool isWatchingHavingABadTimeWatchpoint(Node* node)
+ {
+ JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
+ return watchpoints().isWatched(globalObject->havingABadTimeWatchpoint());
+ }
Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -2319,7 +2319,7 @@
unsigned numberOfArgumentsToSkip()
{
- ASSERT(op() == CopyRest || op() == GetRestLength);
+ ASSERT(op() == CreateRest || op() == GetRestLength);
return static_cast<unsigned>(m_opInfo);
}
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -291,7 +291,7 @@
macro(NewRegexp, NodeResultJS) \
/* Rest Parameter */\
macro(GetRestLength, NodeResultInt32) \
- macro(CopyRest, NodeMustGenerate) \
+ macro(CreateRest, NodeResultJS | NodeMustGenerate) \
\
/* Support for allocation sinking. */\
macro(PhantomNewObject, NodeResultJS | NodeMustGenerate) \
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -1102,17 +1102,16 @@
return result;
}
-void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
+JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- ASSERT(arraySize);
- JSArray* array = jsCast<JSArray*>(arrayAsCell);
- ASSERT(arraySize == array->length());
- array->setLength(exec, arraySize);
- for (unsigned i = 0; i < arraySize; i++)
- array->putDirectIndex(exec, i, argumentStart[i + numberOfParamsToSkip].jsValue());
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
+ static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
+ JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
+ return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
}
size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -121,7 +121,7 @@
JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment*);
JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount);
JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee);
-void JIT_OPERATION operationCopyRest(ExecState*, JSCell*, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize);
+JSCell* JIT_OPERATION operationCreateRest(ExecState*, Register* argumentStart, unsigned numberOfArgumentsToSkip, unsigned arraySize);
double JIT_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL;
size_t JIT_OPERATION operationObjectIsObject(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
size_t JIT_OPERATION operationObjectIsFunction(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -836,6 +836,7 @@
case NewArray:
case NewArrayWithSize:
+ case CreateRest:
case NewArrayBuffer: {
setPrediction(SpecArray);
break;
@@ -1063,7 +1064,6 @@
case ExitOK:
case LoadVarargs:
case ForwardVarargs:
- case CopyRest:
case PutDynamicVar:
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -346,7 +346,7 @@
case GetMyArgumentByVal:
case GetMyArgumentByValOutOfBounds:
case ForwardVarargs:
- case CopyRest:
+ case CreateRest:
case StringReplace:
case StringReplaceRegExp:
case GetRegExpObjectLastIndex:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -6482,30 +6482,75 @@
cellResult(resultGPR, node);
}
-void SpeculativeJIT::compileCopyRest(Node* node)
+void SpeculativeJIT::compileCreateRest(Node* node)
{
- ASSERT(node->op() == CopyRest);
+ ASSERT(node->op() == CreateRest);
- SpeculateCellOperand array(this, node->child1());
+#if !CPU(X86)
+ if (m_jit.graph().isWatchingHavingABadTimeWatchpoint(node)) {
+ SpeculateStrictInt32Operand arrayLength(this, node->child1());
+ GPRTemporary arrayResult(this);
+
+ GPRReg arrayLengthGPR = arrayLength.gpr();
+ GPRReg arrayResultGPR = arrayResult.gpr();
+
+ bool shouldAllowForArrayStorageStructureForLargeArrays = false;
+ compileAllocateNewArrayWithSize(m_jit.graph().globalObjectFor(node->origin.semantic), arrayResultGPR, arrayLengthGPR, ArrayWithContiguous, shouldAllowForArrayStorageStructureForLargeArrays);
+
+ GPRTemporary argumentsStart(this);
+ GPRReg argumentsStartGPR = argumentsStart.gpr();
+
+ emitGetArgumentStart(node->origin.semantic, argumentsStartGPR);
+
+ GPRTemporary butterfly(this);
+ GPRTemporary currentLength(this);
+#if USE(JSVALUE64)
+ GPRTemporary value(this);
+ JSValueRegs valueRegs = JSValueRegs(value.gpr());
+#else
+ GPRTemporary valueTag(this);
+ GPRTemporary valuePayload(this);
+ JSValueRegs valueRegs = JSValueRegs(valueTag.gpr(), valuePayload.gpr());
+#endif
+
+ GPRReg currentLengthGPR = currentLength.gpr();
+ GPRReg butterflyGPR = butterfly.gpr();
+
+ m_jit.loadPtr(MacroAssembler::Address(arrayResultGPR, JSObject::butterflyOffset()), butterflyGPR);
+
+ CCallHelpers::Jump skipLoop = m_jit.branch32(MacroAssembler::Equal, arrayLengthGPR, TrustedImm32(0));
+ m_jit.zeroExtend32ToPtr(arrayLengthGPR, currentLengthGPR);
+ m_jit.addPtr(Imm32(sizeof(Register) * node->numberOfArgumentsToSkip()), argumentsStartGPR);
+
+ auto loop = m_jit.label();
+ m_jit.sub32(TrustedImm32(1), currentLengthGPR);
+ m_jit.loadValue(JITCompiler::BaseIndex(argumentsStartGPR, currentLengthGPR, MacroAssembler::TimesEight), valueRegs);
+ m_jit.storeValue(valueRegs, MacroAssembler::BaseIndex(butterflyGPR, currentLengthGPR, MacroAssembler::TimesEight));
+ m_jit.branch32(MacroAssembler::NotEqual, currentLengthGPR, TrustedImm32(0)).linkTo(loop, &m_jit);
+
+ skipLoop.link(&m_jit);
+ cellResult(arrayResultGPR, node);
+ return;
+ }
+#endif // !CPU(X86)
+
+ SpeculateStrictInt32Operand arrayLength(this, node->child1());
GPRTemporary argumentsStart(this);
- SpeculateStrictInt32Operand arrayLength(this, node->child2());
+ GPRTemporary numberOfArgumentsToSkip(this);
- GPRReg arrayGPR = array.gpr();
+ GPRReg arrayLengthGPR = arrayLength.gpr();
GPRReg argumentsStartGPR = argumentsStart.gpr();
- GPRReg arrayLengthGPR = arrayLength.gpr();
- CCallHelpers::Jump done = m_jit.branch32(MacroAssembler::Equal, arrayLengthGPR, TrustedImm32(0));
+ emitGetArgumentStart(node->origin.semantic, argumentsStartGPR);
- emitGetArgumentStart(node->origin.semantic, argumentsStartGPR);
- silentSpillAllRegisters(argumentsStartGPR);
- // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length
- callOperation(operationCopyRest, arrayGPR, argumentsStartGPR, Imm32(node->numberOfArgumentsToSkip()), arrayLengthGPR);
- silentFillAllRegisters(argumentsStartGPR);
+ flushRegisters();
+
+ GPRFlushedCallResult result(this);
+ GPRReg resultGPR = result.gpr();
+ callOperation(operationCreateRest, resultGPR, argumentsStartGPR, Imm32(node->numberOfArgumentsToSkip()), arrayLengthGPR);
m_jit.exceptionCheck();
- done.link(&m_jit);
-
- noResult(node);
+ cellResult(resultGPR, node);
}
void SpeculativeJIT::compileGetRestLength(Node* node)
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -760,6 +760,8 @@
void compileIsTypedArrayView(Node*);
void emitCall(Node*);
+
+ void compileAllocateNewArrayWithSize(JSGlobalObject*, GPRReg resultGPR, GPRReg sizeGPR, IndexingType, bool shouldConvertLargeSizeToArrayStorage = true);
// Called once a node has completed code generation but prior to setting
// its result, to free up its children. (This must happen prior to setting
@@ -1274,10 +1276,10 @@
return appendCall(operation);
}
- JITCompiler::Call callOperation(V_JITOperation_ECRUiUi operation, GPRReg arg1, GPRReg arg2, Imm32 arg3, GPRReg arg4)
+ JITCompiler::Call callOperation(C_JITOperation_ERUiUi operation, GPRReg result, GPRReg arg1, Imm32 arg2, GPRReg arg3)
{
- m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.asTrustedImm32(), arg4);
- return appendCall(operation);
+ m_jit.setupArgumentsWithExecState(arg1, arg2.asTrustedImm32(), arg3);
+ return appendCallSetResult(operation, result);
}
JITCompiler::Call callOperation(C_JITOperation_EJscI operation, GPRReg result, GPRReg arg1, UniquedStringImpl* impl)
@@ -2487,7 +2489,7 @@
void compilePutToArguments(Node*);
void compileCreateScopedArguments(Node*);
void compileCreateClonedArguments(Node*);
- void compileCopyRest(Node*);
+ void compileCreateRest(Node*);
void compileGetRestLength(Node*);
void compileNotifyWrite(Node*);
bool compileRegExpExec(Node*);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -3890,51 +3890,11 @@
if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
SpeculateStrictInt32Operand size(this, node->child1());
GPRTemporary result(this);
- GPRTemporary storage(this);
- GPRTemporary scratch(this);
- GPRTemporary scratch2(this);
-
+
GPRReg sizeGPR = size.gpr();
GPRReg resultGPR = result.gpr();
- GPRReg storageGPR = storage.gpr();
- GPRReg scratchGPR = scratch.gpr();
- GPRReg scratch2GPR = scratch2.gpr();
-
- MacroAssembler::JumpList slowCases;
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
-
- ASSERT((1 << 3) == sizeof(JSValue));
- m_jit.move(sizeGPR, scratchGPR);
- m_jit.lshift32(TrustedImm32(3), scratchGPR);
- m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
- slowCases.append(
- emitAllocateBasicStorage(resultGPR, storageGPR));
- m_jit.subPtr(scratchGPR, storageGPR);
- Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
- emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
-
- m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-
- if (hasDouble(node->indexingType())) {
- JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
-
- m_jit.move(sizeGPR, scratchGPR);
- MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
- MacroAssembler::Label loop = m_jit.label();
- m_jit.sub32(TrustedImm32(1), scratchGPR);
- m_jit.store32(TrustedImm32(nan.u.asBits.tag), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(TrustedImm32(nan.u.asBits.payload), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
- m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
- done.link(&m_jit);
- }
-
- addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
- slowCases, this, operationNewArrayWithSize, resultGPR,
- globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()),
- globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage),
- sizeGPR));
-
+
+ compileAllocateNewArrayWithSize(globalObject, resultGPR, sizeGPR, node->indexingType());
cellResult(resultGPR, node);
break;
}
@@ -4908,8 +4868,8 @@
break;
}
- case CopyRest: {
- compileCopyRest(node);
+ case CreateRest: {
+ compileCreateRest(node);
break;
}
@@ -5438,6 +5398,53 @@
doubleResult(result.fpr(), node);
}
+void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)
+{
+ GPRTemporary storage(this);
+ GPRTemporary scratch(this);
+ GPRTemporary scratch2(this);
+
+ GPRReg storageGPR = storage.gpr();
+ GPRReg scratchGPR = scratch.gpr();
+ GPRReg scratch2GPR = scratch2.gpr();
+
+ MacroAssembler::JumpList slowCases;
+ if (shouldConvertLargeSizeToArrayStorage)
+ slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
+
+ ASSERT((1 << 3) == sizeof(JSValue));
+ m_jit.move(sizeGPR, scratchGPR);
+ m_jit.lshift32(TrustedImm32(3), scratchGPR);
+ m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
+ slowCases.append(
+ emitAllocateBasicStorage(resultGPR, storageGPR));
+ m_jit.subPtr(scratchGPR, storageGPR);
+ Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType);
+ emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
+
+ m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+ m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+
+ if (hasDouble(indexingType)) {
+ JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
+
+ m_jit.move(sizeGPR, scratchGPR);
+ MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
+ MacroAssembler::Label loop = m_jit.label();
+ m_jit.sub32(TrustedImm32(1), scratchGPR);
+ m_jit.store32(TrustedImm32(nan.u.asBits.tag), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+ m_jit.store32(TrustedImm32(nan.u.asBits.payload), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+ m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
+ done.link(&m_jit);
+ }
+
+ addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
+ slowCases, this, operationNewArrayWithSize, resultGPR,
+ structure,
+ shouldConvertLargeSizeToArrayStorage ? globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : structure,
+ sizeGPR));
+}
+
#endif
} } // namespace JSC::DFG
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -3852,49 +3852,9 @@
if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
SpeculateStrictInt32Operand size(this, node->child1());
GPRTemporary result(this);
- GPRTemporary storage(this);
- GPRTemporary scratch(this);
- GPRTemporary scratch2(this);
-
GPRReg sizeGPR = size.gpr();
GPRReg resultGPR = result.gpr();
- GPRReg storageGPR = storage.gpr();
- GPRReg scratchGPR = scratch.gpr();
- GPRReg scratch2GPR = scratch2.gpr();
-
- MacroAssembler::JumpList slowCases;
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
-
- ASSERT((1 << 3) == sizeof(JSValue));
- m_jit.move(sizeGPR, scratchGPR);
- m_jit.lshift32(TrustedImm32(3), scratchGPR);
- m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
- slowCases.append(
- emitAllocateBasicStorage(resultGPR, storageGPR));
- m_jit.subPtr(scratchGPR, storageGPR);
- Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
- emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
-
- m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-
- if (hasDouble(node->indexingType())) {
- m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), scratchGPR);
- m_jit.move(sizeGPR, scratch2GPR);
- MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratch2GPR);
- MacroAssembler::Label loop = m_jit.label();
- m_jit.sub32(TrustedImm32(1), scratch2GPR);
- m_jit.store64(scratchGPR, MacroAssembler::BaseIndex(storageGPR, scratch2GPR, MacroAssembler::TimesEight));
- m_jit.branchTest32(MacroAssembler::NonZero, scratch2GPR).linkTo(loop, &m_jit);
- done.link(&m_jit);
- }
-
- addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
- slowCases, this, operationNewArrayWithSize, resultGPR,
- globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()),
- globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage),
- sizeGPR));
-
+ compileAllocateNewArrayWithSize(globalObject, resultGPR, sizeGPR, node->indexingType());
cellResult(resultGPR, node);
break;
}
@@ -4855,8 +4815,8 @@
compileCreateClonedArguments(node);
break;
}
- case CopyRest: {
- compileCopyRest(node);
+ case CreateRest: {
+ compileCreateRest(node);
break;
}
@@ -5505,6 +5465,51 @@
doubleResult(result.fpr(), node);
}
+void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)
+{
+ GPRTemporary storage(this);
+ GPRTemporary scratch(this);
+ GPRTemporary scratch2(this);
+
+ GPRReg storageGPR = storage.gpr();
+ GPRReg scratchGPR = scratch.gpr();
+ GPRReg scratch2GPR = scratch2.gpr();
+
+ MacroAssembler::JumpList slowCases;
+ if (shouldConvertLargeSizeToArrayStorage)
+ slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
+
+ ASSERT((1 << 3) == sizeof(JSValue));
+ m_jit.move(sizeGPR, scratchGPR);
+ m_jit.lshift32(TrustedImm32(3), scratchGPR);
+ m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
+ slowCases.append(
+ emitAllocateBasicStorage(resultGPR, storageGPR));
+ m_jit.subPtr(scratchGPR, storageGPR);
+ Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType);
+ emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
+
+ m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+ m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+
+ if (hasDouble(indexingType)) {
+ m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), scratchGPR);
+ m_jit.move(sizeGPR, scratch2GPR);
+ MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratch2GPR);
+ MacroAssembler::Label loop = m_jit.label();
+ m_jit.sub32(TrustedImm32(1), scratch2GPR);
+ m_jit.store64(scratchGPR, MacroAssembler::BaseIndex(storageGPR, scratch2GPR, MacroAssembler::TimesEight));
+ m_jit.branchTest32(MacroAssembler::NonZero, scratch2GPR).linkTo(loop, &m_jit);
+ done.link(&m_jit);
+ }
+
+ addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
+ slowCases, this, operationNewArrayWithSize, resultGPR,
+ structure,
+ shouldConvertLargeSizeToArrayStorage ? globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : structure,
+ sizeGPR));
+}
+
#endif
} } // namespace JSC::DFG
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -229,7 +229,7 @@
case PutGetterSetterById:
case PutGetterByVal:
case PutSetterByVal:
- case CopyRest:
+ case CreateRest:
case GetRestLength:
case RegExpExec:
case RegExpTest:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -972,8 +972,8 @@
case CheckWatchdogTimer:
compileCheckWatchdogTimer();
break;
- case CopyRest:
- compileCopyRest();
+ case CreateRest:
+ compileCreateRest();
break;
case GetRestLength:
compileGetRestLength();
@@ -3863,26 +3863,40 @@
setJSValue(result);
}
- void compileCopyRest()
- {
- LBasicBlock doCopyRest = m_out.newBlock();
- LBasicBlock continuation = m_out.newBlock();
+ void compileCreateRest()
+ {
+ if (m_graph.isWatchingHavingABadTimeWatchpoint(m_node)) {
+ LBasicBlock continuation = m_out.newBlock();
+ LValue arrayLength = lowInt32(m_node->child1());
+ LBasicBlock loopStart = m_out.newBlock();
+ bool shouldLargeArraySizeCreateArrayStorage = false;
+ LValue array = compileAllocateArrayWithSize(arrayLength, ArrayWithContiguous, shouldLargeArraySizeCreateArrayStorage);
- LValue arrayLength = lowInt32(m_node->child2());
+ LValue butterfly = m_out.loadPtr(array, m_heaps.JSObject_butterfly);
+ ValueFromBlock startLength = m_out.anchor(arrayLength);
+ LValue argumentRegion = m_out.add(getArgumentsStart(), m_out.constInt64(sizeof(Register) * m_node->numberOfArgumentsToSkip()));
+ m_out.branch(m_out.equal(arrayLength, m_out.constInt32(0)),
+ unsure(continuation), unsure(loopStart));
- m_out.branch(
- m_out.equal(arrayLength, m_out.constInt32(0)),
- unsure(continuation), unsure(doCopyRest));
-
- LBasicBlock lastNext = m_out.appendTo(doCopyRest, continuation);
- // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length
+ LBasicBlock lastNext = m_out.appendTo(loopStart, continuation);
+ LValue phiOffset = m_out.phi(Int32, startLength);
+ LValue currentOffset = m_out.sub(phiOffset, m_out.int32One);
+ m_out.addIncomingToPhi(phiOffset, m_out.anchor(currentOffset));
+ LValue loadedValue = m_out.load64(m_out.baseIndex(m_heaps.variables, argumentRegion, m_out.zeroExtPtr(currentOffset)));
+ IndexedAbstractHeap& heap = m_heaps.indexedContiguousProperties;
+ m_out.store(loadedValue, m_out.baseIndex(heap, butterfly, m_out.zeroExtPtr(currentOffset)), Output::Store64);
+ m_out.branch(m_out.equal(currentOffset, m_out.constInt32(0)), unsure(continuation), unsure(loopStart));
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(array);
+ return;
+ }
+
+ LValue arrayLength = lowInt32(m_node->child1());
+ LValue argumentStart = getArgumentsStart();
LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip());
- vmCall(
- Void,m_out.operation(operationCopyRest), m_callFrame, lowCell(m_node->child1()),
- getArgumentsStart(), numberOfArgumentsToSkip, arrayLength);
- m_out.jump(continuation);
-
- m_out.appendTo(continuation, lastNext);
+ setJSValue(vmCall(
+ Int64, m_out.operation(operationCreateRest), m_callFrame, argumentStart, numberOfArgumentsToSkip, arrayLength));
}
void compileGetRestLength()
@@ -4028,81 +4042,99 @@
m_out.constIntPtr(structure), m_out.constIntPtr(m_node->startConstant()),
m_out.constIntPtr(m_node->numConstants())));
}
-
- void compileNewArrayWithSize()
+
+ LValue compileAllocateArrayWithSize(LValue publicLength, IndexingType indexingType, bool shouldLargeArraySizeCreateArrayStorage = true)
{
- LValue publicLength = lowInt32(m_node->child1());
-
JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
- Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
- m_node->indexingType());
-
- if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
- ASSERT(
- hasUndecided(structure->indexingType())
- || hasInt32(structure->indexingType())
- || hasDouble(structure->indexingType())
- || hasContiguous(structure->indexingType()));
+ Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType);
+ ASSERT(
+ hasUndecided(structure->indexingType())
+ || hasInt32(structure->indexingType())
+ || hasDouble(structure->indexingType())
+ || hasContiguous(structure->indexingType()));
- LBasicBlock fastCase = m_out.newBlock();
- LBasicBlock largeCase = m_out.newBlock();
- LBasicBlock failCase = m_out.newBlock();
- LBasicBlock slowCase = m_out.newBlock();
- LBasicBlock continuation = m_out.newBlock();
-
+ LBasicBlock fastCase = m_out.newBlock();
+ LBasicBlock largeCase = shouldLargeArraySizeCreateArrayStorage ? m_out.newBlock() : nullptr;
+ LBasicBlock failCase = m_out.newBlock();
+ LBasicBlock continuation = m_out.newBlock();
+ LBasicBlock lastNext = nullptr;
+ if (shouldLargeArraySizeCreateArrayStorage) {
m_out.branch(
m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)),
rarely(largeCase), usually(fastCase));
+ lastNext = m_out.appendTo(fastCase, largeCase);
+ }
- LBasicBlock lastNext = m_out.appendTo(fastCase, largeCase);
-
- // We don't round up to BASE_VECTOR_LEN for new Array(blah).
- LValue vectorLength = publicLength;
-
- LValue payloadSize =
- m_out.shl(m_out.zeroExt(vectorLength, pointerType()), m_out.constIntPtr(3));
-
- LValue butterflySize = m_out.add(
- payloadSize, m_out.constIntPtr(sizeof(IndexingHeader)));
-
- LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, failCase);
-
- LValue butterfly = m_out.sub(endOfStorage, payloadSize);
-
- LValue object = allocateObject<JSArray>(structure, butterfly, failCase);
-
- m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
- m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
+
+ // We don't round up to BASE_VECTOR_LEN for new Array(blah).
+ LValue vectorLength = publicLength;
+
+ LValue payloadSize =
+ m_out.shl(m_out.zeroExt(vectorLength, pointerType()), m_out.constIntPtr(3));
+
+ LValue butterflySize = m_out.add(
+ payloadSize, m_out.constIntPtr(sizeof(IndexingHeader)));
+
+ LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, failCase);
+
+ LValue butterfly = m_out.sub(endOfStorage, payloadSize);
+
+ LValue object = allocateObject<JSArray>(structure, butterfly, failCase);
+
+ m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
+ m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
- initializeArrayElements(m_node->indexingType(), vectorLength, butterfly);
-
- ValueFromBlock fastResult = m_out.anchor(object);
- m_out.jump(continuation);
-
+ initializeArrayElements(indexingType, vectorLength, butterfly);
+
+ ValueFromBlock fastResult = m_out.anchor(object);
+ m_out.jump(continuation);
+
+ LValue structureValue;
+ if (shouldLargeArraySizeCreateArrayStorage) {
+ LBasicBlock slowCase = m_out.newBlock();
+
m_out.appendTo(largeCase, failCase);
ValueFromBlock largeStructure = m_out.anchor(m_out.constIntPtr(
globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)));
m_out.jump(slowCase);
-
+
m_out.appendTo(failCase, slowCase);
ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure));
m_out.jump(slowCase);
-
+
m_out.appendTo(slowCase, continuation);
- LValue structureValue = m_out.phi(
+ structureValue = m_out.phi(
pointerType(), largeStructure, failStructure);
- LValue slowResultValue = lazySlowPath(
- [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
- return createLazyCallGenerator(
- operationNewArrayWithSize, locations[0].directGPR(),
- locations[1].directGPR(), locations[2].directGPR());
- },
- structureValue, publicLength);
- ValueFromBlock slowResult = m_out.anchor(slowResultValue);
- m_out.jump(continuation);
-
- m_out.appendTo(continuation, lastNext);
- setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
+ } else {
+ ASSERT(!lastNext);
+ lastNext = m_out.appendTo(failCase, continuation);
+ structureValue = m_out.constIntPtr(structure);
+ }
+
+ LValue slowResultValue = lazySlowPath(
+ [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
+ return createLazyCallGenerator(
+ operationNewArrayWithSize, locations[0].directGPR(),
+ locations[1].directGPR(), locations[2].directGPR());
+ },
+ structureValue, publicLength);
+ ValueFromBlock slowResult = m_out.anchor(slowResultValue);
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ return m_out.phi(pointerType(), fastResult, slowResult);
+ }
+
+ void compileNewArrayWithSize()
+ {
+ LValue publicLength = lowInt32(m_node->child1());
+
+ JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
+ Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
+ m_node->indexingType());
+
+ if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
+ setJSValue(compileAllocateArrayWithSize(publicLength, m_node->indexingType()));
return;
}
Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.h (204438 => 204439)
--- trunk/Source/_javascript_Core/interpreter/CallFrame.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -211,6 +211,7 @@
// arguments(0) will not fetch the 'this' value. To get/set 'this',
// use thisValue() and setThisValue() below.
+ JSValue* addressOfArgumentsStart() const { return bitwise_cast<JSValue*>(this + argumentOffset(0)); }
JSValue argument(size_t argument)
{
if (argument >= argumentCount())
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -231,7 +231,7 @@
DEFINE_OP(op_create_scoped_arguments)
DEFINE_OP(op_create_cloned_arguments)
DEFINE_OP(op_argument_count)
- DEFINE_OP(op_copy_rest)
+ DEFINE_OP(op_create_rest)
DEFINE_OP(op_get_rest_length)
DEFINE_OP(op_check_tdz)
DEFINE_OP(op_assert)
Modified: trunk/Source/_javascript_Core/jit/JIT.h (204438 => 204439)
--- trunk/Source/_javascript_Core/jit/JIT.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -493,7 +493,7 @@
void emit_op_create_scoped_arguments(Instruction*);
void emit_op_create_cloned_arguments(Instruction*);
void emit_op_argument_count(Instruction*);
- void emit_op_copy_rest(Instruction*);
+ void emit_op_create_rest(Instruction*);
void emit_op_get_rest_length(Instruction*);
void emit_op_check_tdz(Instruction*);
void emit_op_assert(Instruction*);
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -1458,9 +1458,9 @@
emitPutVirtualRegister(dst, result);
}
-void JIT::emit_op_copy_rest(Instruction* currentInstruction)
+void JIT::emit_op_create_rest(Instruction* currentInstruction)
{
- JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_copy_rest);
+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_rest);
slowPathCall.call();
}
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (204438 => 204439)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -262,7 +262,7 @@
typedef void (JIT_OPERATION *V_JITOperation_EVm)(ExecState*, VM*);
typedef void (JIT_OPERATION *V_JITOperation_J)(EncodedJSValue);
typedef void (JIT_OPERATION *V_JITOperation_Z)(int32_t);
-typedef void (JIT_OPERATION *V_JITOperation_ECRUiUi)(ExecState*, JSCell*, Register*, uint32_t, uint32_t);
+typedef JSCell* (JIT_OPERATION *C_JITOperation_ERUiUi)(ExecState*, Register*, uint32_t, uint32_t);
typedef void (JIT_OPERATION *V_JITOperation_EOJIUi)(ExecState*, JSObject*, EncodedJSValue, UniquedStringImpl*, uint32_t);
typedef char* (JIT_OPERATION *P_JITOperation_E)(ExecState*);
typedef char* (JIT_OPERATION *P_JITOperation_EC)(ExecState*, JSCell*);
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (204438 => 204439)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-08-13 02:14:42 UTC (rev 204439)
@@ -1762,9 +1762,9 @@
callOpcodeSlowPath(_slow_path_to_index_string)
dispatch(3)
-_llint_op_copy_rest:
+_llint_op_create_rest:
traceExecution()
- callOpcodeSlowPath(_slow_path_copy_rest)
+ callOpcodeSlowPath(_slow_path_create_rest)
dispatch(4)
_llint_op_instanceof:
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (204438 => 204439)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2016-08-13 02:14:42 UTC (rev 204439)
@@ -848,20 +848,15 @@
RETURN(resolvedScope);
}
-SLOW_PATH_DECL(slow_path_copy_rest)
+SLOW_PATH_DECL(slow_path_create_rest)
{
BEGIN();
unsigned arraySize = OP_C(2).jsValue().asUInt32();
- if (!arraySize) {
- ASSERT(!jsCast<JSArray*>(OP(1).jsValue())->length());
- END();
- }
- JSArray* array = jsCast<JSArray*>(OP(1).jsValue());
- ASSERT(arraySize == array->length());
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
unsigned numParamsToSkip = pc[3].u.unsignedValue;
- for (unsigned i = 0; i < arraySize; i++)
- array->putDirectIndex(exec, i, exec->uncheckedArgument(i + numParamsToSkip));
- END();
+ JSValue* argumentsToCopyRegion = exec->addressOfArgumentsStart() + numParamsToSkip;
+ RETURN(constructArray(exec, structure, argumentsToCopyRegion, arraySize));
}
SLOW_PATH_DECL(slow_path_get_by_id_with_this)
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (204438 => 204439)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2016-08-13 02:14:42 UTC (rev 204439)
@@ -253,7 +253,7 @@
SLOW_PATH_HIDDEN_DECL(slow_path_create_lexical_environment);
SLOW_PATH_HIDDEN_DECL(slow_path_push_with_scope);
SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope);
-SLOW_PATH_HIDDEN_DECL(slow_path_copy_rest);
+SLOW_PATH_HIDDEN_DECL(slow_path_create_rest);
SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id_with_this);
SLOW_PATH_HIDDEN_DECL(slow_path_get_by_val_with_this);
SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id_with_this);