Title: [166392] trunk
Revision
166392
Author
[email protected]
Date
2014-03-27 18:10:25 -0700 (Thu, 27 Mar 2014)

Log Message

Support spread operand in |new| expressions
https://bugs.webkit.org/show_bug.cgi?id=130877

Reviewed by Michael Saboff.

Source/_javascript_Core:

Add support for the spread operator being applied in
|new| expressions.  This required adding support for
a new opcode, op_construct_varargs.  This is a relatively
simple refactoring of the call_varargs implementation.

* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CallLinkInfo.cpp:
(JSC::CallLinkInfo::unlink):
* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::callTypeFor):
(JSC::CallLinkInfo::specializationKind):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitCallVarargs):
(JSC::BytecodeGenerator::emitConstructVarargs):
(JSC::BytecodeGenerator::emitConstruct):
* bytecompiler/BytecodeGenerator.h:
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITCall.cpp:
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
(JSC::JIT::emit_op_construct_varargs):
(JSC::JIT::emitSlow_op_construct_varargs):
* jit/JITCall32_64.cpp:
(JSC::JIT::emitSlow_op_construct_varargs):
(JSC::JIT::emit_op_construct_varargs):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LLIntSlowPaths.h:
* llint/LowLevelInterpreter.asm:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseMemberExpression):

LayoutTests:

Correctness and performance tests for spread operands

* js/parser-syntax-check-expected.txt:
* js/regress/call-spread-expected.txt: Added.
* js/regress/call-spread.html: Added.
* js/regress/new-spread-expected.txt: Added.
* js/regress/new-spread.html: Added.
* js/regress/script-tests/call-spread.js: Added.
(testFunction):
(test2):
(test3):
* js/regress/script-tests/new-spread.js: Added.
(testFunction):
(test2):
(test3):
* js/script-tests/parser-syntax-check.js:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (166391 => 166392)


--- trunk/LayoutTests/ChangeLog	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/LayoutTests/ChangeLog	2014-03-28 01:10:25 UTC (rev 166392)
@@ -1,3 +1,27 @@
+2014-03-27  Oliver Hunt  <[email protected]>
+
+        Support spread operand in |new| expressions
+        https://bugs.webkit.org/show_bug.cgi?id=130877
+
+        Reviewed by Michael Saboff.
+
+        Correctness and performance tests for spread operands
+
+        * js/parser-syntax-check-expected.txt:
+        * js/regress/call-spread-expected.txt: Added.
+        * js/regress/call-spread.html: Added.
+        * js/regress/new-spread-expected.txt: Added.
+        * js/regress/new-spread.html: Added.
+        * js/regress/script-tests/call-spread.js: Added.
+        (testFunction):
+        (test2):
+        (test3):
+        * js/regress/script-tests/new-spread.js: Added.
+        (testFunction):
+        (test2):
+        (test3):
+        * js/script-tests/parser-syntax-check.js:
+
 2014-03-27  Bem Jones-Bey  <[email protected]>
 
         [CSS Shapes][css clip-path] rounded corner calculation for box shapes is wrong

Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (166391 => 166392)


--- trunk/LayoutTests/js/parser-syntax-check-expected.txt	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt	2014-03-28 01:10:25 UTC (rev 166392)
@@ -668,12 +668,12 @@
 PASS Valid:   "function f() { o.foo(...bar) }"
 PASS Valid:   "o[foo](...bar)"
 PASS Valid:   "function f() { o[foo](...bar) }"
-PASS Invalid: "new foo(...bar)"
-PASS Invalid: "function f() { new foo(...bar) }"
-PASS Invalid: "new o.foo(...bar)"
-PASS Invalid: "function f() { new o.foo(...bar) }"
-PASS Invalid: "new o[foo](...bar)"
-PASS Invalid: "function f() { new o[foo](...bar) }"
+PASS Valid:   "new foo(...bar)"
+PASS Valid:   "function f() { new foo(...bar) }"
+PASS Valid:   "new o.foo(...bar)"
+PASS Valid:   "function f() { new o.foo(...bar) }"
+PASS Valid:   "new o[foo](...bar)"
+PASS Valid:   "function f() { new o[foo](...bar) }"
 PASS Invalid: "foo(...)"
 PASS Invalid: "function f() { foo(...) }"
 PASS Invalid: "o.foo(...)"

Added: trunk/LayoutTests/js/regress/call-spread-expected.txt (0 => 166392)


--- trunk/LayoutTests/js/regress/call-spread-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/call-spread-expected.txt	2014-03-28 01:10:25 UTC (rev 166392)
@@ -0,0 +1,10 @@
+JSRegress/call-spread
+
+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/call-spread.html (0 => 166392)


--- trunk/LayoutTests/js/regress/call-spread.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/call-spread.html	2014-03-28 01:10:25 UTC (rev 166392)
@@ -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/new-spread-expected.txt (0 => 166392)


--- trunk/LayoutTests/js/regress/new-spread-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/new-spread-expected.txt	2014-03-28 01:10:25 UTC (rev 166392)
@@ -0,0 +1,10 @@
+JSRegress/new-spread
+
+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/new-spread.html (0 => 166392)


--- trunk/LayoutTests/js/regress/new-spread.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/new-spread.html	2014-03-28 01:10:25 UTC (rev 166392)
@@ -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/call-spread.js (0 => 166392)


--- trunk/LayoutTests/js/regress/script-tests/call-spread.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/call-spread.js	2014-03-28 01:10:25 UTC (rev 166392)
@@ -0,0 +1,34 @@
+
+function testFunction(a, b)
+{
+    "use strict"
+    result |= 0;
+    return a * 1000 + b * 100 + arguments[2] * 10 + arguments.length ^ (result & 1024);
+}
+
+var arrayArguments = [2, 3, 4]
+var result = 0;
+for (var i = 0; i < 1000000; i++)
+    result += testFunction(...arrayArguments);
+
+for (var i = 0; i < 1000000; i++)
+    result += testFunction(...[1, 2, result, 4]);
+
+function test2() {
+    for (var i = 0; i < 1000000; i++)
+        result += testFunction(...arguments);
+}
+
+test2(1,2,3,4)
+
+
+function test3() {
+    aliasedArguments = arguments;
+    for (var i = 0; i < 1000000; i++)
+        result += testFunction(...aliasedArguments);
+}
+
+test3(1,2,result,4)
+
+if (result != -856444619779264)
+    throw "Result was " + result + " expected -856444619779264";
\ No newline at end of file

Added: trunk/LayoutTests/js/regress/script-tests/new-spread.js (0 => 166392)


--- trunk/LayoutTests/js/regress/script-tests/new-spread.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/new-spread.js	2014-03-28 01:10:25 UTC (rev 166392)
@@ -0,0 +1,34 @@
+
+function testFunction(a, b)
+{
+    "use strict"
+    result |= 0;
+    result += a * 1000 + b * 100 + arguments[2] * 10 + arguments.length ^ (result & 1024);
+}
+
+var arrayArguments = [2, 3, 4]
+var result = 0;
+for (var i = 0; i < 1000000; i++)
+    new testFunction(...arrayArguments);
+
+for (var i = 0; i < 1000000; i++)
+    new testFunction(...[1, 2, result, 4]);
+
+function test2() {
+    for (var i = 0; i < 1000000; i++)
+        new testFunction(...arguments);
+}
+
+test2(1,2,3,4)
+
+
+function test3() {
+    aliasedArguments = arguments;
+    for (var i = 0; i < 1000000; i++)
+        new testFunction(...aliasedArguments);
+}
+
+test3(1,2,result,4)
+
+if (result != -2371153088)
+    throw "Result was " + result + " expected -2371153088";
\ No newline at end of file

Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (166391 => 166392)


--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js	2014-03-28 01:10:25 UTC (rev 166392)
@@ -418,9 +418,9 @@
 valid("foo(...bar)")
 valid("o.foo(...bar)")
 valid("o[foo](...bar)")
-invalid("new foo(...bar)")
-invalid("new o.foo(...bar)")
-invalid("new o[foo](...bar)")
+valid("new foo(...bar)")
+valid("new o.foo(...bar)")
+valid("new o[foo](...bar)")
 invalid("foo(...)")
 invalid("o.foo(...)")
 invalid("o[foo](...)")

Modified: trunk/Source/_javascript_Core/ChangeLog (166391 => 166392)


--- trunk/Source/_javascript_Core/ChangeLog	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-03-28 01:10:25 UTC (rev 166392)
@@ -1,3 +1,54 @@
+2014-03-27  Oliver Hunt  <[email protected]>
+
+        Support spread operand in |new| expressions
+        https://bugs.webkit.org/show_bug.cgi?id=130877
+
+        Reviewed by Michael Saboff.
+
+        Add support for the spread operator being applied in
+        |new| expressions.  This required adding support for
+        a new opcode, op_construct_varargs.  This is a relatively
+        simple refactoring of the call_varargs implementation.
+
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CallLinkInfo.cpp:
+        (JSC::CallLinkInfo::unlink):
+        * bytecode/CallLinkInfo.h:
+        (JSC::CallLinkInfo::callTypeFor):
+        (JSC::CallLinkInfo::specializationKind):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::CodeBlock):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitCallVarargs):
+        (JSC::BytecodeGenerator::emitConstructVarargs):
+        (JSC::BytecodeGenerator::emitConstruct):
+        * bytecompiler/BytecodeGenerator.h:
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        (JSC::JIT::emit_op_construct_varargs):
+        (JSC::JIT::emitSlow_op_construct_varargs):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::emitSlow_op_construct_varargs):
+        (JSC::JIT::emit_op_construct_varargs):
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITOperations.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * llint/LLIntSlowPaths.h:
+        * llint/LowLevelInterpreter.asm:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseMemberExpression):
+
 2014-03-27  Filip Pizlo  <[email protected]>
 
         Revert http://trac.webkit.org/changeset/166386 because it broke builds.

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (166391 => 166392)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2014-03-28 01:10:25 UTC (rev 166392)
@@ -104,6 +104,7 @@
             { "name" : "op_ret", "length" : 2 },
             { "name" : "op_ret_object_or_this", "length" : 3 },
             { "name" : "op_construct", "length" : 9 },
+            { "name" : "op_construct_varargs", "length" : 9 },
             { "name" : "op_strcat", "length" : 4 },
             { "name" : "op_to_primitive", "length" : 3 },
             { "name" : "op_get_pnames", "length" : 6 },

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (166391 => 166392)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2014-03-28 01:10:25 UTC (rev 166392)
@@ -176,6 +176,7 @@
         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
         return;
     }
+    case op_construct_varargs:
     case op_call_varargs: {
         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
@@ -307,6 +308,7 @@
     case op_new_captured_func:
     case op_new_func_exp:
     case op_call_varargs:
+    case op_construct_varargs:
     case op_get_from_scope:
     case op_call:
     case op_call_eval:

Modified: trunk/Source/_javascript_Core/bytecode/CallLinkInfo.cpp (166391 => 166392)


--- trunk/Source/_javascript_Core/bytecode/CallLinkInfo.cpp	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/bytecode/CallLinkInfo.cpp	2014-03-28 01:10:25 UTC (rev 166392)
@@ -46,7 +46,7 @@
     repatchBuffer.relink(
         callReturnLocation,
         repatchBuffer.codeBlock()->vm()->getCTIStub(linkThunkGeneratorFor(
-            callType == Construct ? CodeForConstruct : CodeForCall,
+            (callType == Construct || callType == ConstructVarargs)? CodeForConstruct : CodeForCall,
             isFTL ? MustPreserveRegisters : RegisterPreservationNotRequired)).code());
     hasSeenShouldRepatch = false;
     callee.clear();

Modified: trunk/Source/_javascript_Core/bytecode/CallLinkInfo.h (166391 => 166392)


--- trunk/Source/_javascript_Core/bytecode/CallLinkInfo.h	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/bytecode/CallLinkInfo.h	2014-03-28 01:10:25 UTC (rev 166392)
@@ -42,13 +42,15 @@
 class RepatchBuffer;
 
 struct CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
-    enum CallType { None, Call, CallVarargs, Construct };
+    enum CallType { None, Call, CallVarargs, Construct, ConstructVarargs };
     static CallType callTypeFor(OpcodeID opcodeID)
     {
         if (opcodeID == op_call || opcodeID == op_call_eval)
             return Call;
         if (opcodeID == op_construct)
             return Construct;
+        if (opcodeID == op_construct_varargs)
+            return ConstructVarargs;
         ASSERT(opcodeID == op_call_varargs);
         return CallVarargs;
     }
@@ -70,7 +72,7 @@
     
     CodeSpecializationKind specializationKind() const
     {
-        return specializationFromIsConstruct(callType == Construct);
+        return specializationFromIsConstruct(callType == Construct || callType == ConstructVarargs);
     }
 
     CodeLocationNearCall callReturnLocation;

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (166391 => 166392)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2014-03-28 01:10:25 UTC (rev 166392)
@@ -627,7 +627,8 @@
 {
     int location = it - begin;
     bool hasPrintedProfiling = false;
-    switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
+    OpcodeID opcode = exec->interpreter()->getOpcodeID(it->u.opcode);
+    switch (opcode) {
         case op_enter: {
             printLocationAndOp(out, exec, location, it, "enter");
             break;
@@ -1188,6 +1189,8 @@
             printCallOp(out, exec, location, it, "call_eval", DontDumpCaches, hasPrintedProfiling, callLinkInfos);
             break;
         }
+            
+        case op_construct_varargs:
         case op_call_varargs: {
             int result = (++it)->u.operand;
             int callee = (++it)->u.operand;
@@ -1196,11 +1199,12 @@
             int firstFreeRegister = (++it)->u.operand;
             int varArgOffset = (++it)->u.operand;
             ++it;
-            printLocationAndOp(out, exec, location, it, "call_varargs");
+            printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? "call_varargs" : "construct_varargs");
             out.printf("%s, %s, %s, %s, %d, %d", registerName(result).data(), registerName(callee).data(), registerName(thisValue).data(), registerName(arguments).data(), firstFreeRegister, varArgOffset);
             dumpValueProfiling(out, it, hasPrintedProfiling);
             break;
         }
+            
         case op_tear_off_activation: {
             int r0 = (++it)->u.operand;
             printLocationOpAndRegisterOperand(out, exec, location, it, "tear_off_activation", r0);
@@ -1640,6 +1644,7 @@
         }
         switch (pc[0].u.opcode) {
         case op_call_varargs:
+        case op_construct_varargs:
         case op_get_by_val:
         case op_get_argument_by_val: {
             int arrayProfileIndex = pc[opLength - 2].u.operand;

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (166391 => 166392)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2014-03-28 01:10:25 UTC (rev 166392)
@@ -1788,6 +1788,16 @@
 
 RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
 {
+    return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
+}
+
+RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+{
+    return emitCallVarargs(op_construct_varargs, dst, func, 0, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
+}
+    
+RegisterID* BytecodeGenerator::emitCallVarargs(OpcodeID opcode, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+{
     if (m_shouldEmitProfileHooks) {
         emitMove(profileHookRegister, func);
         emitOpcode(op_profile_will_call);
@@ -1798,11 +1808,11 @@
 
     // Emit call.
     UnlinkedArrayProfile arrayProfile = newArrayProfile();
-    UnlinkedValueProfile profile = ""
+    UnlinkedValueProfile profile = ""
     ASSERT(dst != ignoredResult());
     instructions().append(dst->index());
     instructions().append(func->index());
-    instructions().append(thisRegister->index());
+    instructions().append(thisRegister ? thisRegister->index() : 0);
     instructions().append(arguments->index());
     instructions().append(firstFreeRegister->index());
     instructions().append(firstVarArgOffset);
@@ -1857,6 +1867,19 @@
     // Generate code for arguments.
     unsigned argument = 0;
     if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
+        
+        ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
+        if (n && n->m_expr->isSpreadExpression()) {
+            RELEASE_ASSERT(!n->m_next);
+            auto _expression_ = static_cast<SpreadExpressionNode*>(n->m_expr)->_expression_();
+            RefPtr<RegisterID> argumentRegister;
+            if (_expression_->isResolveNode() && willResolveToArguments(static_cast<ResolveNode*>(_expression_)->identifier()) && !symbolTable().slowArguments())
+                argumentRegister = uncheckedRegisterForArguments();
+            else
+                argumentRegister = _expression_->emitBytecode(*this, callArguments.argumentRegister(0));
+            return emitConstructVarargs(dst, func, argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
+        }
+        
         for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
             emitNode(callArguments.argumentRegister(argument++), n);
     }

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (166391 => 166392)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2014-03-28 01:10:25 UTC (rev 166392)
@@ -551,7 +551,10 @@
         }
 
         RegisterID* emitInitLazyRegister(RegisterID*);
-
+        
+        RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+        RegisterID* emitCallVarargs(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+        
     public:
         JSString* addStringConstant(const Identifier&);
 

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (166391 => 166392)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2014-03-28 01:10:25 UTC (rev 166392)
@@ -186,6 +186,7 @@
         DEFINE_OP(op_call)
         DEFINE_OP(op_call_eval)
         DEFINE_OP(op_call_varargs)
+        DEFINE_OP(op_construct_varargs)
         DEFINE_OP(op_catch)
         DEFINE_OP(op_construct)
         DEFINE_OP(op_get_callee)
@@ -353,6 +354,7 @@
         DEFINE_SLOWCASE_OP(op_call)
         DEFINE_SLOWCASE_OP(op_call_eval)
         DEFINE_SLOWCASE_OP(op_call_varargs)
+        DEFINE_SLOWCASE_OP(op_construct_varargs)
         DEFINE_SLOWCASE_OP(op_construct)
         DEFINE_SLOWCASE_OP(op_to_this)
         DEFINE_SLOWCASE_OP(op_create_this)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (166391 => 166392)


--- trunk/Source/_javascript_Core/jit/JIT.h	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2014-03-28 01:10:25 UTC (rev 166392)
@@ -455,6 +455,7 @@
         void emit_op_call(Instruction*);
         void emit_op_call_eval(Instruction*);
         void emit_op_call_varargs(Instruction*);
+        void emit_op_construct_varargs(Instruction*);
         void emit_op_captured_mov(Instruction*);
         void emit_op_catch(Instruction*);
         void emit_op_construct(Instruction*);
@@ -554,6 +555,7 @@
         void emitSlow_op_call(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_call_eval(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_construct_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_captured_mov(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_this(Instruction*, Vector<SlowCaseEntry>::iterator&);

Modified: trunk/Source/_javascript_Core/jit/JITCall.cpp (166391 => 166392)


--- trunk/Source/_javascript_Core/jit/JITCall.cpp	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/jit/JITCall.cpp	2014-03-28 01:10:25 UTC (rev 166392)
@@ -186,7 +186,8 @@
     */
     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct), call_and_construct_opcodes_must_be_same_length);
     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_varargs), call_and_call_varargs_opcodes_must_be_same_length);
-    if (opcodeID == op_call_varargs)
+    COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct_varargs), call_and_construct_varargs_opcodes_must_be_same_length);
+    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
         compileLoadVarargs(instruction);
     else {
         int argCount = instruction[3].u.operand;
@@ -252,7 +253,7 @@
     linkSlowCase(iter);
 
     ThunkGenerator generator = linkThunkGeneratorFor(
-        opcodeID == op_construct ? CodeForConstruct : CodeForCall,
+        (opcodeID == op_construct || opcodeID == op_construct_varargs) ? CodeForConstruct : CodeForCall,
         RegisterPreservationNotRequired);
     
     move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
@@ -326,6 +327,11 @@
 {
     compileOpCall(op_call_varargs, currentInstruction, m_callLinkInfoIndex++);
 }
+    
+void JIT::emit_op_construct_varargs(Instruction* currentInstruction)
+{
+    compileOpCall(op_construct_varargs, currentInstruction, m_callLinkInfoIndex++);
+}
 
 void JIT::emit_op_construct(Instruction* currentInstruction)
 {
@@ -346,7 +352,12 @@
 {
     compileOpCallSlowCase(op_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
 }
-
+    
+void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    compileOpCallSlowCase(op_construct_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
+}
+    
 void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     compileOpCallSlowCase(op_construct, currentInstruction, iter, m_callLinkInfoIndex++);

Modified: trunk/Source/_javascript_Core/jit/JITCall32_64.cpp (166391 => 166392)


--- trunk/Source/_javascript_Core/jit/JITCall32_64.cpp	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/jit/JITCall32_64.cpp	2014-03-28 01:10:25 UTC (rev 166392)
@@ -99,7 +99,12 @@
 {
     compileOpCallSlowCase(op_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
 }
-
+    
+void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    compileOpCallSlowCase(op_construct_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
+}
+    
 void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     compileOpCallSlowCase(op_construct, currentInstruction, iter, m_callLinkInfoIndex++);
@@ -119,7 +124,12 @@
 {
     compileOpCall(op_call_varargs, currentInstruction, m_callLinkInfoIndex++);
 }
-
+    
+void JIT::emit_op_construct_varargs(Instruction* currentInstruction)
+{
+    compileOpCall(op_construct_varargs, currentInstruction, m_callLinkInfoIndex++);
+}
+    
 void JIT::emit_op_construct(Instruction* currentInstruction)
 {
     compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
@@ -263,7 +273,7 @@
         - Caller restores callFrameRegister after return.
     */
     
-    if (opcodeID == op_call_varargs)
+    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
         compileLoadVarargs(instruction);
     else {
         int argCount = instruction[3].u.operand;
@@ -334,7 +344,7 @@
     linkSlowCase(iter);
 
     ThunkGenerator generator = linkThunkGeneratorFor(
-        opcodeID == op_construct ? CodeForConstruct : CodeForCall,
+        (opcodeID == op_construct || opcodeID == op_construct_varargs) ? CodeForConstruct : CodeForCall,
         RegisterPreservationNotRequired);
     
     move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (166391 => 166392)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-03-28 01:10:25 UTC (rev 166392)
@@ -705,7 +705,7 @@
         }
         codeBlock = functionExecutable->codeBlockFor(kind);
         ArityCheckMode arity;
-        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType == CallLinkInfo::CallVarargs)
+        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType == CallLinkInfo::CallVarargs || callLinkInfo->callType == CallLinkInfo::ConstructVarargs)
             arity = MustCheckArity;
         else
             arity = ArityCheckNotRequired;
@@ -802,7 +802,7 @@
         codeBlock = 0;
     else {
         codeBlock = jsCast<FunctionExecutable*>(callee->executable())->codeBlockForCall();
-        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs)
+        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs || callLinkInfo.callType == CallLinkInfo::ConstructVarargs)
             return false;
     }
     

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (166391 => 166392)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2014-03-28 01:10:25 UTC (rev 166392)
@@ -1192,7 +1192,28 @@
     
     return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
 }
-
+    
+LLINT_SLOW_PATH_DECL(slow_path_construct_varargs)
+{
+    LLINT_BEGIN_NO_SET_PC();
+    // This needs to:
+    // - Figure out what to call and compile it if necessary.
+    // - Return a tuple of machine code address to call and the new call frame.
+    
+    JSValue calleeAsValue = LLINT_OP_C(2).jsValue();
+    
+    ExecState* execCallee = vm.newCallFrameReturnValue;
+    
+    loadVarargs(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand);
+    LLINT_CALL_CHECK_EXCEPTION(exec);
+    
+    execCallee->uncheckedR(JSStack::Callee) = calleeAsValue;
+    execCallee->setCallerFrame(exec);
+    exec->setCurrentVPC(pc);
+    
+    return setUpCall(execCallee, pc, CodeForConstruct, calleeAsValue);
+}
+    
 LLINT_SLOW_PATH_DECL(slow_path_call_eval)
 {
     LLINT_BEGIN_NO_SET_PC();

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h (166391 => 166392)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h	2014-03-28 01:10:25 UTC (rev 166392)
@@ -103,6 +103,7 @@
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_construct);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_size_frame_for_varargs);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call_varargs);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_construct_varargs);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call_eval);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_tear_off_activation);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_tear_off_arguments);

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (166391 => 166392)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2014-03-28 01:10:25 UTC (rev 166392)
@@ -991,7 +991,25 @@
     end
     slowPathForCall(_llint_slow_path_call_varargs)
 
+_llint_op_construct_varargs:
+    traceExecution()
+    callSlowPath(_llint_slow_path_size_frame_for_varargs)
+    branchIfException(_llint_throw_from_slow_path_trampoline)
+    # calleeFrame in t1
+    if JSVALUE64
+        move t1, sp
+    else
+        # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
+        if ARMv7
+            subp t1, CallerFrameAndPCSize, t2
+            move t2, sp
+        else
+            subp t1, CallerFrameAndPCSize, sp
+        end
+    end
+    slowPathForCall(_llint_slow_path_construct_varargs)
 
+
 _llint_op_call_eval:
     traceExecution()
     

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (166391 => 166392)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2014-03-28 01:00:35 UTC (rev 166391)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2014-03-28 01:10:25 UTC (rev 166392)
@@ -2144,7 +2144,7 @@
             if (newCount) {
                 newCount--;
                 JSTextPosition expressionEnd = lastTokenEndPosition();
-                TreeArguments arguments = parseArguments(context, DontAllowSpread);
+                TreeArguments arguments = parseArguments(context, AllowSpread);
                 failIfFalse(arguments, "Cannot parse call arguments");
                 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
             } else {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to