Changeset 192814 in webkit
- Timestamp:
- Nov 30, 2015 12:36:54 PM (8 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r192812 r192814 1 2015-11-30 Saam barati <sbarati@apple.com> 2 3 implement op_get_rest_length so that we can allocate the rest array with the right size from the start 4 https://bugs.webkit.org/show_bug.cgi?id=151467 5 6 Reviewed by Geoffrey Garen and Mark Lam. 7 8 This patch implements op_get_rest_length which returns the length 9 that the rest parameter array will be. We're implementing this because 10 it might be a constant value in the presence of inlining in the DFG. 11 We will take advantage of this optimization opportunity in a future patch: 12 https://bugs.webkit.org/show_bug.cgi?id=151454 13 to emit better code for op_copy_rest. 14 15 op_get_rest_length has two operands: 16 1) a destination 17 2) A constant indicating the number of parameters to skip when copying the rest array. 18 19 op_get_rest_length lowers to a JSConstant node when we're inlined 20 and not a varargs call (in this case, we statically know the arguments 21 length). When that condition isn't met, we lower op_get_rest_length to 22 GetRestArray. GetRestArray produces its result as an int32. 23 24 * bytecode/BytecodeList.json: 25 * bytecode/BytecodeUseDef.h: 26 (JSC::computeUsesForBytecodeOffset): 27 (JSC::computeDefsForBytecodeOffset): 28 * bytecode/CodeBlock.cpp: 29 (JSC::CodeBlock::dumpBytecode): 30 * bytecompiler/BytecodeGenerator.cpp: 31 (JSC::BytecodeGenerator::emitNewArray): 32 (JSC::BytecodeGenerator::emitNewArrayWithSize): 33 (JSC::BytecodeGenerator::emitNewFunction): 34 (JSC::BytecodeGenerator::emitExpectedFunctionSnippet): 35 (JSC::BytecodeGenerator::emitRestParameter): 36 * bytecompiler/BytecodeGenerator.h: 37 * bytecompiler/NodesCodegen.cpp: 38 (JSC::RestParameterNode::emit): 39 * dfg/DFGAbstractInterpreterInlines.h: 40 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 41 * dfg/DFGByteCodeParser.cpp: 42 (JSC::DFG::ByteCodeParser::parseBlock): 43 * dfg/DFGCapabilities.cpp: 44 (JSC::DFG::capabilityLevel): 45 * dfg/DFGClobberize.h: 46 (JSC::DFG::clobberize): 47 * dfg/DFGDoesGC.cpp: 48 (JSC::DFG::doesGC): 49 * dfg/DFGFixupPhase.cpp: 50 (JSC::DFG::FixupPhase::fixupNode): 51 * dfg/DFGMayExit.cpp: 52 (JSC::DFG::mayExit): 53 * dfg/DFGNode.h: 54 (JSC::DFG::Node::numberOfArgumentsToSkip): 55 * dfg/DFGNodeType.h: 56 * dfg/DFGOperations.cpp: 57 * dfg/DFGOperations.h: 58 * dfg/DFGPredictionPropagationPhase.cpp: 59 (JSC::DFG::PredictionPropagationPhase::propagate): 60 * dfg/DFGSafeToExecute.h: 61 (JSC::DFG::safeToExecute): 62 * dfg/DFGSpeculativeJIT.cpp: 63 (JSC::DFG::SpeculativeJIT::compileCopyRest): 64 (JSC::DFG::SpeculativeJIT::compileGetRestLength): 65 (JSC::DFG::SpeculativeJIT::compileNotifyWrite): 66 * dfg/DFGSpeculativeJIT.h: 67 (JSC::DFG::SpeculativeJIT::callOperation): 68 * dfg/DFGSpeculativeJIT32_64.cpp: 69 (JSC::DFG::SpeculativeJIT::compile): 70 * dfg/DFGSpeculativeJIT64.cpp: 71 (JSC::DFG::SpeculativeJIT::compile): 72 * ftl/FTLCapabilities.cpp: 73 (JSC::FTL::canCompile): 74 * ftl/FTLLowerDFGToLLVM.cpp: 75 (JSC::FTL::DFG::LowerDFGToLLVM::compileNode): 76 (JSC::FTL::DFG::LowerDFGToLLVM::compileCopyRest): 77 (JSC::FTL::DFG::LowerDFGToLLVM::compileGetRestLength): 78 (JSC::FTL::DFG::LowerDFGToLLVM::compileNewObject): 79 * jit/JIT.cpp: 80 (JSC::JIT::privateCompileMainPass): 81 * jit/JIT.h: 82 * jit/JITOpcodes.cpp: 83 (JSC::JIT::emit_op_copy_rest): 84 (JSC::JIT::emit_op_get_rest_length): 85 * llint/LowLevelInterpreter.asm: 86 * llint/LowLevelInterpreter32_64.asm: 87 * llint/LowLevelInterpreter64.asm: 88 * runtime/CommonSlowPaths.cpp: 89 (JSC::SLOW_PATH_DECL): 90 1 91 2015-11-30 Filip Pizlo <fpizlo@apple.com> 2 92 -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.json
r192671 r192814 130 130 { "name" : "op_load_arrowfunction_this", "length" : 2 }, 131 131 { "name" : "op_assert", "length" : 3 }, 132 { "name" : "op_copy_rest", "length": 3 } 132 { "name" : "op_copy_rest", "length": 4 }, 133 { "name" : "op_get_rest_length", "length": 3 } 133 134 ] 134 135 }, -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
r192671 r192814 54 54 case op_create_direct_arguments: 55 55 case op_create_out_of_band_arguments: 56 case op_get_rest_length: 56 57 return; 57 58 case op_assert: … … 71 72 case op_jneq_null: 72 73 case op_dec: 73 case op_inc: 74 case op_copy_rest: { 74 case op_inc: { 75 75 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 76 76 return; … … 83 83 case op_jngreater: 84 84 case op_jngreatereq: 85 case op_jless: { 85 case op_jless: 86 case op_copy_rest: { 86 87 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 87 88 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); … … 378 379 case op_del_by_val: 379 380 case op_unsigned: 380 case op_get_from_arguments: { 381 case op_get_from_arguments: 382 case op_get_rest_length: { 381 383 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 382 384 return; -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r192671 r192814 784 784 case op_copy_rest: { 785 785 int r0 = (++it)->u.operand; 786 int r1 = (++it)->u.operand; 787 unsigned argumentOffset = (++it)->u.unsignedValue; 786 788 printLocationAndOp(out, exec, location, it, "copy_rest"); 789 out.printf("%s, %s, ", registerName(r0).data(), registerName(r1).data()); 790 out.printf("ArgumentsOffset: %u", argumentOffset); 791 break; 792 } 793 case op_get_rest_length: { 794 int r0 = (++it)->u.operand; 795 printLocationAndOp(out, exec, location, it, "get_rest_length"); 787 796 out.printf("%s, ", registerName(r0).data()); 788 797 unsigned argumentOffset = (++it)->u.unsignedValue; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r192671 r192814 2472 2472 } 2473 2473 2474 RegisterID* BytecodeGenerator::emitNewArrayWithSize(RegisterID* dst, RegisterID* length) 2475 { 2476 emitOpcode(op_new_array_with_size); 2477 instructions().append(dst->index()); 2478 instructions().append(length->index()); 2479 instructions().append(newArrayAllocationProfile()); 2480 2481 return dst; 2482 } 2483 2474 2484 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionMetadataNode* function) 2475 2485 { … … 2601 2611 2602 2612 if (dst != ignoredResult()) { 2603 if (callArguments.argumentCountIncludingThis() == 2) { 2604 emitOpcode(op_new_array_with_size); 2605 instructions().append(dst->index()); 2606 instructions().append(callArguments.argumentRegister(0)->index()); 2607 instructions().append(newArrayAllocationProfile()); 2608 } else { 2613 if (callArguments.argumentCountIncludingThis() == 2) 2614 emitNewArrayWithSize(dst, callArguments.argumentRegister(0)); 2615 else { 2609 2616 ASSERT(callArguments.argumentCountIncludingThis() == 1); 2610 2617 emitOpcode(op_new_array); … … 3834 3841 RegisterID* BytecodeGenerator::emitRestParameter(RegisterID* result, unsigned numParametersToSkip) 3835 3842 { 3836 emitNewArray(result, nullptr, 0); 3843 RefPtr<RegisterID> restArrayLength = newTemporary(); 3844 emitOpcode(op_get_rest_length); 3845 instructions().append(restArrayLength->index()); 3846 instructions().append(numParametersToSkip); 3847 3848 emitNewArrayWithSize(result, restArrayLength.get()); 3837 3849 3838 3850 emitOpcode(op_copy_rest); 3839 3851 instructions().append(result->index()); 3852 instructions().append(restArrayLength->index()); 3840 3853 instructions().append(numParametersToSkip); 3841 3854 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r192671 r192814 498 498 RegisterID* emitNewObject(RegisterID* dst); 499 499 RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision 500 RegisterID* emitNewArrayWithSize(RegisterID* dst, RegisterID* length); 500 501 501 502 RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*); -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r192768 r192814 3484 3484 } 3485 3485 3486 RefPtr<RegisterID> restParameterArray = generator.emitRestParameter(generator.newTemporary(), m_numParametersToSkip); 3486 RefPtr<RegisterID> restParameterArray = generator.newTemporary(); 3487 generator.emitRestParameter(restParameterArray.get(), m_numParametersToSkip); 3487 3488 generator.emitProfileType(restParameterArray.get(), var, m_divotStart, m_divotEnd); 3488 3489 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r192671 r192814 1761 1761 1762 1762 case GetArgumentCount: 1763 forNode(node).setType(SpecInt32); 1764 break; 1765 1766 case GetRestLength: 1763 1767 forNode(node).setType(SpecInt32); 1764 1768 break; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r192671 r192814 3332 3332 } 3333 3333 3334 case op_get_rest_length: { 3335 InlineCallFrame* inlineCallFrame = this->inlineCallFrame(); 3336 Node* length; 3337 if (inlineCallFrame && !inlineCallFrame->isVarargs()) { 3338 unsigned argumentsLength = inlineCallFrame->arguments.size() - 1; 3339 unsigned numParamsToSkip = currentInstruction[2].u.unsignedValue; 3340 JSValue restLength; 3341 if (argumentsLength <= numParamsToSkip) 3342 restLength = jsNumber(0); 3343 else 3344 restLength = jsNumber(argumentsLength - numParamsToSkip); 3345 3346 length = jsConstant(restLength); 3347 } else 3348 length = addToGraph(GetRestLength, OpInfo(currentInstruction[2].u.unsignedValue)); 3349 set(VirtualRegister(currentInstruction[1].u.operand), length); 3350 NEXT_OPCODE(op_get_rest_length); 3351 } 3352 3334 3353 case op_copy_rest: { 3335 3354 noticeArgumentsUse(); 3336 addToGraph(CopyRest, 3337 OpInfo(currentInstruction[2].u.unsignedValue), get(VirtualRegister(currentInstruction[1].u.operand))); 3355 Node* array = get(VirtualRegister(currentInstruction[1].u.operand)); 3356 Node* arrayLength = get(VirtualRegister(currentInstruction[2].u.operand)); 3357 addToGraph(CopyRest, OpInfo(currentInstruction[3].u.unsignedValue), 3358 array, arrayLength); 3338 3359 NEXT_OPCODE(op_copy_rest); 3339 3360 } -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r192671 r192814 221 221 case op_catch: 222 222 case op_copy_rest: 223 case op_get_rest_length: 223 224 return CanCompileAndInline; 224 225 -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r192671 r192814 429 429 def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, JSStack::ArgumentCount)), LazyNode(node)); 430 430 return; 431 432 case GetRestLength: 433 read(Stack); 434 return; 431 435 432 436 case GetLocal: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r192671 r192814 51 51 case GetCallee: 52 52 case GetArgumentCount: 53 case GetRestLength: 53 54 case GetLocal: 54 55 case SetLocal: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r192671 r192814 1371 1371 case CopyRest: { 1372 1372 fixEdge<KnownCellUse>(node->child1()); 1373 fixEdge<KnownInt32Use>(node->child2()); 1373 1374 break; 1374 1375 } … … 1382 1383 case GetCallee: 1383 1384 case GetArgumentCount: 1385 case GetRestLength: 1384 1386 case Flush: 1385 1387 case PhantomLocal: -
trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp
r189070 r192814 114 114 case GetCallee: 115 115 case GetArgumentCount: 116 case GetRestLength: 116 117 case GetScope: 117 118 case PhantomLocal: -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r192671 r192814 2162 2162 unsigned numberOfArgumentsToSkip() 2163 2163 { 2164 ASSERT(op() == CopyRest );2164 ASSERT(op() == CopyRest || op() == GetRestLength); 2165 2165 return static_cast<unsigned>(m_opInfo); 2166 2166 } -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r192671 r192814 263 263 macro(NewTypedArray, NodeResultJS | NodeMustGenerate) \ 264 264 macro(NewRegexp, NodeResultJS) \ 265 /* Rest Parameter */\ 266 macro(GetRestLength, NodeResultInt32) \ 265 267 macro(CopyRest, NodeMustGenerate) \ 266 268 \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r192671 r192814 819 819 } 820 820 821 void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned numberOfArguments)822 { 823 RELEASE_ASSERT(numberOfArguments > numberOfParamsToSkip); // We should only call this from JIT code when this condition is true.821 void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize) 822 { 823 ASSERT(arraySize); 824 824 JSArray* array = jsCast<JSArray*>(arrayAsCell); 825 unsigned arraySize = numberOfArguments - numberOfParamsToSkip;825 ASSERT(arraySize == array->length()); 826 826 array->setLength(exec, arraySize); 827 827 for (unsigned i = 0; i < arraySize; i++) -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r192671 r192814 104 104 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount); 105 105 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee); 106 void JIT_OPERATION operationCopyRest(ExecState*, JSCell*, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned ar gumentsCount);106 void JIT_OPERATION operationCopyRest(ExecState*, JSCell*, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize); 107 107 double JIT_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL; 108 108 size_t JIT_OPERATION operationObjectIsObject(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r192671 r192814 216 216 217 217 case GetArgumentCount: { 218 changed |= setPrediction(SpecInt32); 219 break; 220 } 221 222 case GetRestLength: { 218 223 changed |= setPrediction(SpecInt32); 219 224 break; -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r192671 r192814 141 141 case GetCallee: 142 142 case GetArgumentCount: 143 case GetRestLength: 143 144 case GetLocal: 144 145 case SetLocal: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r192795 r192814 5353 5353 5354 5354 SpeculateCellOperand array(this, node->child1()); 5355 GPRTemporary argumentsStart(this); 5356 SpeculateStrictInt32Operand arrayLength(this, node->child2()); 5357 5355 5358 GPRReg arrayGPR = array.gpr(); 5356 5357 GPRTemporary argumentsLength(this);5358 GPRReg argumentsLengthGPR = argumentsLength.gpr();5359 5360 GPRTemporary argumentsStart(this);5361 5359 GPRReg argumentsStartGPR = argumentsStart.gpr(); 5362 5363 emitGetLength(node->origin.semantic, argumentsLengthGPR); 5364 CCallHelpers::Jump done = m_jit.branch32(MacroAssembler:: LessThanOrEqual, argumentsLengthGPR, TrustedImm32(node->numberOfArgumentsToSkip()));5360 GPRReg arrayLengthGPR = arrayLength.gpr(); 5361 5362 CCallHelpers::Jump done = m_jit.branch32(MacroAssembler::Equal, arrayLengthGPR, TrustedImm32(0)); 5365 5363 5366 5364 emitGetArgumentStart(node->origin.semantic, argumentsStartGPR); 5367 silentSpillAllRegisters(arguments LengthGPR, argumentsStartGPR);5368 // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4: number of arguments5369 callOperation(operationCopyRest, arrayGPR, argumentsStartGPR, TrustedImm32(node->numberOfArgumentsToSkip()), argumentsLengthGPR);5370 silentFillAllRegisters(arguments LengthGPR);5365 silentSpillAllRegisters(argumentsStartGPR); 5366 // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length 5367 callOperation(operationCopyRest, arrayGPR, argumentsStartGPR, Imm32(node->numberOfArgumentsToSkip()), arrayLengthGPR); 5368 silentFillAllRegisters(argumentsStartGPR); 5371 5369 m_jit.exceptionCheck(); 5372 5370 … … 5374 5372 5375 5373 noResult(node); 5374 } 5375 5376 void SpeculativeJIT::compileGetRestLength(Node* node) 5377 { 5378 ASSERT(node->op() == GetRestLength); 5379 5380 GPRTemporary result(this); 5381 GPRReg resultGPR = result.gpr(); 5382 5383 emitGetLength(node->origin.semantic, resultGPR); 5384 CCallHelpers::Jump hasNonZeroLength = m_jit.branch32(MacroAssembler::Above, resultGPR, Imm32(node->numberOfArgumentsToSkip())); 5385 m_jit.move(TrustedImm32(0), resultGPR); 5386 CCallHelpers::Jump done = m_jit.jump(); 5387 hasNonZeroLength.link(&m_jit); 5388 if (node->numberOfArgumentsToSkip()) 5389 m_jit.sub32(TrustedImm32(node->numberOfArgumentsToSkip()), resultGPR); 5390 done.link(&m_jit); 5391 int32Result(resultGPR, node); 5376 5392 } 5377 5393 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r192671 r192814 1222 1222 } 1223 1223 1224 JITCompiler::Call callOperation(V_JITOperation_ECRUiUi operation, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4)1225 { 1226 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3 , arg4);1224 JITCompiler::Call callOperation(V_JITOperation_ECRUiUi operation, GPRReg arg1, GPRReg arg2, Imm32 arg3, GPRReg arg4) 1225 { 1226 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.asTrustedImm32(), arg4); 1227 1227 return appendCall(operation); 1228 1228 } … … 2246 2246 void compileCreateClonedArguments(Node*); 2247 2247 void compileCopyRest(Node*); 2248 void compileGetRestLength(Node*); 2248 2249 void compileNotifyWrite(Node*); 2249 2250 bool compileRegExpExec(Node*); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r192671 r192814 4444 4444 } 4445 4445 4446 case GetRestLength: { 4447 compileGetRestLength(node); 4448 break; 4449 } 4450 4446 4451 case NewFunction: 4447 4452 case NewArrowFunction: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r192671 r192814 3828 3828 break; 3829 3829 } 3830 3831 case GetRestLength: { 3832 compileGetRestLength(node); 3833 break; 3834 } 3830 3835 3831 3836 case GetScope: -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r192671 r192814 212 212 case PutSetterByVal: 213 213 case CopyRest: 214 case GetRestLength: 214 215 // These are OK. 215 216 break; -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r192671 r192814 970 970 case CopyRest: 971 971 compileCopyRest(); 972 break; 973 case GetRestLength: 974 compileGetRestLength(); 972 975 break; 973 976 … … 3646 3649 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("FillRestParameter continuation")); 3647 3650 3651 LValue arrayLength = lowInt32(m_node->child2()); 3652 3653 m_out.branch( 3654 m_out.equal(arrayLength, m_out.constInt32(0)), 3655 unsure(continuation), unsure(doCopyRest)); 3656 3657 LBasicBlock lastNext = m_out.appendTo(doCopyRest, continuation); 3658 // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length 3648 3659 LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip()); 3649 LValue numberOfArguments = getArgumentsLength().value;3650 3651 m_out.branch(3652 m_out.above(numberOfArguments, numberOfArgumentsToSkip),3653 unsure(doCopyRest), unsure(continuation));3654 3655 LBasicBlock lastNext = m_out.appendTo(doCopyRest, continuation);3656 // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:number of arguments3657 3660 vmCall( 3658 3661 m_out.voidType,m_out.operation(operationCopyRest), m_callFrame, lowCell(m_node->child1()), 3659 getArgumentsStart(), numberOfArgumentsToSkip, numberOfArguments);3662 getArgumentsStart(), numberOfArgumentsToSkip, arrayLength); 3660 3663 m_out.jump(continuation); 3661 3664 3662 3665 m_out.appendTo(continuation, lastNext); 3666 } 3667 3668 void compileGetRestLength() 3669 { 3670 LBasicBlock nonZeroLength = FTL_NEW_BLOCK(m_out, ("GetRestLength non zero")); 3671 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetRestLength continuation")); 3672 3673 ValueFromBlock zeroLengthResult = m_out.anchor(m_out.constInt32(0)); 3674 3675 LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip()); 3676 LValue argumentsLength = getArgumentsLength().value; 3677 m_out.branch(m_out.above(argumentsLength, numberOfArgumentsToSkip), 3678 unsure(nonZeroLength), unsure(continuation)); 3679 3680 LBasicBlock lastNext = m_out.appendTo(nonZeroLength, continuation); 3681 ValueFromBlock nonZeroLengthResult = m_out.anchor(m_out.sub(argumentsLength, numberOfArgumentsToSkip)); 3682 m_out.jump(continuation); 3683 3684 m_out.appendTo(continuation, lastNext); 3685 setInt32(m_out.phi(m_out.int32, zeroLengthResult, nonZeroLengthResult)); 3663 3686 } 3664 3687 -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r192671 r192814 213 213 DEFINE_OP(op_create_out_of_band_arguments) 214 214 DEFINE_OP(op_copy_rest) 215 DEFINE_OP(op_get_rest_length) 215 216 DEFINE_OP(op_check_tdz) 216 217 DEFINE_OP(op_assert) -
trunk/Source/JavaScriptCore/jit/JIT.h
r192671 r192814 492 492 void emit_op_create_out_of_band_arguments(Instruction*); 493 493 void emit_op_copy_rest(Instruction*); 494 void emit_op_get_rest_length(Instruction*); 494 495 void emit_op_check_tdz(Instruction*); 495 496 void emit_op_assert(Instruction*); -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r192671 r192814 1406 1406 } 1407 1407 1408 void JIT::emit_op_get_rest_length(Instruction* currentInstruction) 1409 { 1410 int dst = currentInstruction[1].u.operand; 1411 unsigned numParamsToSkip = currentInstruction[2].u.unsignedValue; 1412 load32(payloadFor(JSStack::ArgumentCount), regT0); 1413 sub32(TrustedImm32(1), regT0); 1414 Jump zeroLength = branch32(LessThanOrEqual, regT0, Imm32(numParamsToSkip)); 1415 sub32(Imm32(numParamsToSkip), regT0); 1416 #if USE(JSVALUE64) 1417 boxInt32(regT0, JSValueRegs(regT0)); 1418 #endif 1419 Jump done = jump(); 1420 1421 zeroLength.link(this); 1422 #if USE(JSVALUE64) 1423 move(TrustedImm64(JSValue::encode(jsNumber(0))), regT0); 1424 #else 1425 move(TrustedImm32(0), regT0); 1426 #endif 1427 1428 done.link(this); 1429 #if USE(JSVALUE64) 1430 emitPutVirtualRegister(dst, regT0); 1431 #else 1432 move(TrustedImm32(JSValue::Int32Tag), regT1); 1433 emitPutVirtualRegister(dst, JSValueRegs(regT1, regT0)); 1434 #endif 1435 } 1436 1408 1437 } // namespace JSC 1409 1438 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r192671 r192814 1679 1679 traceExecution() 1680 1680 callSlowPath(_slow_path_copy_rest) 1681 dispatch( 3)1681 dispatch(4) 1682 1682 1683 1683 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r192125 r192814 2431 2431 storei t0, PayloadOffset[cfr, t1, 8] 2432 2432 dispatch(2) 2433 2434 2435 _llint_op_get_rest_length: 2436 traceExecution() 2437 loadi PayloadOffset + ArgumentCount[cfr], t0 2438 subi 1, t0 2439 loadisFromInstruction(2, t1) 2440 bilteq t0, t1, .storeZero 2441 subi t1, t0 2442 jmp .finish 2443 .storeZero: 2444 move 0, t0 2445 .finish: 2446 loadisFromInstruction(1, t1) 2447 storei t0, PayloadOffset[cfr, t1, 8] 2448 storei Int32Tag, TagOffset[cfr, t1, 8] 2449 dispatch(3) -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r192125 r192814 2299 2299 storeq t0, [cfr, t1, 8] 2300 2300 dispatch(2) 2301 2302 2303 _llint_op_get_rest_length: 2304 traceExecution() 2305 loadi PayloadOffset + ArgumentCount[cfr], t0 2306 subi 1, t0 2307 loadisFromInstruction(2, t1) 2308 bilteq t0, t1, .storeZero 2309 subi t1, t0 2310 jmp .boxUp 2311 .storeZero: 2312 move 0, t0 2313 .boxUp: 2314 orq tagTypeNumber, t0 2315 loadisFromInstruction(1, t1) 2316 storeq t0, [cfr, t1, 8] 2317 dispatch(3) -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r192671 r192814 705 705 { 706 706 BEGIN(); 707 unsigned numParamsToSkip = pc[2].u.unsignedValue;708 unsigned numArgumentsToFunction = exec->argumentCount();709 if (numArgumentsToFunction <= numParamsToSkip)707 unsigned arraySize = OP_C(2).jsValue().asUInt32(); 708 if (!arraySize) { 709 ASSERT(!jsCast<JSArray*>(OP(1).jsValue())->length()); 710 710 END(); 711 711 } 712 712 JSArray* array = jsCast<JSArray*>(OP(1).jsValue()); 713 unsigned arraySize = numArgumentsToFunction - numParamsToSkip;714 array->setLength(exec, arraySize);713 ASSERT(arraySize == array->length()); 714 unsigned numParamsToSkip = pc[3].u.unsignedValue; 715 715 for (unsigned i = 0; i < arraySize; i++) 716 716 array->putDirectIndex(exec, i, exec->uncheckedArgument(i + numParamsToSkip));
Note: See TracChangeset
for help on using the changeset viewer.