Changeset 91225 in webkit
- Timestamp:
- Jul 18, 2011 5:26:14 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r91224 r91225 1 2011-07-18 Gavin Barraclough <barraclough@apple.com> 2 3 https://bugs.webkit.org/show_bug.cgi?id=64760 4 DFG JIT - Should be able to compile program code. 5 6 Reviewed by Geoff Garen. 7 8 Add support for op_end, hooks to compile program code in Executable.cpp. 9 10 * dfg/DFGByteCodeParser.cpp: 11 (JSC::DFG::ByteCodeParser::parseBlock): 12 - Add support for op_end 13 * dfg/DFGJITCompiler.cpp: 14 (JSC::DFG::JITCompiler::compileEntry): 15 (JSC::DFG::JITCompiler::compileBody): 16 (JSC::DFG::JITCompiler::link): 17 - Added, separate out steps of compileFunction. 18 (JSC::DFG::JITCompiler::compile): 19 - Added, compile program code. 20 (JSC::DFG::JITCompiler::compileFunction): 21 - Sections separated out to helper functions. 22 * dfg/DFGJITCompiler.h: 23 (JSC::DFG::JITCompiler::JITCompiler): 24 - Added m_exceptionCheckCount. 25 * runtime/Executable.cpp: 26 (JSC::tryDFGCompile): 27 (JSC::tryDFGCompileFunction): 28 (JSC::ProgramExecutable::compileInternal): 29 (JSC::FunctionExecutable::compileForCallInternal): 30 - Renamed tryDFGCompile to tryDFGCompileFunction, added tryDFGCompile to compile program code. 31 1 32 2011-07-18 Gavin Barraclough <barraclough@apple.com> 2 33 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r90877 r91225 1113 1113 } 1114 1114 1115 case op_ret: {1115 case op_ret: 1116 1116 addToGraph(Return, get(currentInstruction[1].u.operand)); 1117 1117 LAST_OPCODE(op_ret); 1118 } 1118 1119 case op_end: 1120 addToGraph(Return, get(currentInstruction[1].u.operand)); 1121 LAST_OPCODE(op_end); 1119 1122 1120 1123 case op_call: { -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r90950 r91225 224 224 } 225 225 226 void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck) 227 { 228 // === Stage 1 - Function header code generation === 229 // 226 void JITCompiler::compileEntry() 227 { 230 228 // This code currently matches the old JIT. In the function header we need to 231 229 // pop the return address (since we do not allow any recursion on the machine 232 230 // stack), and perform a fast register file check. 233 234 // This is the main entry point, without performing an arity check.235 231 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56292 236 232 // We'll need to convert the remaining cti_ style calls (specifically the register file … … 239 235 preserveReturnAddressAfterCall(GPRInfo::regT2); 240 236 emitPutToCallFrameHeader(GPRInfo::regT2, RegisterFile::ReturnPC); 241 // If we needed to perform an arity check we will already have moved the return address, 242 // so enter after this. 243 Label fromArityCheck(this); 244 245 // Setup a pointer to the codeblock in the CallFrameHeader. 246 emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock); 247 248 // Plant a check that sufficient space is available in the RegisterFile. 249 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291 250 addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1); 251 Jump registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), GPRInfo::regT1); 252 // Return here after register file check. 253 Label fromRegisterFileCheck = label(); 254 255 256 // === Stage 2 - Function body code generation === 257 // 237 } 238 239 void JITCompiler::compileBody() 240 { 258 241 // We generate the speculative code path, followed by the non-speculative 259 242 // code for the function. Next we need to link the two together, making … … 305 288 } 306 289 307 // === Stage 3 - Function footer code generation ===308 //309 // Generate code to lookup and jump to exception handlers, to perform the slow310 // register file check (if the fast one in the function header fails), and311 // generate the entry point with arity check.312 313 290 // Iterate over the m_calls vector, checking for exception checks, 314 291 // and linking them to here. 315 unsigned exceptionCheckCount = 0;316 292 for (unsigned i = 0; i < m_calls.size(); ++i) { 317 293 Jump& exceptionCheck = m_calls[i].m_exceptionCheck; 318 294 if (exceptionCheck.isSet()) { 319 295 exceptionCheck.link(this); 320 ++ exceptionCheckCount;296 ++m_exceptionCheckCount; 321 297 } 322 298 } 323 299 // If any exception checks were linked, generate code to lookup a handler. 324 if ( exceptionCheckCount) {300 if (m_exceptionCheckCount) { 325 301 // lookupExceptionHandler is passed two arguments, exec (the CallFrame*), and 326 302 // an identifier for the operation that threw the exception, which we can use … … 335 311 jump(GPRInfo::returnValueGPR2); 336 312 } 337 313 } 314 315 void JITCompiler::link(LinkBuffer& linkBuffer) 316 { 317 // Link the code, populate data in CodeBlock data structures. 318 #if DFG_DEBUG_VERBOSE 319 fprintf(stderr, "JIT code start at %p\n", linkBuffer.debugAddress()); 320 #endif 321 322 // Link all calls out from the JIT code to their respective functions. 323 for (unsigned i = 0; i < m_calls.size(); ++i) { 324 if (m_calls[i].m_function.value()) 325 linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function); 326 } 327 328 if (m_codeBlock->needsCallReturnIndices()) { 329 m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionCheckCount); 330 for (unsigned i = 0; i < m_calls.size(); ++i) { 331 if (m_calls[i].m_handlesExceptions) { 332 unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_calls[i].m_call); 333 unsigned exceptionInfo = m_calls[i].m_exceptionInfo; 334 m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo)); 335 } 336 } 337 } 338 339 m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccesses.size()); 340 for (unsigned i = 0; i < m_propertyAccesses.size(); ++i) { 341 StructureStubInfo& info = m_codeBlock->structureStubInfo(i); 342 info.callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall); 343 info.u.unset.deltaCheckImmToCall = m_propertyAccesses[i].m_deltaCheckImmToCall; 344 info.deltaCallToStructCheck = m_propertyAccesses[i].m_deltaCallToStructCheck; 345 info.u.unset.deltaCallToLoadOrStore = m_propertyAccesses[i].m_deltaCallToLoadOrStore; 346 info.deltaCallToSlowCase = m_propertyAccesses[i].m_deltaCallToSlowCase; 347 info.deltaCallToDone = m_propertyAccesses[i].m_deltaCallToDone; 348 info.baseGPR = m_propertyAccesses[i].m_baseGPR; 349 info.valueGPR = m_propertyAccesses[i].m_valueGPR; 350 info.scratchGPR = m_propertyAccesses[i].m_scratchGPR; 351 } 352 353 m_codeBlock->setNumberOfCallLinkInfos(m_jsCalls.size()); 354 for (unsigned i = 0; i < m_jsCalls.size(); ++i) { 355 CallLinkInfo& info = m_codeBlock->callLinkInfo(i); 356 info.isCall = m_jsCalls[i].m_isCall; 357 info.callReturnLocation = CodeLocationLabel(linkBuffer.locationOf(m_jsCalls[i].m_slowCall)); 358 info.hotPathBegin = linkBuffer.locationOf(m_jsCalls[i].m_targetToCheck); 359 info.hotPathOther = linkBuffer.locationOfNearCall(m_jsCalls[i].m_fastCall); 360 } 361 362 m_codeBlock->addMethodCallLinkInfos(m_methodGets.size()); 363 for (unsigned i = 0; i < m_methodGets.size(); ++i) { 364 MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i); 365 info.cachedStructure.setLocation(linkBuffer.locationOf(m_methodGets[i].m_structToCompare)); 366 info.cachedPrototypeStructure.setLocation(linkBuffer.locationOf(m_methodGets[i].m_protoStructToCompare)); 367 info.cachedFunction.setLocation(linkBuffer.locationOf(m_methodGets[i].m_putFunction)); 368 info.cachedPrototype.setLocation(linkBuffer.locationOf(m_methodGets[i].m_protoObj)); 369 info.callReturnLocation = linkBuffer.locationOf(m_methodGets[i].m_slowCall); 370 } 371 } 372 373 void JITCompiler::compile(JITCode& entry) 374 { 375 // Preserve the return address to the callframe. 376 compileEntry(); 377 // Generate the body of the program. 378 compileBody(); 379 // Link 380 LinkBuffer linkBuffer(*m_globalData, this, m_globalData->executableAllocator); 381 link(linkBuffer); 382 entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT); 383 } 384 385 void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck) 386 { 387 compileEntry(); 388 389 // === Function header code generation === 390 // This is the main entry point, without performing an arity check. 391 // If we needed to perform an arity check we will already have moved the return address, 392 // so enter after this. 393 Label fromArityCheck(this); 394 // Setup a pointer to the codeblock in the CallFrameHeader. 395 emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock); 396 // Plant a check that sufficient space is available in the RegisterFile. 397 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291 398 addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1); 399 Jump registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), GPRInfo::regT1); 400 // Return here after register file check. 401 Label fromRegisterFileCheck = label(); 402 403 404 // === Function body code generation === 405 compileBody(); 406 407 // === Function footer code generation === 408 // 409 // Generate code to perform the slow register file check (if the fast one in 410 // the function header fails), and generate the entry point with arity check. 411 // 338 412 // Generate the register file check; if the fast check in the function head fails, 339 413 // we need to call out to a helper function to check whether more space is available. … … 344 418 Call callRegisterFileCheck = call(); 345 419 jump(fromRegisterFileCheck); 346 420 347 421 // The fast entry point into a function does not check the correct number of arguments 348 422 // have been passed to the call (we only use the fast entry point where we can statically … … 361 435 362 436 363 // === Stage 4 - Link === 364 // 365 // Link the code, populate data in CodeBlock data structures. 366 437 // === Link === 367 438 LinkBuffer linkBuffer(*m_globalData, this, m_globalData->executableAllocator); 368 369 #if DFG_DEBUG_VERBOSE 370 fprintf(stderr, "JIT code start at %p\n", linkBuffer.debugAddress()); 371 #endif 372 373 // Link all calls out from the JIT code to their respective functions. 374 for (unsigned i = 0; i < m_calls.size(); ++i) { 375 if (m_calls[i].m_function.value()) 376 linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function); 377 } 378 379 if (m_codeBlock->needsCallReturnIndices()) { 380 m_codeBlock->callReturnIndexVector().reserveCapacity(exceptionCheckCount); 381 for (unsigned i = 0; i < m_calls.size(); ++i) { 382 if (m_calls[i].m_handlesExceptions) { 383 unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_calls[i].m_call); 384 unsigned exceptionInfo = m_calls[i].m_exceptionInfo; 385 m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo)); 386 } 387 } 388 } 389 390 m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccesses.size()); 391 for (unsigned i = 0; i < m_propertyAccesses.size(); ++i) { 392 StructureStubInfo& info = m_codeBlock->structureStubInfo(i); 393 info.callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall); 394 info.u.unset.deltaCheckImmToCall = m_propertyAccesses[i].m_deltaCheckImmToCall; 395 info.deltaCallToStructCheck = m_propertyAccesses[i].m_deltaCallToStructCheck; 396 info.u.unset.deltaCallToLoadOrStore = m_propertyAccesses[i].m_deltaCallToLoadOrStore; 397 info.deltaCallToSlowCase = m_propertyAccesses[i].m_deltaCallToSlowCase; 398 info.deltaCallToDone = m_propertyAccesses[i].m_deltaCallToDone; 399 info.baseGPR = m_propertyAccesses[i].m_baseGPR; 400 info.valueGPR = m_propertyAccesses[i].m_valueGPR; 401 info.scratchGPR = m_propertyAccesses[i].m_scratchGPR; 402 } 403 404 m_codeBlock->setNumberOfCallLinkInfos(m_jsCalls.size()); 405 for (unsigned i = 0; i < m_jsCalls.size(); ++i) { 406 CallLinkInfo& info = m_codeBlock->callLinkInfo(i); 407 info.isCall = m_jsCalls[i].m_isCall; 408 info.callReturnLocation = CodeLocationLabel(linkBuffer.locationOf(m_jsCalls[i].m_slowCall)); 409 info.hotPathBegin = linkBuffer.locationOf(m_jsCalls[i].m_targetToCheck); 410 info.hotPathOther = linkBuffer.locationOfNearCall(m_jsCalls[i].m_fastCall); 411 } 412 413 m_codeBlock->addMethodCallLinkInfos(m_methodGets.size()); 414 for (unsigned i = 0; i < m_methodGets.size(); ++i) { 415 MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i); 416 info.cachedStructure.setLocation(linkBuffer.locationOf(m_methodGets[i].m_structToCompare)); 417 info.cachedPrototypeStructure.setLocation(linkBuffer.locationOf(m_methodGets[i].m_protoStructToCompare)); 418 info.cachedFunction.setLocation(linkBuffer.locationOf(m_methodGets[i].m_putFunction)); 419 info.cachedPrototype.setLocation(linkBuffer.locationOf(m_methodGets[i].m_protoObj)); 420 info.callReturnLocation = linkBuffer.locationOf(m_methodGets[i].m_slowCall); 421 } 439 link(linkBuffer); 422 440 423 441 // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs. -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h
r90529 r91225 111 111 , m_graph(dfg) 112 112 , m_codeBlock(codeBlock) 113 { 114 } 115 113 , m_exceptionCheckCount(0) 114 { 115 } 116 117 void compile(JITCode& entry); 116 118 void compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck); 117 119 … … 280 282 281 283 private: 284 // Internal implementation to compile. 285 void compileEntry(); 286 void compileBody(); 287 void link(LinkBuffer&); 288 282 289 // These methods used in linking the speculative & non-speculative paths together. 283 290 void fillNumericToDouble(NodeIndex, FPRReg, GPRReg temporary); … … 297 304 298 305 // Vector of calls out from JIT code, including exception handler information. 306 // Count of the number of CallRecords with exception handlers. 299 307 Vector<CallRecord> m_calls; 308 unsigned m_exceptionCheckCount; 300 309 301 310 struct PropertyAccessRecord { -
trunk/Source/JavaScriptCore/runtime/Executable.cpp
r91194 r91225 44 44 45 45 #if ENABLE(JIT) 46 #if ENABLE(DFG_JIT) 47 static bool tryDFGCompile(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode) 48 { 49 #if ENABLE(DFG_JIT_RESTRICTIONS) 50 // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets. 51 if (codeBlock->numberOfJumpTargets()) 52 return false; 53 #endif 54 55 JSGlobalData* globalData = &exec->globalData(); 56 DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars); 57 if (!parse(dfg, globalData, codeBlock)) 58 return false; 59 60 dfg.predictArgumentTypes(exec); 61 62 DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock); 63 dataFlowJIT.compile(jitCode); 64 return true; 65 } 66 67 static bool tryDFGCompileFunction(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck) 68 { 69 #if ENABLE(DFG_JIT_RESTRICTIONS) 70 // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets. 71 if (codeBlock->numberOfJumpTargets()) 72 return false; 73 #endif 74 75 JSGlobalData* globalData = &exec->globalData(); 76 DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars); 77 if (!parse(dfg, globalData, codeBlock)) 78 return false; 79 80 dfg.predictArgumentTypes(exec); 81 82 DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock); 83 dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck); 84 return true; 85 } 86 #else 87 static bool tryDFGCompile(ExecState*, CodeBlock*, JITCode&) { return false; } 88 static bool tryDFGCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr&) { return false; } 89 #endif 90 46 91 class ExecutableFinalizer : public WeakHandleOwner { 47 92 virtual void finalize(Handle<Unknown> handle, void*) … … 227 272 #if ENABLE(JIT) 228 273 if (exec->globalData().canUseJIT()) { 229 m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock.get()); 274 bool dfgCompiled = tryDFGCompile(exec, m_programCodeBlock.get(), m_jitCodeForCall); 275 if (!dfgCompiled) 276 m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock.get()); 230 277 #if !ENABLE(OPCODE_SAMPLING) 231 278 if (!BytecodeGenerator::dumpsGeneratedCode()) … … 258 305 #endif 259 306 } 260 261 #if ENABLE(JIT)262 static bool tryDFGCompile(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)263 {264 JSGlobalData* globalData = &exec->globalData();265 #if ENABLE(DFG_JIT)266 #if ENABLE(DFG_JIT_RESTRICTIONS)267 // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets.268 if (codeBlock->numberOfJumpTargets())269 return false;270 #endif271 272 DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars);273 if (!parse(dfg, globalData, codeBlock))274 return false;275 276 dfg.predictArgumentTypes(exec);277 278 DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock);279 dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck);280 return true;281 #else282 UNUSED_PARAM(globalData);283 UNUSED_PARAM(codeBlock);284 UNUSED_PARAM(jitCode);285 UNUSED_PARAM(jitCodeWithArityCheck);286 return false;287 #endif288 }289 #endif290 307 291 308 void ProgramExecutable::visitChildren(SlotVisitor& visitor) … … 333 350 #if ENABLE(JIT) 334 351 if (exec->globalData().canUseJIT()) { 335 bool dfgCompiled = tryDFGCompile (exec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck);352 bool dfgCompiled = tryDFGCompileFunction(exec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck); 336 353 if (!dfgCompiled) 337 354 m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck);
Note: See TracChangeset
for help on using the changeset viewer.