Changeset 95672 in webkit
- Timestamp:
- Sep 21, 2011 3:17:06 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r95666 r95672 1 2011-09-21 Filip Pizlo <fpizlo@apple.com> 2 3 DFG does not support compiling functions as constructors 4 https://bugs.webkit.org/show_bug.cgi?id=68500 5 6 Reviewed by Oliver Hunt. 7 8 This adds support for compiling constructors to the DFG. It's a 9 1% speed-up on V8, mostly due to a 6% speed-up on early-boyer. 10 It's also a 13% win on access-binary-trees, but it's neutral in 11 the SunSpider and Kraken averages. 12 13 * dfg/DFGByteCodeParser.cpp: 14 (JSC::DFG::ByteCodeParser::parseBlock): 15 * dfg/DFGCapabilities.h: 16 (JSC::DFG::mightCompileFunctionForConstruct): 17 (JSC::DFG::canCompileOpcode): 18 * dfg/DFGNode.h: 19 * dfg/DFGOperations.cpp: 20 * dfg/DFGOperations.h: 21 * dfg/DFGPropagator.cpp: 22 (JSC::DFG::Propagator::propagateNodePredictions): 23 (JSC::DFG::Propagator::performNodeCSE): 24 * dfg/DFGSpeculativeJIT.cpp: 25 (JSC::DFG::SpeculativeJIT::compile): 26 * runtime/Executable.cpp: 27 (JSC::FunctionExecutable::compileOptimizedForConstruct): 28 (JSC::FunctionExecutable::compileForConstructInternal): 29 * runtime/Executable.h: 30 (JSC::FunctionExecutable::compileForConstruct): 31 (JSC::FunctionExecutable::compileFor): 32 (JSC::FunctionExecutable::compileOptimizedFor): 33 1 34 2011-09-21 Gavin Barraclough <barraclough@apple.com> 2 35 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r95666 r95672 729 729 setThis(addToGraph(ConvertThis, op1)); 730 730 NEXT_OPCODE(op_convert_this); 731 } 732 733 case op_create_this: { 734 NodeIndex op1 = get(currentInstruction[2].u.operand); 735 set(currentInstruction[1].u.operand, addToGraph(CreateThis, op1)); 736 NEXT_OPCODE(op_create_this); 737 } 738 739 case op_get_callee: { 740 set(currentInstruction[1].u.operand, addToGraph(GetCallee)); 741 NEXT_OPCODE(op_get_callee); 731 742 } 732 743 -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.h
r95016 r95672 38 38 inline bool mightCompileProgram(CodeBlock*) { return true; } 39 39 inline bool mightCompileFunctionForCall(CodeBlock*) { return true; } 40 inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }40 inline bool mightCompileFunctionForConstruct(CodeBlock*) { return true; } 41 41 42 42 // Opcode checking. … … 46 46 case op_enter: 47 47 case op_convert_this: 48 case op_create_this: 49 case op_get_callee: 48 50 case op_bitand: 49 51 case op_bitor: -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r95594 r95672 212 212 /* Nodes for constants. */\ 213 213 macro(JSConstant, NodeResultJS) \ 214 \ 215 /* Nodes for handling functions (both as call and as construct). */\ 214 216 macro(ConvertThis, NodeResultJS) \ 217 macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \ 218 macro(GetCallee, NodeResultJS) \ 215 219 \ 216 220 /* Nodes for local variable access. */\ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r95666 r95672 120 120 } 121 121 122 EncodedJSValue operationCreateThis(ExecState* exec, EncodedJSValue encodedOp) 123 { 124 JSFunction* constructor = asFunction(exec->callee()); 125 126 #if !ASSERT_DISABLED 127 ConstructData constructData; 128 ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS); 129 #endif 130 131 JSGlobalData& globalData = exec->globalData(); 132 133 Structure* structure; 134 JSValue proto = JSValue::decode(encodedOp); 135 if (proto.isObject()) 136 structure = asObject(proto)->inheritorID(globalData); 137 else 138 structure = constructor->scope()->globalObject->emptyObjectStructure(); 139 140 return JSValue::encode(constructEmptyObject(exec, structure)); 141 } 142 122 143 EncodedJSValue operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 123 144 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r95147 r95672 57 57 // These routines are provide callbacks out to C++ implementations of operations too complex to JIT. 58 58 EncodedJSValue operationConvertThis(ExecState*, EncodedJSValue encodedOp1); 59 EncodedJSValue operationCreateThis(ExecState*, EncodedJSValue encodedOp1); 59 60 EncodedJSValue operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2); 60 61 EncodedJSValue operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2); -
trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp
r95594 r95672 534 534 break; 535 535 } 536 537 case GetCallee: { 538 changed |= setPrediction(makePrediction(PredictObjectOther, StrongPrediction)); 539 break; 540 } 541 542 case CreateThis: { 543 changed |= mergeUse(node.child1(), PredictObjectUnknown | StrongPredictionTag); 544 changed |= setPrediction(makePrediction(PredictFinalObject, StrongPrediction)); 545 break; 546 } 536 547 537 548 #ifndef NDEBUG … … 1019 1030 case ArithMax: 1020 1031 case ArithSqrt: 1032 case GetCallee: 1021 1033 setReplacement(pureCSE(node)); 1022 1034 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r95594 r95672 1528 1528 break; 1529 1529 } 1530 1531 case CreateThis: { 1532 // Note that there is not so much profit to speculate here. The only things we 1533 // speculate on are (1) that it's a cell, since that eliminates cell checks 1534 // later if the proto is reused, and (2) if we have a FinalObject prediction 1535 // then we speculate because we want to get recompiled if it isn't (since 1536 // otherwise we'd start taking slow path a lot). 1537 1538 SpeculateCellOperand proto(this, node.child1()); 1539 GPRTemporary result(this); 1540 GPRTemporary scratch(this); 1541 1542 GPRReg protoGPR = proto.gpr(); 1543 GPRReg resultGPR = result.gpr(); 1544 GPRReg scratchGPR = scratch.gpr(); 1545 1546 proto.use(); 1547 1548 MacroAssembler::JumpList slowPath; 1549 1550 // Need to verify that the prototype is an object. If we have reason to believe 1551 // that it's a FinalObject then we speculate on that directly. Otherwise we 1552 // do the slow (structure-based) check. 1553 if (shouldSpeculateFinalObject(node.child1())) 1554 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr))); 1555 else { 1556 m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR); 1557 slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType))); 1558 } 1559 1560 // Load the inheritorID (the Structure that objects who have protoGPR as the prototype 1561 // use to refer to that prototype). If the inheritorID is not set, go to slow path. 1562 m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR); 1563 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR)); 1564 1565 MarkedSpace::SizeClass* sizeClass = &m_jit.globalData()->heap.sizeClassForObject(sizeof(JSFinalObject)); 1566 1567 m_jit.loadPtr(&sizeClass->firstFreeCell, resultGPR); 1568 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR)); 1569 1570 // The object is half-allocated: we have what we know is a fresh object, but 1571 // it's still on the GC's free list. 1572 1573 // Ditch the inheritorID by placing it into the structure, so that we can reuse 1574 // scratchGPR. 1575 m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSObject::structureOffset())); 1576 1577 // Now that we have scratchGPR back, remove the object from the free list 1578 m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR); 1579 m_jit.storePtr(scratchGPR, &sizeClass->firstFreeCell); 1580 1581 // Initialize the object's vtable 1582 m_jit.storePtr(MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr), MacroAssembler::Address(resultGPR)); 1583 1584 // Initialize the object's inheritorID. 1585 m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID())); 1586 1587 // Initialize the object's property storage pointer. 1588 m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR); 1589 m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSFinalObject::offsetOfPropertyStorage())); 1590 1591 MacroAssembler::Jump done = m_jit.jump(); 1592 1593 slowPath.link(&m_jit); 1594 1595 silentSpillAllRegisters(resultGPR); 1596 m_jit.move(protoGPR, GPRInfo::argumentGPR1); 1597 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1598 appendCallWithExceptionCheck(operationCreateThis); 1599 m_jit.move(GPRInfo::returnValueGPR, resultGPR); 1600 silentFillAllRegisters(resultGPR); 1601 1602 done.link(&m_jit); 1603 1604 cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly); 1605 break; 1606 } 1607 1608 case GetCallee: { 1609 GPRTemporary result(this); 1610 m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::Callee)), result.gpr()); 1611 cellResult(result.gpr(), m_compileIndex); 1612 break; 1613 } 1530 1614 1531 1615 case GetById: { -
trunk/Source/JavaScriptCore/runtime/Executable.cpp
r95310 r95672 371 371 } 372 372 373 JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode )373 JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode, ExecState* calleeArgsExec) 374 374 { 375 375 ASSERT(exec->globalData().dynamicGlobalObject); … … 377 377 JSObject* error = 0; 378 378 if (m_codeBlockForConstruct->getJITType() != JITCode::topTierJIT()) 379 error = compileForConstructInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_codeBlockForConstruct->getJITType()));379 error = compileForConstructInternal(exec, scopeChainNode, calleeArgsExec, JITCode::nextTierJIT(m_codeBlockForConstruct->getJITType())); 380 380 ASSERT(!!m_codeBlockForConstruct); 381 381 return error; … … 460 460 } 461 461 462 JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)462 JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, ExecState* calleeArgsExec, JITCode::JITType jitType) 463 463 { 464 464 UNUSED_PARAM(jitType); … … 499 499 if (exec->globalData().canUseJIT()) { 500 500 bool dfgCompiled = false; 501 // FIXME: Make it possible to compile constructors with DFG. 501 if (jitType == JITCode::DFGJIT) 502 dfgCompiled = DFG::tryCompileFunction(exec, calleeArgsExec, m_codeBlockForConstruct.get(), m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck); 502 503 if (dfgCompiled) { 503 504 if (m_codeBlockForConstruct->alternative()) -
trunk/Source/JavaScriptCore/runtime/Executable.h
r95666 r95672 488 488 } 489 489 490 JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode )490 JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode, ExecState* calleeArgsExec = 0) 491 491 { 492 492 ASSERT(exec->globalData().dynamicGlobalObject); 493 493 JSObject* error = 0; 494 494 if (!m_codeBlockForConstruct) 495 error = compileForConstructInternal(exec, scopeChainNode, JITCode::bottomTierJIT());495 error = compileForConstructInternal(exec, scopeChainNode, calleeArgsExec, JITCode::bottomTierJIT()); 496 496 ASSERT(!error == !!m_codeBlockForConstruct); 497 497 return error; 498 498 } 499 499 500 JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode* );500 JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec = 0); 501 501 502 502 bool isGeneratedForConstruct() const … … 522 522 return compileForCall(exec, scopeChainNode, exec); 523 523 ASSERT(kind == CodeForConstruct); 524 return compileForConstruct(exec, scopeChainNode );524 return compileForConstruct(exec, scopeChainNode, exec); 525 525 } 526 526 … … 536 536 return compileOptimizedForCall(exec, scopeChainNode, exec); 537 537 ASSERT(kind == CodeForConstruct); 538 return compileOptimizedForConstruct(exec, scopeChainNode );538 return compileOptimizedForConstruct(exec, scopeChainNode, exec); 539 539 } 540 540 … … 588 588 589 589 JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec, JITCode::JITType); 590 JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, JITCode::JITType);590 JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec, JITCode::JITType); 591 591 592 592 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
Note: See TracChangeset
for help on using the changeset viewer.