Changeset 128096 in webkit
- Timestamp:
- Sep 10, 2012 1:23:50 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r128091 r128096 1 2012-09-09 Geoffrey Garen <ggaren@apple.com> 2 3 Refactored op_tear_off* to support activations that don't allocate space for 'arguments' 4 https://bugs.webkit.org/show_bug.cgi?id=96231 5 6 Reviewed by Gavin Barraclough. 7 8 This is a step toward smaller activations. 9 10 As a side-effect, this patch eliminates a load and branch from the hot path 11 of activation tear-off by moving it to the cold path of arguments tear-off. Our 12 optimizing assumptions are that activations are common and that reifying the 13 arguments object is less common. 14 15 * bytecode/CodeBlock.cpp: 16 (JSC::CodeBlock::dump): 17 * bytecode/Opcode.h: 18 (JSC::padOpcodeName): Updated for new opcode lengths. 19 20 * bytecompiler/BytecodeGenerator.cpp: 21 (JSC::BytecodeGenerator::BytecodeGenerator): 22 (JSC::BytecodeGenerator::addConstantValue): Added support for JSValue() 23 in the bytecode, which we use when we have 'arguments' but no activation. 24 25 (JSC::BytecodeGenerator::emitReturn): Always emit tear_off_arguments 26 if we've allocated the arguments registers. This allows tear_off_activation 27 not to worry about the arguments object anymore. 28 29 Also, pass the activation and arguments values directly to these opcodes 30 instead of requiring the opcodes to infer the values through special 31 registers. This gives us more flexibility to move or eliminate registers. 32 33 * dfg/DFGArgumentsSimplificationPhase.cpp: 34 (JSC::DFG::ArgumentsSimplificationPhase::run): 35 * dfg/DFGByteCodeParser.cpp: 36 (JSC::DFG::ByteCodeParser::parseBlock): 37 * dfg/DFGNode.h: 38 (Node): Updated for new opcode lengths. 39 40 * dfg/DFGOperations.cpp: Activation tear-off doesn't worry about the 41 arguments object anymore. If 'arguments' is in use and reified, it's 42 responsible for aliasing back to the activation object in tear_off_arguments. 43 44 * dfg/DFGOperations.h: 45 * dfg/DFGSpeculativeJIT.h: 46 (JSC::DFG::SpeculativeJIT::callOperation): 47 (SpeculativeJIT): 48 * dfg/DFGSpeculativeJIT32_64.cpp: 49 (JSC::DFG::SpeculativeJIT::compile): 50 * dfg/DFGSpeculativeJIT64.cpp: 51 (JSC::DFG::SpeculativeJIT::compile): Don't pass the arguments object to 52 activation tear-off; do pass the activation object to arguments tear-off. 53 54 * interpreter/Interpreter.cpp: 55 (JSC::Interpreter::privateExecute): Ditto. 56 57 * jit/JITOpcodes.cpp: 58 (JSC::JIT::emit_op_tear_off_activation): 59 (JSC::JIT::emit_op_tear_off_arguments): 60 * jit/JITOpcodes32_64.cpp: 61 (JSC::JIT::emit_op_tear_off_activation): 62 (JSC::JIT::emit_op_tear_off_arguments): 63 * jit/JITStubs.cpp: 64 (JSC::DEFINE_STUB_FUNCTION): 65 * llint/LLIntSlowPaths.cpp: 66 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 67 * llint/LowLevelInterpreter32_64.asm: 68 * llint/LowLevelInterpreter64.asm: Same change in a few more execution engines. 69 1 70 2012-09-10 Patrick Gansterer <paroga@webkit.org> 2 71 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r128084 r128096 1408 1408 case op_tear_off_activation: { 1409 1409 int r0 = (++it)->u.operand; 1410 dataLog("[%4d] tear_off_activation\t %s", location, registerName(exec, r0).data()); 1411 dumpBytecodeCommentAndNewLine(location); 1412 break; 1413 } 1414 case op_tear_off_arguments: { 1415 int r0 = (++it)->u.operand; 1410 1416 int r1 = (++it)->u.operand; 1411 dataLog("[%4d] tear_off_activation\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); 1412 dumpBytecodeCommentAndNewLine(location); 1413 break; 1414 } 1415 case op_tear_off_arguments: { 1416 int r0 = (++it)->u.operand; 1417 dataLog("[%4d] tear_off_arguments %s", location, registerName(exec, r0).data()); 1417 dataLog("[%4d] tear_off_arguments %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); 1418 1418 dumpBytecodeCommentAndNewLine(location); 1419 1419 break; -
trunk/Source/JavaScriptCore/bytecode/Opcode.h
r127393 r128096 175 175 macro(op_call_eval, 6) \ 176 176 macro(op_call_varargs, 5) \ 177 macro(op_tear_off_activation, 3) \178 macro(op_tear_off_arguments, 2) \177 macro(op_tear_off_activation, 2) \ 178 macro(op_tear_off_arguments, 3) \ 179 179 macro(op_ret, 2) \ 180 180 macro(op_call_put_result, 3) /* has value profiling */ \ -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r127987 r128096 273 273 , m_codeBlock(codeBlock) 274 274 , m_thisRegister(CallFrame::thisArgumentOffset()) 275 , m_emptyValueRegister(0) 275 276 , m_finallyDepth(0) 276 277 , m_dynamicScopeDepth(0) … … 354 355 , m_codeBlock(codeBlock) 355 356 , m_activationRegister(0) 357 , m_emptyValueRegister(0) 356 358 , m_finallyDepth(0) 357 359 , m_dynamicScopeDepth(0) … … 387 389 } 388 390 389 // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'390 // object, if created.391 391 if (m_codeBlock->needsFullScopeChain() || functionBody->usesArguments()) { 392 392 RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code. … … 527 527 , m_codeBlock(codeBlock) 528 528 , m_thisRegister(CallFrame::thisArgumentOffset()) 529 , m_emptyValueRegister(0) 529 530 , m_finallyDepth(0) 530 531 , m_dynamicScopeDepth(0) … … 1112 1113 } 1113 1114 1115 // We can't hash JSValue(), so we use a dedicated data member to cache it. 1116 RegisterID* BytecodeGenerator::addConstantEmptyValue() 1117 { 1118 if (!m_emptyValueRegister) { 1119 int index = m_nextConstantOffset; 1120 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); 1121 ++m_nextConstantOffset; 1122 m_codeBlock->addConstant(JSValue()); 1123 m_emptyValueRegister = &m_constantPoolRegisters[index]; 1124 } 1125 1126 return m_emptyValueRegister; 1127 } 1128 1114 1129 RegisterID* BytecodeGenerator::addConstantValue(JSValue v) 1115 1130 { 1131 if (!v) 1132 return addConstantEmptyValue(); 1133 1116 1134 int index = m_nextConstantOffset; 1117 1118 1135 JSValueMap::AddResult result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset); 1119 1136 if (result.isNewEntry) { 1120 1137 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); 1121 1138 ++m_nextConstantOffset; 1122 m_codeBlock->addConstant( JSValue(v));1139 m_codeBlock->addConstant(v); 1123 1140 } else 1124 1141 index = result.iterator->second; 1125 1126 1142 return &m_constantPoolRegisters[index]; 1127 1143 } … … 2047 2063 emitOpcode(op_tear_off_activation); 2048 2064 instructions().append(m_activationRegister->index()); 2049 instructions().append(m_codeBlock->argumentsRegister()); 2050 } else if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !m_codeBlock->isStrictMode()) { 2065 } 2066 2067 if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !m_codeBlock->isStrictMode()) { 2051 2068 emitOpcode(op_tear_off_arguments); 2052 2069 instructions().append(m_codeBlock->argumentsRegister()); 2070 instructions().append(m_activationRegister ? m_activationRegister->index() : emitLoad(0, JSValue())->index()); 2053 2071 } 2054 2072 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r127987 r128096 638 638 unsigned addConstant(const Identifier&); 639 639 RegisterID* addConstantValue(JSValue); 640 RegisterID* addConstantEmptyValue(); 640 641 unsigned addRegExp(RegExp*); 641 642 … … 714 715 RegisterID m_calleeRegister; 715 716 RegisterID* m_activationRegister; 717 RegisterID* m_emptyValueRegister; 716 718 SegmentedVector<RegisterID, 32> m_constantPoolRegisters; 717 719 SegmentedVector<RegisterID, 32> m_calleeRegisters; -
trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
r126926 r128096 617 617 node.setOpAndDefaultFlags(Nop); 618 618 m_graph.clearAndDerefChild1(node); 619 m_graph.clearAndDerefChild2(node); 619 620 node.setRefCount(0); 620 621 break; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r127643 r128096 2856 2856 2857 2857 case op_tear_off_activation: { 2858 addToGraph(TearOffActivation, OpInfo(unmodifiedArgumentsRegister(currentInstruction[2].u.operand)), get(currentInstruction[1].u.operand), get(currentInstruction[2].u.operand));2858 addToGraph(TearOffActivation, get(currentInstruction[1].u.operand)); 2859 2859 NEXT_OPCODE(op_tear_off_activation); 2860 2860 } 2861 2861 2862 2862 case op_tear_off_arguments: { 2863 2863 m_graph.m_hasArguments = true; 2864 addToGraph(TearOffArguments, get(unmodifiedArgumentsRegister(currentInstruction[1].u.operand)) );2864 addToGraph(TearOffArguments, get(unmodifiedArgumentsRegister(currentInstruction[1].u.operand)), get(currentInstruction[2].u.operand)); 2865 2865 NEXT_OPCODE(op_tear_off_arguments); 2866 2866 } -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r127189 r128096 338 338 } 339 339 340 VirtualRegister unmodifiedArgumentsRegister()341 {342 ASSERT(op() == TearOffActivation);343 return static_cast<VirtualRegister>(m_opInfo);344 }345 346 340 VirtualRegister unlinkedLocal() 347 341 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r127810 r128096 1166 1166 } 1167 1167 1168 void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activationCell , int32_t unmodifiedArgumentsRegister)1168 void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activationCell) 1169 1169 { 1170 1170 JSGlobalData& globalData = exec->globalData(); 1171 1171 NativeCallFrameTracer tracer(&globalData, exec); 1172 if (!activationCell) { 1173 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister).jsValue()) { 1174 if (!exec->codeBlock()->isStrictMode()) 1175 asArguments(v)->tearOff(exec); 1176 } 1172 jsCast<JSActivation*>(activationCell)->tearOff(exec->globalData()); 1173 } 1174 1175 void DFG_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell* activationCell) 1176 { 1177 ASSERT(exec->codeBlock()->usesArguments()); 1178 if (activationCell) { 1179 jsCast<Arguments*>(argumentsCell)->didTearOffActivation(exec->globalData(), jsCast<JSActivation*>(activationCell)); 1177 1180 return; 1178 1181 } 1179 JSActivation* activation = jsCast<JSActivation*>(activationCell); 1180 activation->tearOff(exec->globalData()); 1181 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister).jsValue()) 1182 asArguments(v)->didTearOffActivation(exec->globalData(), activation); 1183 } 1184 1185 1186 void DFG_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell) 1187 { 1188 ASSERT(exec->codeBlock()->usesArguments()); 1189 ASSERT(!exec->codeBlock()->needsFullScopeChain()); 1190 asArguments(argumentsCell)->tearOff(exec); 1182 jsCast<Arguments*>(argumentsCell)->tearOff(exec); 1191 1183 } 1192 1184 1193 1185 void DFG_OPERATION operationTearOffInlinedArguments( 1194 ExecState* exec, JSCell* argumentsCell, InlineCallFrame* inlineCallFrame) 1195 { 1196 // This should only be called when the inline code block uses arguments but does not 1197 // need a full scope chain. We could assert it, except that the assertion would be 1198 // rather expensive and may cause side effects that would greatly diverge debug-mode 1199 // behavior from release-mode behavior, since getting the code block of an inline 1200 // call frame implies call frame reification. 1201 asArguments(argumentsCell)->tearOff(exec, inlineCallFrame); 1186 ExecState* exec, JSCell* argumentsCell, JSCell* activationCell, InlineCallFrame* inlineCallFrame) 1187 { 1188 ASSERT_UNUSED(activationCell, !activationCell); // Currently, we don't inline functions with activations. 1189 jsCast<Arguments*>(argumentsCell)->tearOff(exec, inlineCallFrame); 1202 1190 } 1203 1191 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r127536 r128096 99 99 typedef void DFG_OPERATION (*V_DFGOperation_EC)(ExecState*, JSCell*); 100 100 typedef void DFG_OPERATION (*V_DFGOperation_ECIcf)(ExecState*, JSCell*, InlineCallFrame*); 101 typedef void DFG_OPERATION (*V_DFGOperation_ECCIcf)(ExecState*, JSCell*, JSCell*, InlineCallFrame*); 101 102 typedef void DFG_OPERATION (*V_DFGOperation_ECJJ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue); 102 103 typedef void DFG_OPERATION (*V_DFGOperation_ECZ)(ExecState*, JSCell*, int32_t); 104 typedef void DFG_OPERATION (*V_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*); 103 105 typedef void DFG_OPERATION (*V_DFGOperation_EJCI)(ExecState*, EncodedJSValue, JSCell*, Identifier*); 104 106 typedef void DFG_OPERATION (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue); … … 174 176 JSCell* DFG_OPERATION operationCreateArguments(ExecState*) WTF_INTERNAL; 175 177 JSCell* DFG_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*) WTF_INTERNAL; 176 void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell* , int32_t unmodifiedArgumentsRegister) WTF_INTERNAL;177 void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell* ) WTF_INTERNAL;178 void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, InlineCallFrame*) WTF_INTERNAL;178 void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*) WTF_INTERNAL; 179 void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*, JSCell*) WTF_INTERNAL; 180 void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, JSCell*, InlineCallFrame*) WTF_INTERNAL; 179 181 EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*, int32_t) WTF_INTERNAL; 180 182 EncodedJSValue DFG_OPERATION operationGetInlinedArgumentByVal(ExecState*, int32_t, InlineCallFrame*, int32_t) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r127561 r128096 1354 1354 return appendCallWithExceptionCheck(operation); 1355 1355 } 1356 JITCompiler::Call callOperation(V_DFGOperation_ECCIcf operation, GPRReg arg1, GPRReg arg2, InlineCallFrame* arg3) 1357 { 1358 m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arg3)); 1359 return appendCallWithExceptionCheck(operation); 1360 } 1356 1361 JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1, GPRReg arg2, void* pointer) 1357 1362 { … … 1387 1392 { 1388 1393 m_jit.setupArgumentsWithExecState(arg1, TrustedImm32(arg2)); 1394 return appendCallWithExceptionCheck(operation); 1395 } 1396 JITCompiler::Call callOperation(V_DFGOperation_ECC operation, GPRReg arg1, GPRReg arg2) 1397 { 1398 m_jit.setupArgumentsWithExecState(arg1, arg2); 1389 1399 return appendCallWithExceptionCheck(operation); 1390 1400 } … … 1652 1662 return appendCallWithExceptionCheck(operation); 1653 1663 } 1664 JITCompiler::Call callOperation(V_DFGOperation_ECCIcf operation, GPRReg arg1, GPRReg arg2, InlineCallFrame* inlineCallFrame) 1665 { 1666 m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(inlineCallFrame)); 1667 return appendCallWithExceptionCheck(operation); 1668 } 1654 1669 JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, void* pointer) 1655 1670 { … … 1672 1687 return appendCallWithExceptionCheck(operation); 1673 1688 } 1689 JITCompiler::Call callOperation(V_DFGOperation_ECC operation, GPRReg arg1, GPRReg arg2) 1690 { 1691 m_jit.setupArgumentsWithExecState(arg1, arg2); 1692 return appendCallWithExceptionCheck(operation); 1693 } 1674 1694 JITCompiler::Call callOperation(V_DFGOperation_EPZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload) 1675 1695 { … … 1696 1716 { 1697 1717 return callOperation(operation, arg1, arg2); 1718 } 1719 template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3> 1720 JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2, ArgumentType3 arg3) 1721 { 1722 return callOperation(operation, arg1, arg2, arg3); 1698 1723 } 1699 1724 template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3, typename ArgumentType4> -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r127536 r128096 4024 4024 case TearOffActivation: { 4025 4025 JSValueOperand activationValue(this, node.child1()); 4026 JSValueOperand argumentsValue(this, node.child2());4027 4026 4028 4027 GPRReg activationValueTagGPR = activationValue.tagGPR(); 4029 4028 GPRReg activationValuePayloadGPR = activationValue.payloadGPR(); 4030 GPRReg argumentsValueTagGPR = argumentsValue.tagGPR(); 4031 4032 JITCompiler::JumpList created; 4033 created.append(m_jit.branch32(JITCompiler::NotEqual, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag))); 4034 created.append(m_jit.branch32(JITCompiler::NotEqual, argumentsValueTagGPR, TrustedImm32(JSValue::EmptyValueTag))); 4035 4029 4030 JITCompiler::Jump created = m_jit.branch32(JITCompiler::NotEqual, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4031 4036 4032 addSlowPathGenerator( 4037 4033 slowPathCall( 4038 created, this, operationTearOffActivation, NoResult, activationValuePayloadGPR, 4039 static_cast<int32_t>(node.unmodifiedArgumentsRegister()))); 4034 created, this, operationTearOffActivation, NoResult, activationValuePayloadGPR)); 4040 4035 4041 4036 noResult(m_compileIndex); … … 4044 4039 4045 4040 case TearOffArguments: { 4046 JSValueOperand argumentsValue(this, node.child1()); 4047 GPRReg argumentsValueTagGPR = argumentsValue.tagGPR(); 4048 GPRReg argumentsValuePayloadGPR = argumentsValue.payloadGPR(); 4049 4050 JITCompiler::Jump created = m_jit.branch32( 4051 JITCompiler::NotEqual, argumentsValueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4041 JSValueOperand unmodifiedArgumentsValue(this, node.child1()); 4042 JSValueOperand activationValue(this, node.child2()); 4043 GPRReg unmodifiedArgumentsValuePayloadGPR = unmodifiedArgumentsValue.payloadGPR(); 4044 GPRReg activationValuePayloadGPR = activationValue.payloadGPR(); 4045 4046 JITCompiler::Jump created = m_jit.branchTest32( 4047 JITCompiler::NonZero, unmodifiedArgumentsValuePayloadGPR); 4052 4048 4053 4049 if (node.codeOrigin.inlineCallFrame) { … … 4055 4051 slowPathCall( 4056 4052 created, this, operationTearOffInlinedArguments, NoResult, 4057 argumentsValuePayloadGPR, node.codeOrigin.inlineCallFrame));4053 unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR, node.codeOrigin.inlineCallFrame)); 4058 4054 } else { 4059 4055 addSlowPathGenerator( 4060 4056 slowPathCall( 4061 4057 created, this, operationTearOffArguments, NoResult, 4062 argumentsValuePayloadGPR));4058 unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR)); 4063 4059 } 4064 4060 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r127536 r128096 3973 3973 break; 3974 3974 } 3975 3975 3976 3976 case TearOffActivation: { 3977 3977 ASSERT(!node.codeOrigin.inlineCallFrame); 3978 3978 3979 3979 JSValueOperand activationValue(this, node.child1()); 3980 JSValueOperand argumentsValue(this, node.child2());3981 3980 GPRReg activationValueGPR = activationValue.gpr(); 3982 GPRReg argumentsValueGPR = argumentsValue.gpr(); 3983 3984 JITCompiler::JumpList created; 3985 created.append(m_jit.branchTestPtr(JITCompiler::NonZero, activationValueGPR)); 3986 created.append(m_jit.branchTestPtr(JITCompiler::NonZero, argumentsValueGPR)); 3981 3982 JITCompiler::Jump created = m_jit.branchTestPtr(JITCompiler::NonZero, activationValueGPR); 3987 3983 3988 3984 addSlowPathGenerator( 3989 3985 slowPathCall( 3990 created, this, operationTearOffActivation, NoResult, activationValueGPR, 3991 static_cast<int32_t>(node.unmodifiedArgumentsRegister()))); 3986 created, this, operationTearOffActivation, NoResult, activationValueGPR)); 3992 3987 3993 3988 noResult(m_compileIndex); 3994 3989 break; 3995 3990 } 3996 3991 3997 3992 case TearOffArguments: { 3998 JSValueOperand argumentsValue(this, node.child1()); 3999 GPRReg argumentsValueGPR = argumentsValue.gpr(); 4000 4001 JITCompiler::Jump created = m_jit.branchTestPtr(JITCompiler::NonZero, argumentsValueGPR); 4002 3993 JSValueOperand unmodifiedArgumentsValue(this, node.child1()); 3994 JSValueOperand activationValue(this, node.child2()); 3995 GPRReg unmodifiedArgumentsValueGPR = unmodifiedArgumentsValue.gpr(); 3996 GPRReg activationValueGPR = activationValue.gpr(); 3997 3998 JITCompiler::Jump created = m_jit.branchTestPtr(JITCompiler::NonZero, unmodifiedArgumentsValueGPR); 3999 4003 4000 if (node.codeOrigin.inlineCallFrame) { 4004 4001 addSlowPathGenerator( 4005 4002 slowPathCall( 4006 4003 created, this, operationTearOffInlinedArguments, NoResult, 4007 argumentsValueGPR, node.codeOrigin.inlineCallFrame));4004 unmodifiedArgumentsValueGPR, activationValueGPR, node.codeOrigin.inlineCallFrame)); 4008 4005 } else { 4009 4006 addSlowPathGenerator( 4010 4007 slowPathCall( 4011 created, this, operationTearOffArguments, NoResult, argumentsValueGPR));4008 created, this, operationTearOffArguments, NoResult, unmodifiedArgumentsValueGPR, activationValueGPR)); 4012 4009 } 4013 4010 -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r127958 r128096 4476 4476 } 4477 4477 DEFINE_OPCODE(op_tear_off_activation) { 4478 /* tear_off_activation activation(r) arguments(r)4478 /* tear_off_activation activation(r) 4479 4479 4480 4480 Copy locals and named parameters from the register file to the heap. 4481 Point the bindings in 'activation' and 'arguments' to this new backing 4482 store. (Note that 'arguments' may not have been created. If created, 4483 'arguments' already holds a copy of any extra / unnamed parameters.) 4481 Point the bindings in 'activation' to this new backing store. 4484 4482 4485 4483 This opcode appears before op_ret in functions that require full scope chains. … … 4487 4485 4488 4486 int activation = vPC[1].u.operand; 4489 int arguments = vPC[2].u.operand;4490 4487 ASSERT(codeBlock->needsFullScopeChain()); 4491 4488 JSValue activationValue = callFrame->r(activation).jsValue(); 4492 if (activationValue) {4489 if (activationValue) 4493 4490 asActivation(activationValue)->tearOff(*globalData); 4494 4491 4495 if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue())4496 asArguments(argumentsValue)->didTearOffActivation(*globalData, asActivation(activationValue));4497 } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {4498 if (!codeBlock->isStrictMode())4499 asArguments(argumentsValue)->tearOff(callFrame);4500 }4501 4502 4492 vPC += OPCODE_LENGTH(op_tear_off_activation); 4503 4493 NEXT_INSTRUCTION(); 4504 4494 } 4505 4495 DEFINE_OPCODE(op_tear_off_arguments) { 4506 /* tear_off_arguments arguments(r) 4496 /* tear_off_arguments arguments(r) activation(r) 4507 4497 4508 4498 Copy named parameters from the register file to the heap. Point the 4509 bindings in 'arguments' to this new backing store. (Note that 4510 'arguments' may not have been created. If created, 'arguments' already 4511 holds a copy of any extra / unnamed parameters.) 4499 bindings in 'arguments' to this new backing store. (If 'activation' 4500 was also copied to the heap, 'arguments' will point to its storage.) 4512 4501 4513 4502 This opcode appears before op_ret in functions that don't require full … … 4515 4504 */ 4516 4505 4517 int src1 = vPC[1].u.operand; 4518 ASSERT(!codeBlock->needsFullScopeChain() && codeBlock->ownerExecutable()->usesArguments()); 4519 4520 if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue()) 4521 asArguments(arguments)->tearOff(callFrame); 4506 int arguments = vPC[1].u.operand; 4507 int activation = vPC[2].u.operand; 4508 ASSERT(codeBlock->usesArguments()); 4509 if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) { 4510 if (JSValue activationValue = callFrame->r(activation).jsValue()) 4511 asArguments(argumentsValue)->didTearOffActivation(callFrame->globalData(), asActivation(activationValue)); 4512 else 4513 asArguments(argumentsValue)->tearOff(callFrame); 4514 } 4522 4515 4523 4516 vPC += OPCODE_LENGTH(op_tear_off_arguments); -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r127394 r128096 560 560 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction) 561 561 { 562 unsigned activation = currentInstruction[1].u.operand; 563 unsigned arguments = currentInstruction[2].u.operand; 564 Jump activationCreated = branchTestPtr(NonZero, addressFor(activation)); 565 Jump argumentsNotCreated = branchTestPtr(Zero, addressFor(arguments)); 566 activationCreated.link(this); 562 int activation = currentInstruction[1].u.operand; 563 Jump activationNotCreated = branchTestPtr(Zero, addressFor(activation)); 567 564 JITStubCall stubCall(this, cti_op_tear_off_activation); 568 565 stubCall.addArgument(activation, regT2); 569 stubCall.addArgument(unmodifiedArgumentsRegister(arguments), regT2); 570 stubCall.call(); 571 argumentsNotCreated.link(this); 566 stubCall.call(); 567 activationNotCreated.link(this); 572 568 } 573 569 574 570 void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction) 575 571 { 576 unsigned dst = currentInstruction[1].u.operand; 572 int dst = currentInstruction[1].u.operand; 573 int activation = currentInstruction[2].u.operand; 577 574 578 575 Jump argsNotCreated = branchTestPtr(Zero, Address(callFrameRegister, sizeof(Register) * (unmodifiedArgumentsRegister(dst)))); 579 576 JITStubCall stubCall(this, cti_op_tear_off_arguments); 580 577 stubCall.addArgument(unmodifiedArgumentsRegister(dst), regT2); 578 stubCall.addArgument(activation, regT2); 581 579 stubCall.call(); 582 580 argsNotCreated.link(this); -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r127394 r128096 704 704 { 705 705 unsigned activation = currentInstruction[1].u.operand; 706 unsigned arguments = currentInstruction[2].u.operand; 707 Jump activationCreated = branch32(NotEqual, tagFor(activation), TrustedImm32(JSValue::EmptyValueTag)); 708 Jump argumentsNotCreated = branch32(Equal, tagFor(arguments), TrustedImm32(JSValue::EmptyValueTag)); 709 activationCreated.link(this); 706 Jump activationNotCreated = branch32(Equal, tagFor(activation), TrustedImm32(JSValue::EmptyValueTag)); 710 707 JITStubCall stubCall(this, cti_op_tear_off_activation); 711 stubCall.addArgument(currentInstruction[1].u.operand); 712 stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand)); 708 stubCall.addArgument(activation); 713 709 stubCall.call(); 714 a rgumentsNotCreated.link(this);710 activationNotCreated.link(this); 715 711 } 716 712 … … 718 714 { 719 715 int dst = currentInstruction[1].u.operand; 716 int activation = currentInstruction[1].u.operand; 720 717 721 718 Jump argsNotCreated = branch32(Equal, tagFor(unmodifiedArgumentsRegister(dst)), TrustedImm32(JSValue::EmptyValueTag)); 722 719 JITStubCall stubCall(this, cti_op_tear_off_arguments); 723 720 stubCall.addArgument(unmodifiedArgumentsRegister(dst)); 721 stubCall.addArgument(activation); 724 722 stubCall.call(); 725 723 argsNotCreated.link(this); -
trunk/Source/JavaScriptCore/jit/JITStubs.cpp
r127958 r128096 2312 2312 STUB_INIT_STACK_FRAME(stackFrame); 2313 2313 2314 CallFrame* callFrame = stackFrame.callFrame; 2315 ASSERT(callFrame->codeBlock()->needsFullScopeChain()); 2316 JSValue activationValue = stackFrame.args[0].jsValue(); 2317 if (!activationValue) { 2318 if (JSValue v = stackFrame.args[1].jsValue()) { 2319 if (!callFrame->codeBlock()->isStrictMode()) 2320 asArguments(v)->tearOff(callFrame); 2321 } 2314 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain()); 2315 jsCast<JSActivation*>(stackFrame.args[0].jsValue())->tearOff(*stackFrame.globalData); 2316 } 2317 2318 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments) 2319 { 2320 STUB_INIT_STACK_FRAME(stackFrame); 2321 2322 CallFrame* callFrame = stackFrame.callFrame; 2323 ASSERT(callFrame->codeBlock()->usesArguments()); 2324 Arguments* arguments = jsCast<Arguments*>(stackFrame.args[0].jsValue()); 2325 if (JSValue activationValue = stackFrame.args[1].jsValue()) { 2326 arguments->didTearOffActivation(callFrame->globalData(), jsCast<JSActivation*>(activationValue)); 2322 2327 return; 2323 2328 } 2324 JSActivation* activation = asActivation(stackFrame.args[0].jsValue()); 2325 activation->tearOff(*stackFrame.globalData); 2326 if (JSValue v = stackFrame.args[1].jsValue()) 2327 asArguments(v)->didTearOffActivation(*stackFrame.globalData, activation); 2328 } 2329 2330 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments) 2331 { 2332 STUB_INIT_STACK_FRAME(stackFrame); 2333 2334 CallFrame* callFrame = stackFrame.callFrame; 2335 ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain()); 2336 asArguments(stackFrame.args[0].jsValue())->tearOff(callFrame); 2329 arguments->tearOff(callFrame); 2337 2330 } 2338 2331 -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r127958 r128096 1455 1455 LLINT_BEGIN(); 1456 1456 ASSERT(exec->codeBlock()->needsFullScopeChain()); 1457 JSValue activationValue = LLINT_OP(1).jsValue(); 1458 if (!activationValue) { 1459 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue()) { 1460 if (!exec->codeBlock()->isStrictMode()) 1461 asArguments(v)->tearOff(exec); 1462 } 1463 LLINT_END(); 1464 } 1465 JSActivation* activation = asActivation(activationValue); 1466 activation->tearOff(globalData); 1467 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue()) 1468 asArguments(v)->didTearOffActivation(globalData, activation); 1457 jsCast<JSActivation*>(LLINT_OP(1).jsValue())->tearOff(globalData); 1469 1458 LLINT_END(); 1470 1459 } … … 1473 1462 { 1474 1463 LLINT_BEGIN(); 1475 ASSERT(exec->codeBlock()->usesArguments() && !exec->codeBlock()->needsFullScopeChain()); 1476 asArguments(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue())->tearOff(exec); 1464 ASSERT(exec->codeBlock()->usesArguments()); 1465 Arguments* arguments = jsCast<Arguments*>(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue()); 1466 if (JSValue activationValue = LLINT_OP_C(2).jsValue()) 1467 arguments->didTearOffActivation(globalData, jsCast<JSActivation*>(activationValue)); 1468 else 1469 arguments->tearOff(exec); 1477 1470 LLINT_END(); 1478 1471 } -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r127374 r128096 1640 1640 traceExecution() 1641 1641 loadi 4[PC], t0 1642 loadi 8[PC], t1 1643 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationCreated 1644 bieq TagOffset[cfr, t1, 8], EmptyValueTag, .opTearOffActivationNotCreated 1645 .opTearOffActivationCreated: 1642 bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationNotCreated 1646 1643 callSlowPath(_llint_slow_path_tear_off_activation) 1647 1644 .opTearOffActivationNotCreated: 1648 dispatch( 3)1645 dispatch(2) 1649 1646 1650 1647 … … 1656 1653 callSlowPath(_llint_slow_path_tear_off_arguments) 1657 1654 .opTearOffArgumentsNotCreated: 1658 dispatch( 2)1655 dispatch(3) 1659 1656 1660 1657 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r127374 r128096 1484 1484 traceExecution() 1485 1485 loadis 8[PB, PC, 8], t0 1486 loadis 16[PB, PC, 8], t1 1487 btpnz [cfr, t0, 8], .opTearOffActivationCreated 1488 btpz [cfr, t1, 8], .opTearOffActivationNotCreated 1489 .opTearOffActivationCreated: 1486 btpz [cfr, t0, 8], .opTearOffActivationNotCreated 1490 1487 callSlowPath(_llint_slow_path_tear_off_activation) 1491 1488 .opTearOffActivationNotCreated: 1492 dispatch( 3)1489 dispatch(2) 1493 1490 1494 1491 … … 1500 1497 callSlowPath(_llint_slow_path_tear_off_arguments) 1501 1498 .opTearOffArgumentsNotCreated: 1502 dispatch( 2)1499 dispatch(3) 1503 1500 1504 1501
Note: See TracChangeset
for help on using the changeset viewer.