Changeset 129156 in webkit
- Timestamp:
- Sep 20, 2012 12:51:58 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r129154 r129156 1 2012-09-20 Geoffrey Garen <ggaren@apple.com> 2 3 Refactored the interpreter and JIT so they don't dictate closure layout 4 https://bugs.webkit.org/show_bug.cgi?id=97221 5 6 Reviewed by Oliver Hunt. 7 8 * fast/js/dfg-arguments-alias-activation-expected.txt: Added. 9 * fast/js/dfg-arguments-alias-activation.html: Added. 10 1 11 2012-09-20 Tony Chang <tony@chromium.org> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r129127 r129156 1 2012-09-20 Geoffrey Garen <ggaren@apple.com> 2 3 Refactored the interpreter and JIT so they don't dictate closure layout 4 https://bugs.webkit.org/show_bug.cgi?id=97221 5 6 Reviewed by Oliver Hunt. 7 8 Capture may change the location of an argument for space efficiency. This 9 patch removes static assumptions about argument location from the interpreter 10 and JIT. 11 12 * bytecode/CodeBlock.h: 13 (JSC::CodeBlock::argumentIndexAfterCapture): 14 (JSC::ExecState::argumentAfterCapture): Factored out a helper function 15 so the compiler could share this logic. 16 17 * bytecompiler/NodesCodegen.cpp: 18 (JSC::BracketAccessorNode::emitBytecode): Don't emit optimized bracket 19 access on arguments if a parameter has been captured by name. This case is 20 rare and, where I've seen it in the wild, the optimization mostly failed 21 anyway due to arguments escape, so I didn't feel like writing and testing 22 five copies of the code that would handle it in the baseline engines. 23 24 The DFG can still synthesize this optimization even if we don't emit the 25 optimized bytecode for it. 26 27 * dfg/DFGArgumentsSimplificationPhase.cpp: 28 (JSC::DFG::ArgumentsSimplificationPhase::run): 29 * dfg/DFGAssemblyHelpers.h: 30 (JSC::DFG::AssemblyHelpers::symbolTableFor): 31 (AssemblyHelpers): Use the right helper function to account for the fact 32 that a parameter may have been captured by name and moved. 33 34 * dfg/DFGByteCodeParser.cpp: 35 (JSC::DFG::ByteCodeParser::parseBlock): ASSERT that we haven't inlined 36 a .apply on captured arguments. Once we do start inlining such things, 37 we'll need to do a little bit of math here to get them right. 38 39 * dfg/DFGSpeculativeJIT32_64.cpp: 40 (JSC::DFG::SpeculativeJIT::compile): 41 * dfg/DFGSpeculativeJIT64.cpp: 42 (JSC::DFG::SpeculativeJIT::compile): Added support for bracket access on 43 an arguments object where arguments have also been captured by name. We 44 load the true index of the argument from a side vector. Arguments elision 45 is very powerful in the DFG, so I wanted to keep it working, even in this 46 rare case. 47 48 * interpreter/Interpreter.cpp: 49 (JSC::loadVarargs): Use the right helper function to account for the fact 50 that a parameter may have been captured by name and moved. 51 52 * jit/JITCall.cpp: 53 (JSC::JIT::compileLoadVarargs): 54 * jit/JITCall32_64.cpp: 55 (JSC::JIT::compileLoadVarargs): Don't use the inline copy loop if some 56 of our arguments have moved, since it would copy stale values. (We still 57 optimize the actual call, and elide the arguments object.) 58 1 59 2012-09-20 Gabor Rapcsanyi <rgabor@webkit.org> 2 60 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r128832 r129156 433 433 unsigned instructionCount() { return m_instructions.size(); } 434 434 435 int argumentIndexAfterCapture(size_t argument); 436 435 437 #if ENABLE(JIT) 436 438 void setJITCode(const JITCode& code, MacroAssemblerCodePtr codeWithArityCheck) … … 1521 1523 } 1522 1524 1525 inline int CodeBlock::argumentIndexAfterCapture(size_t argument) 1526 { 1527 if (argument >= static_cast<size_t>(symbolTable()->parameterCount())) 1528 return CallFrame::argumentOffset(argument); 1529 1530 const SlowArgument* slowArguments = symbolTable()->slowArguments(); 1531 if (!slowArguments || slowArguments[argument].status == SlowArgument::Normal) 1532 return CallFrame::argumentOffset(argument); 1533 1534 ASSERT(slowArguments[argument].status == SlowArgument::Captured); 1535 return slowArguments[argument].indexIfCaptured; 1536 } 1523 1537 1524 1538 inline Register& ExecState::r(int index) … … 1553 1567 return this[argumentOffset(argument)].jsValue(); 1554 1568 1555 if (argument >= static_cast<size_t>(codeBlock()->symbolTable()->parameterCount())) 1556 return this[argumentOffset(argument)].jsValue(); 1557 1558 const SlowArgument* slowArguments = codeBlock()->symbolTable()->slowArguments(); 1559 if (!slowArguments || slowArguments[argument].status == SlowArgument::Normal) 1560 return this[argumentOffset(argument)].jsValue(); 1561 1562 ASSERT(slowArguments[argument].status == SlowArgument::Captured); 1563 return this[slowArguments[argument].indexIfCaptured].jsValue(); 1569 return this[codeBlock()->argumentIndexAfterCapture(argument)].jsValue(); 1564 1570 } 1565 1571 -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r128534 r129156 321 321 RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 322 322 { 323 if (m_base->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())) { 323 if (m_base->isResolveNode() 324 && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier()) 325 && !generator.symbolTable().slowArguments()) { 324 326 RegisterID* property = generator.emitNode(m_subscript); 325 327 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); -
trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
r129089 r129156 585 585 static_cast<VirtualRegister>( 586 586 node.codeOrigin.inlineCallFrame->stackOffset + 587 argumentToOperand(index + 1)));588 587 m_graph.baselineCodeBlockFor(node.codeOrigin)->argumentIndexAfterCapture(index))); 588 589 589 NodeIndex checkNodeIndex = m_graph.size(); 590 590 m_graph.append(check); -
trunk/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
r122392 r129156 344 344 } 345 345 346 SharedSymbolTable* symbolTableFor(const CodeOrigin& codeOrigin) 347 { 348 return baselineCodeBlockFor(codeOrigin)->symbolTable(); 349 } 350 351 int offsetOfLocals(const CodeOrigin& codeOrigin) 352 { 353 if (!codeOrigin.inlineCallFrame) 354 return 0; 355 return codeOrigin.inlineCallFrame->stackOffset * sizeof(Register); 356 } 357 358 int offsetOfArgumentsIncludingThis(const CodeOrigin& codeOrigin) 359 { 360 if (!codeOrigin.inlineCallFrame) 361 return CallFrame::argumentOffsetIncludingThis(0) * sizeof(Register); 362 return (codeOrigin.inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(0)) * sizeof(Register); 363 } 364 346 365 Vector<BytecodeAndMachineOffset>& decodedCodeMapFor(CodeBlock*); 347 366 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r128957 r129156 2715 2715 ASSERT(m_inlineStackTop->m_inlineCallFrame); 2716 2716 ASSERT(currentInstruction[3].u.operand == m_inlineStackTop->m_codeBlock->argumentsRegister()); 2717 ASSERT(!m_inlineStackTop->m_codeBlock->symbolTable()->slowArguments()); 2717 2718 // It would be cool to funnel this into handleCall() so that it can handle 2718 2719 // inlining. But currently that won't be profitable anyway, since none of the -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r129089 r129156 4203 4203 } 4204 4204 4205 JITCompiler::JumpList slowArgument; 4206 JITCompiler::JumpList slowArgumentOutOfBounds; 4207 if (const SlowArgument* slowArguments = m_jit.symbolTableFor(node.codeOrigin)->slowArguments()) { 4208 slowArgumentOutOfBounds.append( 4209 m_jit.branch32( 4210 JITCompiler::AboveOrEqual, indexGPR, 4211 Imm32(m_jit.symbolTableFor(node.codeOrigin)->parameterCount()))); 4212 4213 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4214 m_jit.move(ImmPtr(slowArguments), resultPayloadGPR); 4215 m_jit.load32( 4216 JITCompiler::BaseIndex( 4217 resultPayloadGPR, indexGPR, JITCompiler::TimesEight, 4218 OBJECT_OFFSETOF(SlowArgument, indexIfCaptured)), 4219 resultPayloadGPR); 4220 4221 m_jit.load32( 4222 JITCompiler::BaseIndex( 4223 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4224 m_jit.offsetOfLocals(node.codeOrigin) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4225 resultTagGPR); 4226 m_jit.load32( 4227 JITCompiler::BaseIndex( 4228 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4229 m_jit.offsetOfLocals(node.codeOrigin) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4230 resultPayloadGPR); 4231 slowArgument.append(m_jit.jump()); 4232 } 4233 slowArgumentOutOfBounds.link(&m_jit); 4234 4205 4235 m_jit.neg32(resultPayloadGPR); 4206 4236 4207 size_t baseOffset =4208 ((node.codeOrigin.inlineCallFrame4209 ? node.codeOrigin.inlineCallFrame->stackOffset4210 : 0) + CallFrame::argumentOffsetIncludingThis(0)) * sizeof(Register);4211 4237 m_jit.load32( 4212 4238 JITCompiler::BaseIndex( 4213 4239 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4214 baseOffset+ OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),4240 m_jit.offsetOfArgumentsIncludingThis(node.codeOrigin) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4215 4241 resultTagGPR); 4216 4242 m_jit.load32( 4217 4243 JITCompiler::BaseIndex( 4218 4244 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4219 baseOffset+ OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),4245 m_jit.offsetOfArgumentsIncludingThis(node.codeOrigin) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4220 4246 resultPayloadGPR); 4221 4247 4248 slowArgument.link(&m_jit); 4222 4249 jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex); 4223 4250 break; … … 4253 4280 } 4254 4281 4282 JITCompiler::JumpList slowArgument; 4283 JITCompiler::JumpList slowArgumentOutOfBounds; 4284 if (const SlowArgument* slowArguments = m_jit.symbolTableFor(node.codeOrigin)->slowArguments()) { 4285 slowArgumentOutOfBounds.append( 4286 m_jit.branch32( 4287 JITCompiler::AboveOrEqual, indexGPR, 4288 Imm32(m_jit.symbolTableFor(node.codeOrigin)->parameterCount()))); 4289 4290 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4291 m_jit.move(ImmPtr(slowArguments), resultPayloadGPR); 4292 m_jit.load32( 4293 JITCompiler::BaseIndex( 4294 resultPayloadGPR, indexGPR, JITCompiler::TimesEight, 4295 OBJECT_OFFSETOF(SlowArgument, indexIfCaptured)), 4296 resultPayloadGPR); 4297 m_jit.load32( 4298 JITCompiler::BaseIndex( 4299 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4300 m_jit.offsetOfLocals(node.codeOrigin) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4301 resultTagGPR); 4302 m_jit.load32( 4303 JITCompiler::BaseIndex( 4304 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4305 m_jit.offsetOfLocals(node.codeOrigin) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4306 resultPayloadGPR); 4307 slowArgument.append(m_jit.jump()); 4308 } 4309 slowArgumentOutOfBounds.link(&m_jit); 4310 4255 4311 m_jit.neg32(resultPayloadGPR); 4256 4312 4257 size_t baseOffset =4258 ((node.codeOrigin.inlineCallFrame4259 ? node.codeOrigin.inlineCallFrame->stackOffset4260 : 0) + CallFrame::argumentOffsetIncludingThis(0)) * sizeof(Register);4261 4313 m_jit.load32( 4262 4314 JITCompiler::BaseIndex( 4263 4315 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4264 baseOffset+ OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),4316 m_jit.offsetOfArgumentsIncludingThis(node.codeOrigin) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4265 4317 resultTagGPR); 4266 4318 m_jit.load32( 4267 4319 JITCompiler::BaseIndex( 4268 4320 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4269 baseOffset+ OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),4321 m_jit.offsetOfArgumentsIncludingThis(node.codeOrigin) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4270 4322 resultPayloadGPR); 4271 4323 … … 4285 4337 } 4286 4338 4339 slowArgument.link(&m_jit); 4287 4340 jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex); 4288 4341 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r129089 r129156 4123 4123 GPRReg indexGPR = index.gpr(); 4124 4124 GPRReg resultGPR = result.gpr(); 4125 4125 4126 4126 if (!isEmptySpeculation( 4127 4127 m_state.variables().operand( … … 4151 4151 JITCompiler::payloadFor(RegisterFile::ArgumentCount))); 4152 4152 } 4153 4153 4154 JITCompiler::JumpList slowArgument; 4155 JITCompiler::JumpList slowArgumentOutOfBounds; 4156 if (const SlowArgument* slowArguments = m_jit.symbolTableFor(node.codeOrigin)->slowArguments()) { 4157 slowArgumentOutOfBounds.append( 4158 m_jit.branch32( 4159 JITCompiler::AboveOrEqual, indexGPR, 4160 Imm32(m_jit.symbolTableFor(node.codeOrigin)->parameterCount()))); 4161 4162 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4163 m_jit.move(ImmPtr(slowArguments), resultGPR); 4164 m_jit.load32( 4165 JITCompiler::BaseIndex( 4166 resultGPR, indexGPR, JITCompiler::TimesEight, 4167 OBJECT_OFFSETOF(SlowArgument, indexIfCaptured)), 4168 resultGPR); 4169 m_jit.signExtend32ToPtr(resultGPR, resultGPR); 4170 m_jit.loadPtr( 4171 JITCompiler::BaseIndex( 4172 GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight, m_jit.offsetOfLocals(node.codeOrigin)), 4173 resultGPR); 4174 slowArgument.append(m_jit.jump()); 4175 } 4176 slowArgumentOutOfBounds.link(&m_jit); 4177 4154 4178 m_jit.neg32(resultGPR); 4155 4179 m_jit.signExtend32ToPtr(resultGPR, resultGPR); … … 4157 4181 m_jit.loadPtr( 4158 4182 JITCompiler::BaseIndex( 4159 GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight, 4160 ((node.codeOrigin.inlineCallFrame 4161 ? node.codeOrigin.inlineCallFrame->stackOffset 4162 : 0) + CallFrame::argumentOffsetIncludingThis(0)) * sizeof(Register)), 4183 GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight, m_jit.offsetOfArgumentsIncludingThis(node.codeOrigin)), 4163 4184 resultGPR); 4164 4185 4186 slowArgument.link(&m_jit); 4165 4187 jsValueResult(resultGPR, m_compileIndex); 4166 4188 break; … … 4195 4217 } 4196 4218 4219 JITCompiler::JumpList slowArgument; 4220 JITCompiler::JumpList slowArgumentOutOfBounds; 4221 if (const SlowArgument* slowArguments = m_jit.symbolTableFor(node.codeOrigin)->slowArguments()) { 4222 slowArgumentOutOfBounds.append( 4223 m_jit.branch32( 4224 JITCompiler::AboveOrEqual, indexGPR, 4225 Imm32(m_jit.symbolTableFor(node.codeOrigin)->parameterCount()))); 4226 4227 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4228 m_jit.move(ImmPtr(slowArguments), resultGPR); 4229 m_jit.load32( 4230 JITCompiler::BaseIndex( 4231 resultGPR, indexGPR, JITCompiler::TimesEight, 4232 OBJECT_OFFSETOF(SlowArgument, indexIfCaptured)), 4233 resultGPR); 4234 m_jit.signExtend32ToPtr(resultGPR, resultGPR); 4235 m_jit.loadPtr( 4236 JITCompiler::BaseIndex( 4237 GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight, m_jit.offsetOfLocals(node.codeOrigin)), 4238 resultGPR); 4239 slowArgument.append(m_jit.jump()); 4240 } 4241 slowArgumentOutOfBounds.link(&m_jit); 4242 4197 4243 m_jit.neg32(resultGPR); 4198 4244 m_jit.signExtend32ToPtr(resultGPR, resultGPR); … … 4200 4246 m_jit.loadPtr( 4201 4247 JITCompiler::BaseIndex( 4202 GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight, 4203 ((node.codeOrigin.inlineCallFrame 4204 ? node.codeOrigin.inlineCallFrame->stackOffset 4205 : 0) + CallFrame::argumentOffsetIncludingThis(0)) * sizeof(Register)), 4248 GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight, m_jit.offsetOfArgumentsIncludingThis(node.codeOrigin)), 4206 4249 resultGPR); 4207 4250 … … 4221 4264 } 4222 4265 4266 slowArgument.link(&m_jit); 4223 4267 jsValueResult(resultGPR, m_compileIndex); 4224 4268 break; -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r128832 r129156 203 203 newCallFrame->setThisValue(thisValue); 204 204 for (size_t i = 0; i < callFrame->argumentCount(); ++i) 205 newCallFrame->setArgument(i, callFrame->argument (i));205 newCallFrame->setArgument(i, callFrame->argumentAfterCapture(i)); 206 206 return newCallFrame; 207 207 } -
trunk/Source/JavaScriptCore/jit/JITCall.cpp
r127202 r129156 67 67 JumpList slowCase; 68 68 JumpList end; 69 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) { 69 bool canOptimize = m_codeBlock->usesArguments() 70 && arguments == m_codeBlock->argumentsRegister() 71 && !m_codeBlock->symbolTable()->slowArguments(); 72 73 if (canOptimize) { 70 74 emitGetVirtualRegister(arguments, regT0); 71 75 slowCase.append(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue())))); … … 104 108 } 105 109 106 if ( m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())110 if (canOptimize) 107 111 slowCase.link(this); 108 112 … … 113 117 stubCall.call(regT1); 114 118 115 if ( m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())119 if (canOptimize) 116 120 end.link(this); 117 121 } -
trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp
r127202 r129156 142 142 JumpList slowCase; 143 143 JumpList end; 144 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) { 144 bool canOptimize = m_codeBlock->usesArguments() 145 && arguments == m_codeBlock->argumentsRegister() 146 && !m_codeBlock->symbolTable()->slowArguments(); 147 148 if (canOptimize) { 145 149 emitLoadTag(arguments, regT1); 146 150 slowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag))); … … 181 185 } 182 186 183 if ( m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())187 if (canOptimize) 184 188 slowCase.link(this); 185 189 … … 190 194 stubCall.call(regT3); 191 195 192 if ( m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())196 if (canOptimize) 193 197 end.link(this); 194 198 }
Note: See TracChangeset
for help on using the changeset viewer.