Changeset 254480 in webkit
- Timestamp:
- Jan 13, 2020, 5:43:03 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 25 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/stress/dfg-compare-eq-via-nonSpeculativeNonPeepholeCompareNullOrUndefined.js (modified) (1 diff)
-
JSTests/stress/getter-setter-inlining-should-emit-movhint.js (modified) (1 diff)
-
JSTests/stress/make-dictionary-repatch.js (modified) (1 diff)
-
JSTests/stress/merging-ic-variants-should-bail-if-structures-overlap.js (modified) (1 diff)
-
JSTests/stress/proxy-getter-stack-overflow.js (modified) (1 diff)
-
JSTests/stress/regress-192717.js (modified) (1 diff)
-
JSTests/stress/retry-cache-later.js (modified) (1 diff)
-
Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp (modified) (1 diff)
-
Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/CodeBlock.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/bytecode/CodeBlock.h (modified) (5 diffs)
-
Source/JavaScriptCore/dfg/DFGDriver.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h (modified) (1 diff)
-
Source/JavaScriptCore/heap/CodeBlockSet.cpp (modified) (1 diff)
-
Source/JavaScriptCore/heap/CodeBlockSet.h (modified) (1 diff)
-
Source/JavaScriptCore/heap/Heap.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/Options.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/runtime/OptionsList.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/ScriptExecutable.cpp (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/Scripts/run-jsc-stress-tests (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r254464 r254480 1 2020-01-13 Saam Barati <sbarati@apple.com> 2 3 Throw away baseline code if there is an optimized replacement 4 https://bugs.webkit.org/show_bug.cgi?id=202503 5 6 Reviewed by Yusuke Suzuki. 7 8 * stress/dfg-compare-eq-via-nonSpeculativeNonPeepholeCompareNullOrUndefined.js: 9 * stress/getter-setter-inlining-should-emit-movhint.js: 10 * stress/make-dictionary-repatch.js: 11 * stress/merging-ic-variants-should-bail-if-structures-overlap.js: 12 * stress/proxy-getter-stack-overflow.js: 13 * stress/regress-192717.js: 14 * stress/retry-cache-later.js: 15 1 16 2020-01-13 Mark Lam <mark.lam@apple.com> 2 17 -
trunk/JSTests/stress/dfg-compare-eq-via-nonSpeculativeNonPeepholeCompareNullOrUndefined.js
r249075 r254480 1 //@ runDefault("--collectContinuously=true", "--collectContinuouslyPeriodMS=0.15", "-- useLLInt=false", "--useFTLJIT=false", "--jitPolicyScale=0")1 //@ runDefault("--collectContinuously=true", "--collectContinuouslyPeriodMS=0.15", "--forceBaseline=true", "--useFTLJIT=false", "--jitPolicyScale=0") 2 2 3 3 // This test exercises DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(). -
trunk/JSTests/stress/getter-setter-inlining-should-emit-movhint.js
r244864 r254480 1 //@ runDefault("--useRandomizingFuzzerAgent=1", "--usePolymorphicCallInliningForNonStubStatus=1", "--seedOfRandomizingFuzzerAgent=2896922505", "-- useLLInt=0", "--useConcurrentJIT=0")1 //@ runDefault("--useRandomizingFuzzerAgent=1", "--usePolymorphicCallInliningForNonStubStatus=1", "--seedOfRandomizingFuzzerAgent=2896922505", "--forceBaseline=1", "--useConcurrentJIT=0") 2 2 function foo(o) { 3 3 o.f = 0; -
trunk/JSTests/stress/make-dictionary-repatch.js
r208692 r254480 1 //@ if $jitTests then runNoCJIT("--useDFGJIT=false", "-- useLLInt=false") else skip end1 //@ if $jitTests then runNoCJIT("--useDFGJIT=false", "--forceBaseline=true") else skip end 2 2 3 3 function foo(o) { -
trunk/JSTests/stress/merging-ic-variants-should-bail-if-structures-overlap.js
r238411 r254480 1 //@ runDefault("--validateGraphAtEachPhase=1", "-- useLLInt=0")1 //@ runDefault("--validateGraphAtEachPhase=1", "--forceBaseline=1") 2 2 3 3 let items = []; -
trunk/JSTests/stress/proxy-getter-stack-overflow.js
r244069 r254480 1 //@ if $jitTests then runDefault("-- useLLInt=0") else skip end1 //@ if $jitTests then runDefault("--forceBaseline=1") else skip end 2 2 3 3 const o = {}; -
trunk/JSTests/stress/regress-192717.js
r239867 r254480 1 1 //@ skip if $memoryLimited or $buildType == "debug" 2 //@ runDefault("-- useLLInt=false", "--forceCodeBlockToJettisonDueToOldAge=true", "--maxPerThreadStackUsage=200000", "--exceptionStackTraceLimit=1", "--defaultErrorStackTraceLimit=1")2 //@ runDefault("--forceBaseline=true", "--forceCodeBlockToJettisonDueToOldAge=true", "--maxPerThreadStackUsage=200000", "--exceptionStackTraceLimit=1", "--defaultErrorStackTraceLimit=1") 3 3 4 4 let foo = 'let a'; -
trunk/JSTests/stress/retry-cache-later.js
r208692 r254480 1 //@ runNoCJIT("-- useLLInt=false", "--useDFGJIT=false")1 //@ runNoCJIT("--forceBaseline=true", "--useDFGJIT=false") 2 2 3 3 function foo(o) { -
trunk/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp
r253975 r254480 120 120 { 121 121 static const TierOptions tierOptionsList[] = { 122 { "LLINT", 0_ms, "--useConcurrentJIT=false --use LLInt=true --useJIT=false" },123 { "Baseline", 0_ms, "--useConcurrentJIT=false --use LLInt=true --useJIT=true --useDFGJIT=false" },124 { "DFG", 200_ms, "--useConcurrentJIT=false --use LLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=false" },122 { "LLINT", 0_ms, "--useConcurrentJIT=false --useJIT=false" }, 123 { "Baseline", 0_ms, "--useConcurrentJIT=false --useJIT=true --useDFGJIT=false" }, 124 { "DFG", 200_ms, "--useConcurrentJIT=false --useJIT=true --useDFGJIT=true --useFTLJIT=false" }, 125 125 #if ENABLE(FTL_JIT) 126 { "FTL", 500_ms, "--useConcurrentJIT=false --use LLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=true" },126 { "FTL", 500_ms, "--useConcurrentJIT=false --useJIT=true --useDFGJIT=true --useFTLJIT=true" }, 127 127 #endif 128 128 }; -
trunk/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp
r237919 r254480 123 123 auto origSoftReservedZoneSize = Options::softReservedZoneSize(); 124 124 auto origReservedZoneSize = Options::reservedZoneSize(); 125 auto orig UseLLInt = Options::useLLInt();125 auto origForceBaseline = Options::forceBaseline(); 126 126 auto origMaxPerThreadStackUsage = Options::maxPerThreadStackUsage(); 127 127 … … 132 132 // reproducing the regression in https://bugs.webkit.org/show_bug.cgi?id=148749. However, we only 133 133 // want to do this if the LLINT isn't the only available execution engine. 134 Options:: useLLInt() = false;134 Options::forceBaseline() = true; 135 135 #endif 136 136 … … 179 179 Options::softReservedZoneSize() = origSoftReservedZoneSize; 180 180 Options::reservedZoneSize() = origReservedZoneSize; 181 Options:: useLLInt() = origUseLLInt;181 Options::forceBaseline() = origForceBaseline; 182 182 Options::maxPerThreadStackUsage() = origMaxPerThreadStackUsage; 183 183 -
trunk/Source/JavaScriptCore/ChangeLog
r254464 r254480 1 2020-01-13 Saam Barati <sbarati@apple.com> 2 3 Throw away baseline code if there is an optimized replacement 4 https://bugs.webkit.org/show_bug.cgi?id=202503 5 6 Reviewed by Yusuke Suzuki. 7 8 This patch's goal is to help us save JIT executable memory by throwing 9 away baseline code when it has an optimized replacement. To make it 10 easy to reason about, we do this when finalizing a GC, and when the 11 CodeBlock is not on the stack. When we do this, we throw away all JIT 12 data and unlink all incoming calls. 13 14 This patch also paves the way for the LOL tier by making it so we always 15 exit to the LLInt. This allows the code in CodeBlock finalization to not 16 have to consider whether or not an an OSR exit is wired to baseline 17 JIT code, since all exits are now to the LLInt. Because of this, this 18 patch removes the forceOSRExitToLLInt option. Also, this patch renames 19 the useLLInt option to forceBaseline and inverts its meaning. 20 Options::forceBaseline=true implies that code will start off executing in 21 the baseline JIT instead of the LLInt. However, it won't prevent us from 22 emitting an OSR exit which jumps to LLInt code. 23 24 * API/tests/ExecutionTimeLimitTest.cpp: 25 (testExecutionTimeLimit): 26 * API/tests/PingPongStackOverflowTest.cpp: 27 (testPingPongStackOverflow): 28 * bytecode/CodeBlock.cpp: 29 (JSC::CodeBlock::finishCreation): 30 (JSC::CodeBlock::finalizeUnconditionally): 31 (JSC::CodeBlock::resetJITData): 32 (JSC::CodeBlock::optimizedReplacement): 33 (JSC::CodeBlock::hasOptimizedReplacement): 34 (JSC::CodeBlock::tallyFrequentExitSites): 35 (JSC::CodeBlock::findStubInfo): Deleted. 36 (JSC::CodeBlock::getCallLinkInfoForBytecodeIndex): Deleted. 37 * bytecode/CodeBlock.h: 38 (JSC::CodeBlock::setJITCode): 39 * dfg/DFGDriver.cpp: 40 (JSC::DFG::compileImpl): 41 * dfg/DFGOSRExitCompilerCommon.cpp: 42 (JSC::DFG::callerReturnPC): 43 (JSC::DFG::reifyInlinedCallFrames): 44 (JSC::DFG::adjustAndJumpToTarget): 45 * dfg/DFGOSRExitCompilerCommon.h: 46 * heap/CodeBlockSet.cpp: 47 (JSC::CodeBlockSet::isCurrentlyExecuting): 48 * heap/CodeBlockSet.h: 49 * heap/Heap.cpp: 50 (JSC::Heap::finalizeUnconditionalFinalizers): 51 (JSC::Heap::runEndPhase): 52 * llint/LLIntSlowPaths.cpp: 53 (JSC::LLInt::dispatchToNextInstruction): 54 * runtime/Options.cpp: 55 (JSC::recomputeDependentOptions): 56 (JSC::Options::initialize): 57 (JSC::Options::ensureOptionsAreCoherent): 58 * runtime/OptionsList.h: 59 * runtime/ScriptExecutable.cpp: 60 (JSC::ScriptExecutable::prepareForExecutionImpl): 61 1 62 2020-01-13 Mark Lam <mark.lam@apple.com> 2 63 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r254464 r254480 443 443 HandlerInfo& handler = m_rareData->m_exceptionHandlers[i]; 444 444 #if ENABLE(JIT) 445 auto instruction = instructions().at(unlinkedHandler.target); 446 MacroAssemblerCodePtr<BytecodePtrTag> codePtr; 447 if (instruction->isWide32()) 448 codePtr = LLInt::getWide32CodePtr<BytecodePtrTag>(op_catch); 449 else if (instruction->isWide16()) 450 codePtr = LLInt::getWide16CodePtr<BytecodePtrTag>(op_catch); 451 else 452 codePtr = LLInt::getCodePtr<BytecodePtrTag>(op_catch); 445 auto& instruction = *instructions().at(unlinkedHandler.target).ptr(); 446 MacroAssemblerCodePtr<BytecodePtrTag> codePtr = LLInt::getCodePtr<BytecodePtrTag>(instruction); 453 447 handler.initialize(unlinkedHandler, CodeLocationLabel<ExceptionHandlerPtrTag>(codePtr.retagged<ExceptionHandlerPtrTag>())); 454 448 #else … … 1389 1383 1390 1384 updateAllPredictions(); 1385 1386 #if ENABLE(JIT) 1387 // If BaselineJIT code is not executing, and an optimized replacement exists, we attempt 1388 // to discard baseline JIT code and reinstall LLInt code to save JIT memory. 1389 if (!Options::forceBaseline() && jitType() == JITType::BaselineJIT && !m_vm->heap.codeBlockSet().isCurrentlyExecuting(this)) { 1390 if (CodeBlock* optimizedCodeBlock = optimizedReplacement()) { 1391 if (!optimizedCodeBlock->m_osrExitCounter) { 1392 m_jitCode = nullptr; 1393 LLInt::setEntrypoint(this); 1394 RELEASE_ASSERT(jitType() == JITType::InterpreterThunk); 1395 1396 for (size_t i = 0; i < m_unlinkedCode->numberOfExceptionHandlers(); i++) { 1397 const UnlinkedHandlerInfo& unlinkedHandler = m_unlinkedCode->exceptionHandler(i); 1398 HandlerInfo& handler = m_rareData->m_exceptionHandlers[i]; 1399 auto& instruction = *instructions().at(unlinkedHandler.target).ptr(); 1400 MacroAssemblerCodePtr<BytecodePtrTag> codePtr = LLInt::getCodePtr<BytecodePtrTag>(instruction); 1401 handler.initialize(unlinkedHandler, CodeLocationLabel<ExceptionHandlerPtrTag>(codePtr.retagged<ExceptionHandlerPtrTag>())); 1402 } 1403 1404 unlinkIncomingCalls(); 1405 1406 // It's safe to clear these out here because in finalizeUnconditionally all compiler threads 1407 // are safepointed, meaning they're running either before or after bytecode parser, and bytecode 1408 // parser is the only data structure pointing into the various *infos. 1409 resetJITData(); 1410 } 1411 } 1412 } 1413 1414 #endif 1391 1415 1392 1416 if (JITCode::couldBeInterpreted(jitType())) … … 1516 1540 } 1517 1541 1518 StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin)1519 {1520 ConcurrentJSLocker locker(m_lock);1521 if (auto* jitData = m_jitData.get()) {1522 for (StructureStubInfo* stubInfo : jitData->m_stubInfos) {1523 if (stubInfo->codeOrigin == codeOrigin)1524 return stubInfo;1525 }1526 }1527 return nullptr;1528 }1529 1530 1542 ByValInfo* CodeBlock::addByValInfo() 1531 1543 { … … 1538 1550 ConcurrentJSLocker locker(m_lock); 1539 1551 return ensureJITData(locker).m_callLinkInfos.add(); 1540 }1541 1542 CallLinkInfo* CodeBlock::getCallLinkInfoForBytecodeIndex(BytecodeIndex index)1543 {1544 ConcurrentJSLocker locker(m_lock);1545 if (auto* jitData = m_jitData.get()) {1546 for (CallLinkInfo* callLinkInfo : jitData->m_callLinkInfos) {1547 if (callLinkInfo->codeOrigin() == CodeOrigin(index))1548 return callLinkInfo;1549 }1550 }1551 return nullptr;1552 1552 } 1553 1553 … … 1599 1599 // link infos, or by val infos if we don't have JIT code. Attempts to query these data 1600 1600 // structures using the concurrent API (getICStatusMap and friends) will return nothing if we 1601 // don't have JIT code. 1602 jitData->m_stubInfos.clear(); 1603 jitData->m_callLinkInfos.clear(); 1604 jitData->m_byValInfos.clear(); 1601 // don't have JIT code. So it's safe to call this if we fail a baseline JIT compile. 1602 // 1603 // We also call this from finalizeUnconditionally when we degrade from baseline JIT to LLInt 1604 // code. This is safe to do since all compiler threads are safepointed in finalizeUnconditionally, 1605 // which means we've made it past bytecode parsing. Only the bytecode parser will hold onto 1606 // references to these various *infos via its use of ICStatusMap. 1607 1608 for (StructureStubInfo* stubInfo : jitData->m_stubInfos) { 1609 stubInfo->aboutToDie(); 1610 stubInfo->deref(); 1611 } 1612 1605 1613 // We can clear this because the DFG's queries to these data structures are guarded by whether 1606 1614 // there is JIT code. 1607 jitData->m_rareCaseProfiles.clear(); 1615 1616 m_jitData = nullptr; 1608 1617 } 1609 1618 } … … 1737 1746 1738 1747 #if ENABLE(JIT) 1748 CodeBlock* CodeBlock::optimizedReplacement(JITType typeToReplace) 1749 { 1750 CodeBlock* replacement = this->replacement(); 1751 if (!replacement) 1752 return nullptr; 1753 if (JITCode::isHigherTier(replacement->jitType(), typeToReplace)) 1754 return replacement; 1755 return nullptr; 1756 } 1757 1758 CodeBlock* CodeBlock::optimizedReplacement() 1759 { 1760 return optimizedReplacement(jitType()); 1761 } 1762 1739 1763 bool CodeBlock::hasOptimizedReplacement(JITType typeToReplace) 1740 1764 { 1741 CodeBlock* replacement = this->replacement(); 1742 return replacement && JITCode::isHigherTier(replacement->jitType(), typeToReplace); 1765 return !!optimizedReplacement(typeToReplace); 1743 1766 } 1744 1767 … … 2802 2825 { 2803 2826 ASSERT(JITCode::isOptimizingJIT(jitType())); 2804 ASSERT( alternative()->jitType() == JITType::BaselineJIT);2827 ASSERT(JITCode::isBaselineCode(alternative()->jitType())); 2805 2828 2806 2829 CodeBlock* profiledBlock = alternative(); -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r253987 r254480 259 259 Optional<BytecodeIndex> bytecodeIndexFromCallSiteIndex(CallSiteIndex); 260 260 261 // Because we might throw out baseline JIT code and all its baseline JIT data (m_jitData), 262 // you need to be careful about the lifetime of when you use the return value of this function. 263 // The return value may have raw pointers into this data structure that gets thrown away. 264 // Specifically, you need to ensure that no GC can be finalized (typically that means no 265 // allocations) between calling this and the last use of it. 261 266 void getICStatusMap(const ConcurrentJSLocker&, ICStatusMap& result); 262 267 void getICStatusMap(ICStatusMap& result); … … 278 283 std::unique_ptr<PCToCodeOriginMap> m_pcToCodeOriginMap; 279 284 std::unique_ptr<RegisterAtOffsetList> m_calleeSaveRegisters; 285 // FIXME: Now that we unconditionally OSR exit to the LLInt, we might be able to prune 286 // the number of entries we have in this to contain entries only for opcodes we use 287 // it for. Today, that's only for loop OSR entry. 288 // https://bugs.webkit.org/show_bug.cgi?id=206207 280 289 JITCodeMap m_jitCodeMap; 281 290 }; … … 308 317 StructureStubInfo* addStubInfo(AccessType); 309 318 310 // O(n) operation. Use getStubInfoMap() unless you really only intend to get one311 // stub info.312 StructureStubInfo* findStubInfo(CodeOrigin);313 314 319 ByValInfo* addByValInfo(); 315 320 316 321 CallLinkInfo* addCallLinkInfo(); 317 318 // This is a slow function call used primarily for compiling OSR exits in the case319 // that there had been inlining. Chances are if you want to use this, you're really320 // looking for a CallLinkInfoMap to amortize the cost of calling this.321 CallLinkInfo* getCallLinkInfoForBytecodeIndex(BytecodeIndex);322 322 323 323 void setJITCodeMap(JITCodeMap&& jitCodeMap) … … 413 413 void setJITCode(Ref<JITCode>&& code) 414 414 { 415 ASSERT(heap()->isDeferred());416 415 if (!code->isShared()) 417 416 heap()->reportExtraMemoryAllocated(code->size()); … … 445 444 DFG::CapabilityLevel capabilityLevelState() { return static_cast<DFG::CapabilityLevel>(m_capabilityLevelState); } 446 445 446 CodeBlock* optimizedReplacement(JITType typeToReplace); 447 CodeBlock* optimizedReplacement(); // the typeToReplace is my JITType 447 448 bool hasOptimizedReplacement(JITType typeToReplace); 448 449 bool hasOptimizedReplacement(); // the typeToReplace is my JITType -
trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp
r253896 r254480 82 82 ASSERT(codeBlock); 83 83 ASSERT(codeBlock->alternative()); 84 ASSERT( codeBlock->alternative()->jitType() == JITType::BaselineJIT);84 ASSERT(JITCode::isBaselineCode(codeBlock->alternative()->jitType())); 85 85 ASSERT(!profiledDFGCodeBlock || profiledDFGCodeBlock->jitType() == JITType::DFGJIT); 86 86 -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
r254143 r254480 143 143 } 144 144 145 MacroAssemblerCodePtr<JSEntryPtrTag> callerReturnPC(CodeBlock* baselineCodeBlockForCaller, BytecodeIndex callBytecodeIndex, InlineCallFrame::Kind trueCallerCallKind, bool& callerIsLLInt) 146 { 147 callerIsLLInt = Options::forceOSRExitToLLInt() || baselineCodeBlockForCaller->jitType() == JITType::InterpreterThunk; 148 145 static MacroAssemblerCodePtr<JSEntryPtrTag> callerReturnPC(CodeBlock* baselineCodeBlockForCaller, BytecodeIndex callBytecodeIndex, InlineCallFrame::Kind trueCallerCallKind) 146 { 149 147 if (callBytecodeIndex.checkpoint()) 150 148 return LLInt::getCodePtr<JSEntryPtrTag>(checkpoint_osr_exit_from_inlined_call_trampoline); … … 152 150 MacroAssemblerCodePtr<JSEntryPtrTag> jumpTarget; 153 151 154 if (callerIsLLInt) { 155 const Instruction& callInstruction = *baselineCodeBlockForCaller->instructions().at(callBytecodeIndex).ptr(); 152 const Instruction& callInstruction = *baselineCodeBlockForCaller->instructions().at(callBytecodeIndex).ptr(); 156 153 #define LLINT_RETURN_LOCATION(name) (callInstruction.isWide16() ? LLInt::getWide16CodePtr<JSEntryPtrTag>(name##_return_location) : (callInstruction.isWide32() ? LLInt::getWide32CodePtr<JSEntryPtrTag>(name##_return_location) : LLInt::getCodePtr<JSEntryPtrTag>(name##_return_location))) 157 154 158 switch (trueCallerCallKind) { 159 case InlineCallFrame::Call: 160 jumpTarget = LLINT_RETURN_LOCATION(op_call); 161 break; 162 case InlineCallFrame::Construct: 163 jumpTarget = LLINT_RETURN_LOCATION(op_construct); 164 break; 165 case InlineCallFrame::CallVarargs: 166 jumpTarget = LLINT_RETURN_LOCATION(op_call_varargs_slow); 167 break; 168 case InlineCallFrame::ConstructVarargs: 169 jumpTarget = LLINT_RETURN_LOCATION(op_construct_varargs_slow); 170 break; 171 case InlineCallFrame::GetterCall: { 172 if (callInstruction.opcodeID() == op_get_by_id) 173 jumpTarget = LLINT_RETURN_LOCATION(op_get_by_id); 174 else if (callInstruction.opcodeID() == op_get_by_val) 175 jumpTarget = LLINT_RETURN_LOCATION(op_get_by_val); 176 else 177 RELEASE_ASSERT_NOT_REACHED(); 178 break; 179 } 180 case InlineCallFrame::SetterCall: { 181 if (callInstruction.opcodeID() == op_put_by_id) 182 jumpTarget = LLINT_RETURN_LOCATION(op_put_by_id); 183 else if (callInstruction.opcodeID() == op_put_by_val) 184 jumpTarget = LLINT_RETURN_LOCATION(op_put_by_val); 185 else 186 RELEASE_ASSERT_NOT_REACHED(); 187 break; 188 } 189 default: 155 switch (trueCallerCallKind) { 156 case InlineCallFrame::Call: 157 jumpTarget = LLINT_RETURN_LOCATION(op_call); 158 break; 159 case InlineCallFrame::Construct: 160 jumpTarget = LLINT_RETURN_LOCATION(op_construct); 161 break; 162 case InlineCallFrame::CallVarargs: 163 jumpTarget = LLINT_RETURN_LOCATION(op_call_varargs_slow); 164 break; 165 case InlineCallFrame::ConstructVarargs: 166 jumpTarget = LLINT_RETURN_LOCATION(op_construct_varargs_slow); 167 break; 168 case InlineCallFrame::GetterCall: { 169 if (callInstruction.opcodeID() == op_get_by_id) 170 jumpTarget = LLINT_RETURN_LOCATION(op_get_by_id); 171 else if (callInstruction.opcodeID() == op_get_by_val) 172 jumpTarget = LLINT_RETURN_LOCATION(op_get_by_val); 173 else 190 174 RELEASE_ASSERT_NOT_REACHED(); 191 } 175 break; 176 } 177 case InlineCallFrame::SetterCall: { 178 if (callInstruction.opcodeID() == op_put_by_id) 179 jumpTarget = LLINT_RETURN_LOCATION(op_put_by_id); 180 else if (callInstruction.opcodeID() == op_put_by_val) 181 jumpTarget = LLINT_RETURN_LOCATION(op_put_by_val); 182 else 183 RELEASE_ASSERT_NOT_REACHED(); 184 break; 185 } 186 default: 187 RELEASE_ASSERT_NOT_REACHED(); 188 } 192 189 193 190 #undef LLINT_RETURN_LOCATION 194 195 } else {196 switch (trueCallerCallKind) {197 case InlineCallFrame::Call:198 case InlineCallFrame::Construct:199 case InlineCallFrame::CallVarargs:200 case InlineCallFrame::ConstructVarargs: {201 CallLinkInfo* callLinkInfo =202 baselineCodeBlockForCaller->getCallLinkInfoForBytecodeIndex(callBytecodeIndex);203 RELEASE_ASSERT(callLinkInfo);204 205 jumpTarget = callLinkInfo->callReturnLocation().retagged<JSEntryPtrTag>();206 break;207 }208 209 case InlineCallFrame::GetterCall:210 case InlineCallFrame::SetterCall: {211 StructureStubInfo* stubInfo =212 baselineCodeBlockForCaller->findStubInfo(CodeOrigin(callBytecodeIndex));213 RELEASE_ASSERT(stubInfo);214 215 jumpTarget = stubInfo->doneLocation.retagged<JSEntryPtrTag>();216 break;217 }218 219 default:220 RELEASE_ASSERT_NOT_REACHED();221 }222 }223 191 224 192 return jumpTarget; … … 254 222 CodeOrigin* trueCaller = inlineCallFrame->getCallerSkippingTailCalls(&trueCallerCallKind); 255 223 GPRReg callerFrameGPR = GPRInfo::callFrameRegister; 256 257 bool callerIsLLInt = false;258 224 259 225 if (!trueCaller) { … … 272 238 CodeBlock* baselineCodeBlockForCaller = jit.baselineCodeBlockFor(*trueCaller); 273 239 auto callBytecodeIndex = trueCaller->bytecodeIndex(); 274 MacroAssemblerCodePtr<JSEntryPtrTag> jumpTarget = callerReturnPC(baselineCodeBlockForCaller, callBytecodeIndex, trueCallerCallKind , callerIsLLInt);240 MacroAssemblerCodePtr<JSEntryPtrTag> jumpTarget = callerReturnPC(baselineCodeBlockForCaller, callBytecodeIndex, trueCallerCallKind); 275 241 276 242 if (trueCaller->inlineCallFrame()) { … … 303 269 GPRInfo::regT2); 304 270 305 if (callerIsLLInt) { 271 if (trueCaller) { 272 // Set up LLInt registers for our caller in our callee saves. 306 273 CodeBlock* baselineCodeBlockForCaller = jit.baselineCodeBlockFor(*trueCaller); 307 274 jit.storePtr(CCallHelpers::TrustedImmPtr(baselineCodeBlockForCaller->metadataTable()), calleeSaveSlot(inlineCallFrame, baselineCodeBlock, LLInt::Registers::metadataTableGPR)); … … 389 356 ASSERT(JITCode::isBaselineCode(codeBlockForExit->jitType())); 390 357 391 void* jumpTarget; 392 bool exitToLLInt = Options::forceOSRExitToLLInt() || codeBlockForExit->jitType() == JITType::InterpreterThunk; 393 if (exitToLLInt) { 394 auto bytecodeIndex = exit.m_codeOrigin.bytecodeIndex(); 395 const Instruction& currentInstruction = *codeBlockForExit->instructions().at(bytecodeIndex).ptr(); 396 MacroAssemblerCodePtr<JSEntryPtrTag> destination; 397 if (bytecodeIndex.checkpoint()) 398 destination = LLInt::getCodePtr<JSEntryPtrTag>(checkpoint_osr_exit_trampoline); 399 else 400 destination = LLInt::getCodePtr<JSEntryPtrTag>(currentInstruction); 401 402 if (exit.isExceptionHandler()) { 403 jit.move(CCallHelpers::TrustedImmPtr(¤tInstruction), GPRInfo::regT2); 404 jit.storePtr(GPRInfo::regT2, &vm.targetInterpreterPCForThrow); 405 } 406 407 jit.move(CCallHelpers::TrustedImmPtr(codeBlockForExit->metadataTable()), LLInt::Registers::metadataTableGPR); 358 auto bytecodeIndex = exit.m_codeOrigin.bytecodeIndex(); 359 const Instruction& currentInstruction = *codeBlockForExit->instructions().at(bytecodeIndex).ptr(); 360 MacroAssemblerCodePtr<JSEntryPtrTag> destination; 361 if (bytecodeIndex.checkpoint()) 362 destination = LLInt::getCodePtr<JSEntryPtrTag>(checkpoint_osr_exit_trampoline); 363 else 364 destination = LLInt::getCodePtr<JSEntryPtrTag>(currentInstruction); 365 366 if (exit.isExceptionHandler()) { 367 jit.move(CCallHelpers::TrustedImmPtr(¤tInstruction), GPRInfo::regT2); 368 jit.storePtr(GPRInfo::regT2, &vm.targetInterpreterPCForThrow); 369 } 370 371 jit.move(CCallHelpers::TrustedImmPtr(codeBlockForExit->metadataTable()), LLInt::Registers::metadataTableGPR); 408 372 #if USE(JSVALUE64) 409 jit.move(CCallHelpers::TrustedImmPtr(codeBlockForExit->instructionsRawPointer()), LLInt::Registers::pbGPR);410 jit.move(CCallHelpers::TrustedImm32(bytecodeIndex.offset()), LLInt::Registers::pcGPR);373 jit.move(CCallHelpers::TrustedImmPtr(codeBlockForExit->instructionsRawPointer()), LLInt::Registers::pbGPR); 374 jit.move(CCallHelpers::TrustedImm32(bytecodeIndex.offset()), LLInt::Registers::pcGPR); 411 375 #else 412 jit.move(CCallHelpers::TrustedImmPtr(¤tInstruction), LLInt::Registers::pcGPR); 413 #endif 414 jumpTarget = destination.retagged<OSRExitPtrTag>().executableAddress(); 415 } else { 416 BytecodeIndex exitIndex = exit.m_codeOrigin.bytecodeIndex(); 417 MacroAssemblerCodePtr<JSEntryPtrTag> destination; 418 if (exitIndex.checkpoint()) 419 destination = LLInt::getCodePtr<JSEntryPtrTag>(checkpoint_osr_exit_trampoline); 420 else { 421 ASSERT(codeBlockForExit->bytecodeIndexForExit(exitIndex) == exitIndex); 422 destination = codeBlockForExit->jitCodeMap().find(exitIndex); 423 } 424 425 ASSERT(destination); 426 427 jumpTarget = destination.retagged<OSRExitPtrTag>().executableAddress(); 428 } 376 jit.move(CCallHelpers::TrustedImmPtr(¤tInstruction), LLInt::Registers::pcGPR); 377 #endif 429 378 430 379 jit.addPtr(AssemblyHelpers::TrustedImm32(JIT::stackPointerOffsetFor(codeBlockForExit) * sizeof(Register)), GPRInfo::callFrameRegister, AssemblyHelpers::stackPointerRegister); … … 434 383 } 435 384 436 jit.move(AssemblyHelpers::TrustedImmPtr( jumpTarget), GPRInfo::regT2);385 jit.move(AssemblyHelpers::TrustedImmPtr(destination.retagged<OSRExitPtrTag>().executableAddress()), GPRInfo::regT2); 437 386 jit.farJump(GPRInfo::regT2, OSRExitPtrTag); 438 387 } -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h
r254142 r254480 40 40 void reifyInlinedCallFrames(CCallHelpers&, const OSRExitBase&); 41 41 void adjustAndJumpToTarget(VM&, CCallHelpers&, const OSRExitBase&); 42 MacroAssemblerCodePtr<JSEntryPtrTag> callerReturnPC(CodeBlock* baselineCodeBlockForCaller, BytecodeIndex callBytecodeIndex, InlineCallFrame::Kind callerKind, bool& callerIsLLInt);43 42 CCallHelpers::Address calleeSaveSlot(InlineCallFrame*, CodeBlock* baselineCodeBlock, GPRReg calleeSave); 44 43 -
trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp
r226783 r254480 56 56 } 57 57 58 bool CodeBlockSet::isCurrentlyExecuting(CodeBlock* codeBlock) 59 { 60 return m_currentlyExecuting.contains(codeBlock); 61 } 62 58 63 void CodeBlockSet::dump(PrintStream& out) const 59 64 { -
trunk/Source/JavaScriptCore/heap/CodeBlockSet.h
r229180 r254480 57 57 Lock& getLock() { return m_lock; } 58 58 59 // This is expected to run only when we're not adding to the set for now. If 60 // this needs to run concurrently in the future, we'll need to lock around this. 61 bool isCurrentlyExecuting(CodeBlock*); 62 59 63 // Visits each CodeBlock in the heap until the visitor function returns true 60 64 // to indicate that it is done iterating, or until every CodeBlock has been -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r254393 r254480 614 614 finalizeMarkedUnconditionalFinalizers<FunctionExecutable>(vm().functionExecutableSpace.space); 615 615 finalizeMarkedUnconditionalFinalizers<SymbolTable>(vm().symbolTableSpace); 616 finalizeMarkedUnconditionalFinalizers<ExecutableToCodeBlockEdge>(vm().executableToCodeBlockEdgesWithFinalizers); // We run this before CodeBlock's unconditional finalizer since CodeBlock looks at the owner executable's installed CodeBlock in its finalizeUnconditionally. 616 617 vm().forEachCodeBlockSpace( 617 618 [&] (auto& space) { 618 619 this->finalizeMarkedUnconditionalFinalizers<CodeBlock>(space.set); 619 620 }); 620 finalizeMarkedUnconditionalFinalizers<ExecutableToCodeBlockEdge>(vm().executableToCodeBlockEdgesWithFinalizers);621 621 finalizeMarkedUnconditionalFinalizers<StructureRareData>(vm().structureRareDataSpace); 622 622 finalizeMarkedUnconditionalFinalizers<UnlinkedFunctionExecutable>(vm().unlinkedFunctionExecutableSpace.set); … … 1523 1523 sweepArrayBuffers(); 1524 1524 snapshotUnswept(); 1525 finalizeUnconditionalFinalizers(); 1525 finalizeUnconditionalFinalizers(); // We rely on these unconditional finalizers running before clearCurrentlyExecuting since CodeBlock's finalizer relies on querying currently executing. 1526 1526 removeDeadCompilerWorklistEntries(); 1527 1527 notifyIncrementalSweeper(); -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r253896 r254480 1994 1994 { 1995 1995 RELEASE_ASSERT(!codeBlock->vm().exceptionForInspection()); 1996 if (Options::forceOSRExitToLLInt() || codeBlock->jitType() == JITType::InterpreterThunk) { 1997 const Instruction* nextPC = pc.next().ptr(); 1998 auto nextBytecode = LLInt::getCodePtr<JSEntryPtrTag>(*pc.next().ptr()); 1999 return encodeResult(nextPC, nextBytecode.executableAddress()); 2000 } 2001 2002 #if ENABLE(JIT) 2003 ASSERT(codeBlock->jitType() == JITType::BaselineJIT); 2004 BytecodeIndex nextBytecodeIndex = pc.next().index(); 2005 auto nextBytecode = codeBlock->jitCodeMap().find(nextBytecodeIndex); 2006 return encodeResult(nullptr, nextBytecode.executableAddress()); 2007 #endif 2008 RELEASE_ASSERT_NOT_REACHED(); 1996 const Instruction* nextPC = pc.next().ptr(); 1997 auto nextBytecode = LLInt::getCodePtr<JSEntryPtrTag>(*pc.next().ptr()); 1998 return encodeResult(nextPC, nextBytecode.executableAddress()); 2009 1999 } 2010 2000 -
trunk/Source/JavaScriptCore/runtime/Options.cpp
r253975 r254480 388 388 #endif 389 389 #if !ENABLE(JIT) 390 Options:: useLLInt() = true;390 Options::forceBaseline() = false; 391 391 Options::useJIT() = false; 392 392 Options::useBaselineJIT() = false; … … 420 420 421 421 if (!jitEnabledByDefault() && !Options::useJIT()) 422 Options:: useLLInt() = true;422 Options::forceBaseline() = false; 423 423 424 424 if (!Options::useWebAssembly()) … … 547 547 RELEASE_ASSERT(Options::addressOfOption(gcMaxHeapSizeID) == &Options::gcMaxHeapSize()); 548 548 RELEASE_ASSERT(Options::addressOfOptionDefault(gcMaxHeapSizeID) == &Options::gcMaxHeapSizeDefault()); 549 RELEASE_ASSERT(Options::addressOfOption(forceOSRExitToLLIntID) == &Options::forceOSRExitToLLInt());550 RELEASE_ASSERT(Options::addressOfOptionDefault(forceOSRExitToLLIntID) == &Options::forceOSRExitToLLIntDefault());551 549 552 550 #ifndef NDEBUG … … 946 944 { 947 945 bool coherent = true; 948 if ( !(useLLInt() || useJIT())) {946 if (forceBaseline() && !useJIT()) { 949 947 coherent = false; 950 dataLog("INCOHERENT OPTIONS: at least one of useLLInt or useJIT must be true\n");948 dataLog("INCOHERENT OPTIONS: forceBaseline can't be true if useJIT is false\n"); 951 949 } 952 950 if (!coherent) -
trunk/Source/JavaScriptCore/runtime/OptionsList.h
r254230 r254480 82 82 v(OptionString, configFile, nullptr, Normal, "file to configure JSC options and logging location") \ 83 83 \ 84 v(Bool, useLLInt, true, Normal, "allows the LLINT to be used if true") \84 v(Bool, forceBaseline, false, Normal, "If true, we'll start running code in the baseline JIT and skip starting in the LLInt") \ 85 85 v(Bool, useJIT, jitEnabledByDefault(), Normal, "allows the executable pages to be allocated for JIT and thunks if true") \ 86 86 v(Bool, useBaselineJIT, true, Normal, "allows the baseline JIT to be used if true") \ … … 495 495 v(Double, dumpJITMemoryFlushInterval, 10, Restricted, "Maximum time in between flushes of the JIT memory dump in seconds.") \ 496 496 v(Bool, useUnlinkedCodeBlockJettisoning, false, Normal, "If true, UnlinkedCodeBlock can be jettisoned.") \ 497 v(Bool, forceOSRExitToLLInt, false, Normal, "If true, we always exit to the LLInt. If false, we exit to whatever is most convenient.") \498 497 v(Unsigned, getByValICMaxNumberOfIdentifiers, 4, Normal, "Number of identifiers we see in the LLInt that could cause us to bail on generating an IC for get_by_val.") \ 499 498 -
trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp
r251425 r254480 427 427 codeBlock->validate(); 428 428 429 if (Options::useLLInt()) 429 if (Options::forceBaseline()) 430 setupJIT(vm, codeBlock); 431 else 430 432 setupLLInt(codeBlock); 431 else432 setupJIT(vm, codeBlock);433 433 434 434 installCode(vm, codeBlock, codeBlock->codeType(), codeBlock->specializationKind()); -
trunk/Tools/ChangeLog
r254479 r254480 1 2020-01-13 Saam Barati <sbarati@apple.com> 2 3 Throw away baseline code if there is an optimized replacement 4 https://bugs.webkit.org/show_bug.cgi?id=202503 5 6 Reviewed by Yusuke Suzuki. 7 8 * Scripts/run-jsc-stress-tests: 9 1 10 2020-01-13 Yoshiaki Jitsukawa <yoshiaki.jitsukawa@sony.com> 2 11 -
trunk/Tools/Scripts/run-jsc-stress-tests
r254290 r254480 499 499 B3O0_OPTIONS = ["--maxDFGNodesInBasicBlockForPreciseAnalysis=100", "--defaultB3OptLevel=0"] 500 500 FTL_OPTIONS = ["--useFTLJIT=true"] 501 FORCE_LLINT_EXIT_OPTIONS = ["--forceOSRExitToLLInt=true"]502 501 503 502 require_relative "webkitruby/jsc-stress-test-writer-#{$testWriter}" … … 656 655 def runNoLLInt(*optionalTestSpecificOptions) 657 656 if $jitTests 658 run("no-llint", "-- useLLInt=false", *optionalTestSpecificOptions)657 run("no-llint", "--forceBaseline=true", *optionalTestSpecificOptions) 659 658 end 660 659 end … … 709 708 710 709 def runFTLNoCJITB3O0(*optionalTestSpecificOptions) 711 run("ftl-no-cjit-b3o0", "--useArrayAllocationProfiling=false", "--forcePolyProto=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + B3O0_OPTIONS + FORCE_LLINT_EXIT_OPTIONS +optionalTestSpecificOptions))710 run("ftl-no-cjit-b3o0", "--useArrayAllocationProfiling=false", "--forcePolyProto=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + B3O0_OPTIONS + optionalTestSpecificOptions)) 712 711 end 713 712 … … 729 728 730 729 def runDFGEager(*optionalTestSpecificOptions) 731 run("dfg-eager", *(EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + FORCE_LLINT_EXIT_OPTIONS +optionalTestSpecificOptions))730 run("dfg-eager", *(EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions)) 732 731 end 733 732 … … 746 745 747 746 def runFTLEagerNoCJITValidate(*optionalTestSpecificOptions) 748 run("ftl-eager-no-cjit", "--validateGraph=true", "--airForceIRCAllocator=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + FORCE_LLINT_EXIT_OPTIONS +optionalTestSpecificOptions))747 run("ftl-eager-no-cjit", "--validateGraph=true", "--airForceIRCAllocator=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions)) 749 748 end 750 749 … … 1061 1060 end 1062 1061 1063 run("no-llint-modules", "-m", "-- useLLInt=false") if noLLInt1062 run("no-llint-modules", "-m", "--forceBaseline=true") if noLLInt 1064 1063 run("no-cjit-validate-phases-modules", "-m", "--validateBytecode=true", "--validateGraphAtEachPhase=true", *NO_CJIT_OPTIONS) 1065 1064 run("dfg-eager-modules", "-m", *EAGER_OPTIONS) … … 1262 1261 1263 1262 def runLayoutTestNoLLInt 1264 runLayoutTest("no-llint", "-- useLLInt=false")1263 runLayoutTest("no-llint", "--forceBaseline=true") 1265 1264 end 1266 1265 … … 1428 1427 1429 1428 def runMozillaTestBaselineJIT(mode, *extraFiles) 1430 runMozillaTest("baseline", mode, extraFiles, "-- useLLInt=false", "--useDFGJIT=false")1429 runMozillaTest("baseline", mode, extraFiles, "--forceBaseline=true", "--useDFGJIT=false") 1431 1430 end 1432 1431
Note:
See TracChangeset
for help on using the changeset viewer.