Title: [201668] trunk/Source/_javascript_Core
Revision
201668
Author
[email protected]
Date
2016-06-03 16:06:39 -0700 (Fri, 03 Jun 2016)

Log Message

Add argument_count bytecode for concat
https://bugs.webkit.org/show_bug.cgi?id=158358

Reviewed by Geoffrey Garen.

This patch adds a new argument count bytecode. Normally, we would
just make sure that the argument.length bytecode was fast enough
that we shouldn't need such an bytecode.  However, for the case of
Array.prototype.concat the overhead of the arguments object
allocation in the LLInt was too high and caused regressions.

* bytecode/BytecodeIntrinsicRegistry.h:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecompiler/NodesCodegen.cpp:
(JSC::BytecodeIntrinsicNode::emit_intrinsic_argumentCount):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getArgumentCount):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_argument_count):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* tests/stress/argument-count-bytecode.js: Added.
(inlineCount):
(inlineCount1):
(inlineCount2):
(inlineCountVarArgs):
(assert):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (201667 => 201668)


--- trunk/Source/_javascript_Core/ChangeLog	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-06-03 23:06:39 UTC (rev 201668)
@@ -1,3 +1,44 @@
+2016-06-03  Keith Miller  <[email protected]>
+
+        Add argument_count bytecode for concat
+        https://bugs.webkit.org/show_bug.cgi?id=158358
+
+        Reviewed by Geoffrey Garen.
+
+        This patch adds a new argument count bytecode. Normally, we would
+        just make sure that the argument.length bytecode was fast enough
+        that we shouldn't need such an bytecode.  However, for the case of
+        Array.prototype.concat the overhead of the arguments object
+        allocation in the LLInt was too high and caused regressions.
+
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_argumentCount):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::getArgumentCount):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_argument_count):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * tests/stress/argument-count-bytecode.js: Added.
+        (inlineCount):
+        (inlineCount1):
+        (inlineCount2):
+        (inlineCountVarArgs):
+        (assert):
+
 2016-06-03  Geoffrey Garen  <[email protected]>
 
         Clients of PolymorphicAccess::addCases shouldn't have to malloc

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h (201667 => 201668)


--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2016-06-03 23:06:39 UTC (rev 201668)
@@ -40,6 +40,7 @@
 class Identifier;
 
 #define JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \
+    macro(argumentCount) \
     macro(assert) \
     macro(isObject) \
     macro(tryGetById) \

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (201667 => 201668)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-06-03 23:06:39 UTC (rev 201668)
@@ -9,6 +9,7 @@
             { "name" : "op_create_scoped_arguments", "length" : 3 },
             { "name" : "op_create_cloned_arguments", "length" : 2 },
             { "name" : "op_create_this", "length" : 5 },
+            { "name" : "op_argument_count", "length" : 2 },
             { "name" : "op_to_this", "length" : 4 },
             { "name" : "op_check_tdz", "length" : 2 },
             { "name" : "op_new_object", "length" : 4 },

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (201667 => 201668)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-06-03 23:06:39 UTC (rev 201668)
@@ -53,6 +53,7 @@
     case op_jmp:
     case op_new_object:
     case op_enter:
+    case op_argument_count:
     case op_catch:
     case op_profile_control_flow:
     case op_create_direct_arguments:
@@ -362,6 +363,7 @@
 #undef LLINT_HELPER_OPCODES
         return;
     // These all have a single destination for the first argument.
+    case op_argument_count:
     case op_to_index_string:
     case op_get_enumerable_length:
     case op_has_indexed_property:

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -818,6 +818,11 @@
             out.printf("%s", registerName(r0).data());
             break;
         }
+        case op_argument_count: {
+            int r0 = (++it)->u.operand;
+            printLocationOpAndRegisterOperand(out, exec, location, it, "argument_count", r0);
+            break;
+        }
         case op_copy_rest: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -854,6 +854,13 @@
     return (this->*m_emitter)(generator, dst);
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argumentCount(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ASSERT(!m_args->m_listNode);
+
+    return generator.emitUnaryNoDstOp(op_argument_count, generator.finalDestination(dst));
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_assert(BytecodeGenerator& generator, RegisterID* dst)
 {
 #ifndef NDEBUG

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-06-03 23:06:39 UTC (rev 201668)
@@ -1973,7 +1973,7 @@
         forNode(node).setType(m_graph, SpecFunction);
         break;
         
-    case GetArgumentCount:
+    case GetArgumentCountIncludingThis:
         forNode(node).setType(SpecInt32Only);
         break;
         

Modified: trunk/Source/_javascript_Core/dfg/DFGArgumentsUtilities.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGArgumentsUtilities.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGArgumentsUtilities.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -76,7 +76,7 @@
     
     Node* argumentCount;
     if (!inlineCallFrame)
-        argumentCount = insertionSet.insertNode(nodeIndex, SpecInt32Only, GetArgumentCount, origin);
+        argumentCount = insertionSet.insertNode(nodeIndex, SpecInt32Only, GetArgumentCountIncludingThis, origin);
     else {
         VirtualRegister argumentCountRegister(inlineCallFrame->stackOffset + JSStack::ArgumentCount);
         

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -196,6 +196,7 @@
     Terminality handleVarargsCall(Instruction* pc, NodeType op, CallMode);
     void emitFunctionChecks(CallVariant, Node* callTarget, VirtualRegister thisArgumnt);
     void emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis);
+    Node* getArgumentCount();
     unsigned inliningCost(CallVariant, int argumentCountIncludingThis, CallMode); // Return UINT_MAX if it's not an inlining candidate. By convention, intrinsics have a cost of 1.
     // Handle inlining. Return true if it succeeded, false if we need to plant a call.
     bool handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&, int registerOffset, VirtualRegister thisArgument, VirtualRegister argumentsArgument, unsigned argumentsOffset, int argumentCountIncludingThis, unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind, SpeculatedType prediction);
@@ -1322,6 +1323,19 @@
     addToGraph(CheckCell, OpInfo(m_graph.freeze(calleeCell)), callTargetForCheck, thisArgument);
 }
 
+Node* ByteCodeParser::getArgumentCount()
+{
+    Node* argumentCount;
+    if (m_inlineStackTop->m_inlineCallFrame) {
+        if (m_inlineStackTop->m_inlineCallFrame->isVarargs())
+            argumentCount = get(VirtualRegister(JSStack::ArgumentCount));
+        else
+            argumentCount = jsConstant(m_graph.freeze(jsNumber(m_inlineStackTop->m_inlineCallFrame->arguments.size()))->value());
+    } else
+        argumentCount = addToGraph(GetArgumentCountIncludingThis, OpInfo(0), OpInfo(SpecInt32Only));
+    return argumentCount;
+}
+
 void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis)
 {
     for (int i = 0; i < argumentCountIncludingThis; ++i)
@@ -4886,7 +4900,14 @@
             set(VirtualRegister(currentInstruction[1].u.operand), result);
             NEXT_OPCODE(op_get_scope);
         }
-            
+
+        case op_argument_count: {
+            Node* sub = addToGraph(ArithSub, OpInfo(Arith::Unchecked), OpInfo(SpecInt32Only), getArgumentCount(), addToGraph(JSConstant, OpInfo(m_constantOne)));
+
+            set(VirtualRegister(currentInstruction[1].u.operand), sub);
+            NEXT_OPCODE(op_argument_count);
+        }
+
         case op_create_direct_arguments: {
             noticeArgumentsUse();
             Node* createArguments = addToGraph(CreateDirectArguments);

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -106,6 +106,7 @@
     switch (opcodeID) {
     case op_enter:
     case op_to_this:
+    case op_argument_count:
     case op_check_tdz:
     case op_create_this:
     case op_bitand:

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-06-03 23:06:39 UTC (rev 201668)
@@ -502,7 +502,7 @@
         def(HeapLocation(StackLoc, AbstractHeap(Stack, JSStack::Callee)), LazyNode(node));
         return;
         
-    case GetArgumentCount:
+    case GetArgumentCountIncludingThis:
         read(AbstractHeap(Stack, JSStack::ArgumentCount));
         def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, JSStack::ArgumentCount)), LazyNode(node));
         return;

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -50,7 +50,7 @@
     case LazyJSConstant:
     case Identity:
     case GetCallee:
-    case GetArgumentCount:
+    case GetArgumentCountIncludingThis:
     case GetRestLength:
     case GetLocal:
     case SetLocal:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -1508,7 +1508,7 @@
         case DoubleConstant:
         case GetLocal:
         case GetCallee:
-        case GetArgumentCount:
+        case GetArgumentCountIncludingThis:
         case GetRestLength:
         case Flush:
         case PhantomLocal:

Modified: trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -71,7 +71,7 @@
     case KillStack:
     case GetStack:
     case GetCallee:
-    case GetArgumentCount:
+    case GetArgumentCountIncludingThis:
     case GetRestLength:
     case GetScope:
     case PhantomLocal:

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-06-03 23:06:39 UTC (rev 201668)
@@ -53,7 +53,7 @@
     macro(ToThis, NodeResultJS) \
     macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
     macro(GetCallee, NodeResultJS) \
-    macro(GetArgumentCount, NodeResultInt32) \
+    macro(GetArgumentCountIncludingThis, NodeResultInt32) \
     \
     /* Nodes for local variable access. These nodes are linked together using Phi nodes. */\
     /* Any two nodes that are part of the same Phi graph will share the same */\

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -737,7 +737,7 @@
             break;
         }
             
-        case GetArgumentCount: {
+        case GetArgumentCountIncludingThis: {
             setPrediction(SpecInt32Only);
             break;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-06-03 23:06:39 UTC (rev 201668)
@@ -142,7 +142,7 @@
     case ToThis:
     case CreateThis:
     case GetCallee:
-    case GetArgumentCount:
+    case GetArgumentCountIncludingThis:
     case GetRestLength:
     case GetLocal:
     case SetLocal:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -4070,7 +4070,7 @@
         break;
     }
         
-    case GetArgumentCount: {
+    case GetArgumentCountIncludingThis: {
         GPRTemporary result(this);
         m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), result.gpr());
         int32Result(result.gpr(), node);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -4007,7 +4007,7 @@
         break;
     }
         
-    case GetArgumentCount: {
+    case GetArgumentCountIncludingThis: {
         GPRTemporary result(this);
         m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), result.gpr());
         int32Result(result.gpr(), node);

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -160,7 +160,7 @@
     case GetExecutable:
     case GetScope:
     case GetCallee:
-    case GetArgumentCount:
+    case GetArgumentCountIncludingThis:
     case ToString:
     case CallStringConstructor:
     case MakeRope:

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -776,8 +776,8 @@
         case GetCallee:
             compileGetCallee();
             break;
-        case GetArgumentCount:
-            compileGetArgumentCount();
+        case GetArgumentCountIncludingThis:
+            compileGetArgumentCountIncludingThis();
             break;
         case GetScope:
             compileGetScope();
@@ -4670,7 +4670,7 @@
         setJSValue(m_out.loadPtr(addressFor(JSStack::Callee)));
     }
     
-    void compileGetArgumentCount()
+    void compileGetArgumentCountIncludingThis()
     {
         setInt32(m_out.load32(payloadFor(JSStack::ArgumentCount)));
     }

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -223,6 +223,7 @@
         DEFINE_OP(op_create_direct_arguments)
         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_get_rest_length)
         DEFINE_OP(op_check_tdz)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (201667 => 201668)


--- trunk/Source/_javascript_Core/jit/JIT.h	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2016-06-03 23:06:39 UTC (rev 201668)
@@ -491,6 +491,7 @@
         void emit_op_create_direct_arguments(Instruction*);
         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_get_rest_length(Instruction*);
         void emit_op_check_tdz(Instruction*);

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (201667 => 201668)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-06-03 23:06:39 UTC (rev 201668)
@@ -1419,6 +1419,16 @@
     slowPathCall.call();
 }
 
+void JIT::emit_op_argument_count(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    load32(payloadFor(JSStack::ArgumentCount), regT0);
+    sub32(TrustedImm32(1), regT0);
+    JSValueRegs result = JSValueRegs::withTwoAvailableRegs(regT0, regT1);
+    boxInt32(regT0, result);
+    emitPutVirtualRegister(dst, result);
+}
+
 void JIT::emit_op_copy_rest(Instruction* currentInstruction)
 {
     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_copy_rest);

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (201667 => 201668)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2016-06-03 23:06:39 UTC (rev 201668)
@@ -677,6 +677,17 @@
     dispatch(1)
 
 
+_llint_op_argument_count:
+    traceExecution()
+    loadisFromInstruction(1, t2)
+    loadi PayloadOffset + ArgumentCount[cfr], t0
+    subi 1, t0
+    move Int32Tag, t1
+    storei t1, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(2)
+
+
 _llint_op_get_scope:
     traceExecution()
     loadi Callee + PayloadOffset[cfr], t0

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (201667 => 201668)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2016-06-03 23:01:49 UTC (rev 201667)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2016-06-03 23:06:39 UTC (rev 201668)
@@ -584,6 +584,16 @@
     dispatch(1)
 
 
+_llint_op_argument_count:
+    traceExecution()
+    loadisFromInstruction(1, t1)
+    loadi PayloadOffset + ArgumentCount[cfr], t0
+    subi 1, t0
+    orq TagTypeNumber, t0
+    storeq t0, [cfr, t1, 8]
+    dispatch(2)
+
+
 _llint_op_get_scope:
     traceExecution()
     loadp Callee[cfr], t0

Added: trunk/Source/_javascript_Core/tests/stress/argument-count-bytecode.js (0 => 201668)


--- trunk/Source/_javascript_Core/tests/stress/argument-count-bytecode.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/argument-count-bytecode.js	2016-06-03 23:06:39 UTC (rev 201668)
@@ -0,0 +1,38 @@
+count = createBuiltin("(function () { return @argumentCount(); })");
+countNoInline = createBuiltin("(function () { return @argumentCount(); })");
+noInline(countNoInline);
+
+
+function inlineCount() { return count(); }
+noInline(inlineCount);
+
+function inlineCount1() { return count(1); }
+noInline(inlineCount1);
+
+function inlineCount2() { return count(1,2); }
+noInline(inlineCount2);
+
+function inlineCountVarArgs(list) { return count(...list); }
+noInline(inlineCountVarArgs);
+
+function assert(condition, message) {
+    if (!condition)
+        throw new Error(message);
+}
+
+for (i = 0; i < 1000000; i++) {
+    assert(count(1,1,2) === 3, i);
+    assert(count() === 0, i);
+    assert(count(1) === 1, i);
+    assert(count(...[1,2,3,4,5]) === 5, i);
+    assert(count(...[]) === 0, i);
+    assert(inlineCount() === 0, i);
+    assert(inlineCount1() === 1, i);
+    assert(inlineCount2() === 2, i);
+    assert(inlineCountVarArgs([1,2,3,4]) === 4, i);
+    assert(inlineCountVarArgs([]) === 0, i);
+    // Insert extra junk so that inlineCountVarArgs.arguments.length !== count.arguments.length
+    assert(inlineCountVarArgs([1], 2, 4) === 1, i);
+    assert(countNoInline(4) === 1, i)
+    assert(countNoInline() === 0, i);
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to