Changeset 90877 in webkit
- Timestamp:
- Jul 12, 2011 6:46:09 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r90876 r90877 1 2011-07-12 Filip Pizlo <fpizlo@apple.com> 2 3 DFG JIT does not implement op_construct. 4 https://bugs.webkit.org/show_bug.cgi?id=64066 5 6 Reviewed by Gavin Barraclough. 7 8 Added a test for the DFG op_construct regression, where polymorphic constructor 9 calls will result in the code being compiled for call but then invoked as a 10 constructor. This test will fail if that part of the patch is omitted. 11 12 * fast/js/polymorphic-construct-expected.txt: Added. 13 * fast/js/polymorphic-construct.html: Added. 14 * fast/js/script-tests/polymorphic-construct.js: Added. 15 (Foo): 16 (): 17 1 18 2011-07-12 Chris Rogers <crogers@google.com> 2 19 -
trunk/Source/JavaScriptCore/ChangeLog
r90875 r90877 1 2011-07-12 Filip Pizlo <fpizlo@apple.com> 2 3 DFG JIT does not implement op_construct. 4 https://bugs.webkit.org/show_bug.cgi?id=64066 5 6 Reviewed by Gavin Barraclough. 7 8 This is a fixed implementation of op_construct. Constructor calls are implemented 9 by reusing almost all of the code for Call, with care taken to make sure that 10 where the are differences (like selecting different code blocks), those differences 11 are respected. The two fixes over the last patch are: (1) make sure the 12 CodeBlock::unlinkCalls respects differences between Call and Construct, and (2) 13 make sure that virtualFor() in DFGOperations respects the CodeSpecializationKind 14 (either CodeForCall or CodeForConstruct) when invoking the compiler. 15 16 * dfg/DFGAliasTracker.h: 17 (JSC::DFG::AliasTracker::recordConstruct): 18 * dfg/DFGByteCodeParser.cpp: 19 (JSC::DFG::ByteCodeParser::addCall): 20 (JSC::DFG::ByteCodeParser::parseBlock): 21 * dfg/DFGJITCodeGenerator.cpp: 22 (JSC::DFG::JITCodeGenerator::emitCall): 23 * dfg/DFGNode.h: 24 * dfg/DFGNonSpeculativeJIT.cpp: 25 (JSC::DFG::NonSpeculativeJIT::compile): 26 * dfg/DFGOperations.cpp: 27 * dfg/DFGOperations.h: 28 * dfg/DFGRepatch.cpp: 29 (JSC::DFG::dfgLinkFor): 30 * dfg/DFGRepatch.h: 31 * dfg/DFGSpeculativeJIT.cpp: 32 (JSC::DFG::SpeculativeJIT::compile): 33 * runtime/CodeBlock.cpp: 34 (JSC::CodeBlock::unlinkCalls): 35 1 36 2011-07-12 Oliver Hunt <oliver@apple.com> 2 37 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r90529 r90877 1752 1752 if (getJITCode().jitType() == JITCode::DFGJIT) { 1753 1753 #if ENABLE(DFG_JIT) 1754 repatchBuffer.relink(CodeLocationCall(m_callLinkInfos[i].callReturnLocation), operationLinkCall);1754 repatchBuffer.relink(CodeLocationCall(m_callLinkInfos[i].callReturnLocation), m_callLinkInfos[i].isCall ? operationLinkCall : operationLinkConstruct); 1755 1755 #else 1756 1756 ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/dfg/DFGAliasTracker.h
r90673 r90877 108 108 } 109 109 110 void recordConstruct(NodeIndex construct) 111 { 112 ASSERT_UNUSED(construct, m_graph[construct].op == Construct); 113 m_candidateAliasGetByVal = NoNode; 114 } 115 110 116 private: 111 117 // This method returns true for arguments: -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r90673 r90877 411 411 m_graph.m_varArgChildren.append(child); 412 412 m_numPassedVarArgs++; 413 } 414 415 NodeIndex addCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op) 416 { 417 addVarArgChild(get(currentInstruction[1].u.operand)); 418 int argCount = currentInstruction[2].u.operand; 419 int registerOffset = currentInstruction[3].u.operand; 420 int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize; 421 for (int argIdx = firstArg; argIdx < firstArg + argCount; argIdx++) 422 addVarArgChild(get(argIdx)); 423 NodeIndex call = addToGraph(Node::VarArg, op); 424 Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call); 425 if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) 426 set(putInstruction[1].u.operand, call); 427 if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots) 428 m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount; 429 return call; 413 430 } 414 431 … … 1102 1119 1103 1120 case op_call: { 1104 addVarArgChild(get(currentInstruction[1].u.operand)); 1105 int argCount = currentInstruction[2].u.operand; 1106 int registerOffset = currentInstruction[3].u.operand; 1107 int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize; 1108 for (int argIdx = firstArg; argIdx < firstArg + argCount; argIdx++) 1109 addVarArgChild(get(argIdx)); 1110 NodeIndex call = addToGraph(Node::VarArg, Call); 1121 NodeIndex call = addCall(interpreter, currentInstruction, Call); 1111 1122 aliases.recordCall(call); 1112 Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);1113 if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)1114 set(putInstruction[1].u.operand, call);1115 if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)1116 m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;1117 1123 NEXT_OPCODE(op_call); 1124 } 1125 1126 case op_construct: { 1127 NodeIndex construct = addCall(interpreter, currentInstruction, Construct); 1128 aliases.recordConstruct(construct); 1129 NEXT_OPCODE(op_construct); 1118 1130 } 1119 1131 1120 1132 case op_call_put_result: { 1121 #if !ASSERT_DISABLED1122 Instruction* callInstruction = currentInstruction - OPCODE_LENGTH(op_call);1123 ASSERT(interpreter->getOpcodeID(callInstruction->u.opcode) == op_call);1124 #endif1125 1133 NEXT_OPCODE(op_call_put_result); 1126 1134 } -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r90673 r90877 471 471 void JITCodeGenerator::emitCall(Node& node) 472 472 { 473 P_DFGOperation_E slowCallFunction; 474 bool isCall; 475 476 if (node.op == Call) { 477 slowCallFunction = operationLinkCall; 478 isCall = true; 479 } else { 480 ASSERT(node.op == Construct); 481 slowCallFunction = operationLinkConstruct; 482 isCall = false; 483 } 484 473 485 NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()]; 474 486 JSValueOperand callee(this, calleeNodeIndex); … … 502 514 } 503 515 504 switch (node.op) { 505 case Call: 506 m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee)); 507 break; 508 509 default: 510 ASSERT_NOT_REACHED(); 511 } 516 m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee)); 512 517 513 518 flushRegisters(); … … 519 524 JITCompiler::Jump slowPath; 520 525 521 switch (node.op) { 522 case Call: 523 slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue()))); 524 m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR); 525 m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain)); 526 break; 527 528 default: 529 ASSERT_NOT_REACHED(); 530 } 526 slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue()))); 527 m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR); 528 m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain)); 531 529 532 530 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); … … 540 538 541 539 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 542 JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck( operationLinkCall, m_jit.graph()[m_compileIndex].exceptionInfo);540 JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck(slowCallFunction, m_jit.graph()[m_compileIndex].exceptionInfo); 543 541 m_jit.move(Imm32(numArgs), GPRInfo::regT1); 544 542 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); … … 551 549 jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly); 552 550 553 m_jit.addJSCall(fastCall, slowCall, targetToCheck, true, m_jit.graph()[m_compileIndex].exceptionInfo);551 m_jit.addJSCall(fastCall, slowCall, targetToCheck, isCall, m_jit.graph()[m_compileIndex].exceptionInfo); 554 552 } 555 553 -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r90673 r90877 143 143 /* Calls. */\ 144 144 macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \ 145 macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \ 145 146 \ 146 147 /* Nodes for misc operations. */\ -
trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
r90673 r90877 1069 1069 1070 1070 case Call: 1071 case Construct: 1071 1072 emitCall(node); 1072 1073 break; -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r90673 r90877 432 432 } 433 433 434 static void* handleHostCall(ExecState* execCallee, JSValue callee )434 static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind) 435 435 { 436 436 ExecState* exec = execCallee->callerFrame(); 437 437 JSGlobalData* globalData = &exec->globalData(); 438 CallData callData; 439 CallType callType = getCallData(callee, callData); 440 441 ASSERT(callType != CallTypeJS); 442 443 if (callType == CallTypeHost) { 444 if (!globalData->interpreter->registerFile().grow(execCallee->registers())) { 445 globalData->exception = createStackOverflowError(exec); 446 return 0; 447 } 438 if (kind == CodeForCall) { 439 CallData callData; 440 CallType callType = getCallData(callee, callData); 441 442 ASSERT(callType != CallTypeJS); 443 444 if (callType == CallTypeHost) { 445 if (!globalData->interpreter->registerFile().grow(execCallee->registers())) { 446 globalData->exception = createStackOverflowError(exec); 447 return 0; 448 } 448 449 449 execCallee->setScopeChain(exec->scopeChain());450 execCallee->setScopeChain(exec->scopeChain()); 450 451 451 globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));452 globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee)); 452 453 453 if (globalData->exception) 454 return 0; 455 return reinterpret_cast<void*>(getHostCallReturnValue); 456 } 457 458 ASSERT(callType == CallTypeNone); 454 if (globalData->exception) 455 return 0; 456 return reinterpret_cast<void*>(getHostCallReturnValue); 457 } 458 459 ASSERT(callType == CallTypeNone); 460 } else { 461 ASSERT(kind == CodeForConstruct); 462 463 ConstructData constructData; 464 ConstructType constructType = getConstructData(callee, constructData); 465 466 ASSERT(constructType = ConstructTypeJS); 467 468 if (constructType == ConstructTypeHost) { 469 if (!globalData->interpreter->registerFile().grow(execCallee->registers())) { 470 globalData->exception = createStackOverflowError(exec); 471 return 0; 472 } 473 474 execCallee->setScopeChain(exec->scopeChain()); 475 476 globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee)); 477 478 if (globalData->exception) 479 return 0; 480 return reinterpret_cast<void*>(getHostCallReturnValue); 481 } 482 483 ASSERT(constructType == ConstructTypeNone); 484 } 459 485 exec->globalData().exception = createNotAFunctionError(exec, callee); 460 486 return 0; 461 487 } 462 488 463 void* operationLinkCallWithReturnAddress(ExecState*, ReturnAddressPtr); 464 FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkCall); 465 void* operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress) 489 inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind) 466 490 { 467 491 ExecState* exec = execCallee->callerFrame(); … … 470 494 JSCell* calleeAsFunctionCell = getJSFunction(*globalData, calleeAsValue); 471 495 if (!calleeAsFunctionCell) 472 return handleHostCall(execCallee, calleeAsValue );496 return handleHostCall(execCallee, calleeAsValue, kind); 473 497 JSFunction* callee = asFunction(calleeAsFunctionCell); 474 498 ExecutableBase* executable = callee->executable(); … … 477 501 CodeBlock* codeBlock = 0; 478 502 if (executable->isHostFunction()) 479 codePtr = executable->generatedJITCodeFor Call().addressForCall();503 codePtr = executable->generatedJITCodeFor(kind).addressForCall(); 480 504 else { 481 505 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 482 JSObject* error = functionExecutable->compileFor Call(exec, callee->scope());506 JSObject* error = functionExecutable->compileFor(exec, callee->scope(), kind); 483 507 if (error) { 484 508 globalData->exception = createStackOverflowError(exec); 485 509 return 0; 486 510 } 487 codeBlock = &functionExecutable->generatedBytecodeFor Call();511 codeBlock = &functionExecutable->generatedBytecodeFor(kind); 488 512 if (execCallee->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters)) 489 codePtr = functionExecutable->generatedJITCodeFor Call().addressForCall();513 codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall(); 490 514 else 491 codePtr = functionExecutable->generatedJITCode ForCallWithArityCheck();515 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind); 492 516 execCallee->setScopeChain(callee->scope()); 493 517 } … … 496 520 callLinkInfo.setSeen(); 497 521 else 498 dfgLink Call(execCallee, callLinkInfo, codeBlock, callee, codePtr);522 dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind); 499 523 return codePtr.executableAddress(); 500 524 } 501 525 502 void* operationVirtualCall(ExecState* execCallee) 526 void* operationLinkCallWithReturnAddress(ExecState*, ReturnAddressPtr); 527 FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkCall); 528 void* operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress) 529 { 530 return linkFor(execCallee, returnAddress, CodeForCall); 531 } 532 533 void* operationLinkConstructWithReturnAddress(ExecState*, ReturnAddressPtr); 534 FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkConstruct); 535 void* operationLinkConstructWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress) 536 { 537 return linkFor(execCallee, returnAddress, CodeForConstruct); 538 } 539 540 inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind) 503 541 { 504 542 ExecState* exec = execCallee->callerFrame(); … … 507 545 JSCell* calleeAsFunctionCell = getJSFunction(*globalData, calleeAsValue); 508 546 if (UNLIKELY(!calleeAsFunctionCell)) 509 return handleHostCall(execCallee, calleeAsValue );547 return handleHostCall(execCallee, calleeAsValue, kind); 510 548 511 549 JSFunction* function = asFunction(calleeAsFunctionCell); 512 550 ExecutableBase* executable = function->executable(); 513 if (UNLIKELY(!executable->hasJITCodeFor Call())) {551 if (UNLIKELY(!executable->hasJITCodeFor(kind))) { 514 552 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 515 JSObject* error = functionExecutable->compileFor Call(exec, function->scope());553 JSObject* error = functionExecutable->compileFor(exec, function->scope(), kind); 516 554 if (error) { 517 555 exec->globalData().exception = error; … … 520 558 } 521 559 execCallee->setScopeChain(function->scopeUnchecked()); 522 return executable->generatedJITCodeForCallWithArityCheck().executableAddress(); 560 return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress(); 561 } 562 563 void* operationVirtualCall(ExecState* execCallee) 564 { 565 return virtualFor(execCallee, CodeForCall); 566 } 567 568 void* operationVirtualConstruct(ExecState* execCallee) 569 { 570 return virtualFor(execCallee, CodeForConstruct); 523 571 } 524 572 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r90673 r90877 49 49 typedef void (*V_DFGOperation_EJJI)(ExecState*, EncodedJSValue, EncodedJSValue, Identifier*); 50 50 typedef double (*D_DFGOperation_DD)(double, double); 51 typedef void *(*P_DFGOperation_E)(ExecState*); 51 52 52 53 // These routines are provide callbacks out to C++ implementations of operations too complex to JIT. … … 84 85 void* operationVirtualCall(ExecState*); 85 86 void* operationLinkCall(ExecState*); 87 void* operationVirtualConstruct(ExecState*); 88 void* operationLinkConstruct(ExecState*); 86 89 87 90 // This method is used to lookup an exception hander, keyed by faultLocation, which is -
trunk/Source/JavaScriptCore/dfg/DFGRepatch.cpp
r90875 r90877 435 435 } 436 436 437 void dfgLink Call(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock, JSFunction* callee, MacroAssemblerCodePtr codePtr)437 void dfgLinkFor(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock, JSFunction* callee, MacroAssemblerCodePtr codePtr, CodeSpecializationKind kind) 438 438 { 439 439 CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock(); … … 447 447 } 448 448 449 repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualCall); 449 if (kind == CodeForCall) { 450 repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualCall); 451 return; 452 } 453 ASSERT(kind == CodeForConstruct); 454 repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualConstruct); 450 455 } 451 456 -
trunk/Source/JavaScriptCore/dfg/DFGRepatch.h
r90673 r90877 38 38 void dfgBuildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&); 39 39 void dfgRepatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind); 40 void dfgLink Call(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr);40 void dfgLinkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind); 41 41 42 42 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r90799 r90877 1144 1144 1145 1145 case Call: 1146 case Construct: 1146 1147 emitCall(node); 1147 1148 break;
Note: See TracChangeset
for help on using the changeset viewer.