Changeset 95681 in webkit
- Timestamp:
- Sep 21, 2011 4:36:35 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 3 added
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r95559 r95681 50 50 heap/HandleHeap.cpp 51 51 heap/HandleStack.cpp 52 heap/JettisonedCodeBlocks.cpp 52 53 heap/MachineStackMarker.cpp 53 54 heap/MarkedBlock.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r95676 r95681 1 2011-09-21 Filip Pizlo <fpizlo@apple.com> 2 3 DFG should support continuous optimization 4 https://bugs.webkit.org/show_bug.cgi?id=68329 5 6 Reviewed by Geoffrey Garen. 7 8 This adds the ability to reoptimize a code block if speculation 9 failures happen frequently. 6% speed-up on Kraken, 1% slow-down 10 on V8, neutral on SunSpider. 11 12 * CMakeLists.txt: 13 * GNUmakefile.list.am: 14 * JavaScriptCore.pro: 15 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: 16 * JavaScriptCore.vcproj/WTF/WTF.vcproj: 17 * JavaScriptCore.xcodeproj/project.pbxproj: 18 * bytecode/CodeBlock.cpp: 19 (JSC::CodeBlock::CodeBlock): 20 (JSC::ProgramCodeBlock::jettison): 21 (JSC::EvalCodeBlock::jettison): 22 (JSC::FunctionCodeBlock::jettison): 23 (JSC::CodeBlock::shouldOptimizeNow): 24 (JSC::CodeBlock::dumpValueProfiles): 25 * bytecode/CodeBlock.h: 26 * dfg/DFGByteCodeParser.cpp: 27 (JSC::DFG::ByteCodeParser::getStrongPrediction): 28 * dfg/DFGJITCompiler.cpp: 29 (JSC::DFG::JITCompiler::exitSpeculativeWithOSR): 30 (JSC::DFG::JITCompiler::compileEntry): 31 (JSC::DFG::JITCompiler::compileBody): 32 * dfg/DFGJITCompiler.h: 33 (JSC::DFG::JITCompiler::noticeOSREntry): 34 * dfg/DFGOSREntry.cpp: 35 (JSC::DFG::prepareOSREntry): 36 * dfg/DFGOSREntry.h: 37 (JSC::DFG::getOSREntryDataBytecodeIndex): 38 * dfg/DFGSpeculativeJIT.cpp: 39 (JSC::DFG::SpeculativeJIT::compile): 40 * heap/ConservativeRoots.cpp: 41 (JSC::ConservativeRoots::ConservativeRoots): 42 (JSC::ConservativeRoots::~ConservativeRoots): 43 (JSC::DummyMarkHook::mark): 44 (JSC::ConservativeRoots::genericAddPointer): 45 (JSC::ConservativeRoots::genericAddSpan): 46 (JSC::ConservativeRoots::add): 47 * heap/ConservativeRoots.h: 48 * heap/Heap.cpp: 49 (JSC::Heap::addJettisonCodeBlock): 50 (JSC::Heap::markRoots): 51 * heap/Heap.h: 52 * heap/JettisonedCodeBlocks.cpp: Added. 53 (JSC::JettisonedCodeBlocks::JettisonedCodeBlocks): 54 (JSC::JettisonedCodeBlocks::~JettisonedCodeBlocks): 55 (JSC::JettisonedCodeBlocks::addCodeBlock): 56 (JSC::JettisonedCodeBlocks::clearMarks): 57 (JSC::JettisonedCodeBlocks::deleteUnmarkedCodeBlocks): 58 (JSC::JettisonedCodeBlocks::traceCodeBlocks): 59 * heap/JettisonedCodeBlocks.h: Added. 60 (JSC::JettisonedCodeBlocks::mark): 61 * interpreter/RegisterFile.cpp: 62 (JSC::RegisterFile::gatherConservativeRoots): 63 * interpreter/RegisterFile.h: 64 * jit/JITStubs.cpp: 65 (JSC::DEFINE_STUB_FUNCTION): 66 * runtime/Executable.cpp: 67 (JSC::jettisonCodeBlock): 68 (JSC::EvalExecutable::jettisonOptimizedCode): 69 (JSC::ProgramExecutable::jettisonOptimizedCode): 70 (JSC::FunctionExecutable::jettisonOptimizedCodeForCall): 71 (JSC::FunctionExecutable::jettisonOptimizedCodeForConstruct): 72 * runtime/Executable.h: 73 (JSC::FunctionExecutable::jettisonOptimizedCodeFor): 74 * wtf/BitVector.h: Added. 75 (WTF::BitVector::BitVector): 76 (WTF::BitVector::~BitVector): 77 (WTF::BitVector::operator=): 78 (WTF::BitVector::size): 79 (WTF::BitVector::ensureSize): 80 (WTF::BitVector::resize): 81 (WTF::BitVector::clearAll): 82 (WTF::BitVector::get): 83 (WTF::BitVector::set): 84 (WTF::BitVector::clear): 85 (WTF::BitVector::bitsInPointer): 86 (WTF::BitVector::maxInlineBits): 87 (WTF::BitVector::byteCount): 88 (WTF::BitVector::makeInlineBits): 89 (WTF::BitVector::OutOfLineBits::numBits): 90 (WTF::BitVector::OutOfLineBits::numWords): 91 (WTF::BitVector::OutOfLineBits::bits): 92 (WTF::BitVector::OutOfLineBits::create): 93 (WTF::BitVector::OutOfLineBits::destroy): 94 (WTF::BitVector::OutOfLineBits::OutOfLineBits): 95 (WTF::BitVector::isInline): 96 (WTF::BitVector::outOfLineBits): 97 (WTF::BitVector::resizeOutOfLine): 98 (WTF::BitVector::bits): 99 1 100 2011-09-21 Gavin Barraclough <barraclough@apple.com> 2 101 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r95559 r95681 141 141 Source/JavaScriptCore/heap/HandleHeap.cpp \ 142 142 Source/JavaScriptCore/heap/HandleHeap.h \ 143 Source/JavaScriptCore/heap/JettisonedCodeBlocks.cpp \ 144 Source/JavaScriptCore/heap/JettisonedCodeBlocks.h \ 143 145 Source/JavaScriptCore/heap/SlotVisitor.h \ 144 146 Source/JavaScriptCore/heap/HandleStack.cpp \ … … 465 467 Source/JavaScriptCore/wtf/Atomics.h \ 466 468 Source/JavaScriptCore/wtf/AVLTree.h \ 469 Source/JavaScriptCore/wtf/BitVector.h \ 467 470 Source/JavaScriptCore/wtf/Bitmap.h \ 468 471 Source/JavaScriptCore/wtf/BlockStack.h \ -
trunk/Source/JavaScriptCore/JavaScriptCore.pro
r95559 r95681 78 78 heap/HandleStack.cpp \ 79 79 heap/Heap.cpp \ 80 heap/JettisonedCodeBlocks.cpp \ 80 81 heap/MachineStackMarker.cpp \ 81 82 heap/MarkStack.cpp \ -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
r95559 r95681 1975 1975 </File> 1976 1976 <File 1977 RelativePath="..\..\heap\JettisonedCodeBlocks.cpp" 1978 > 1979 </File> 1980 <File 1981 RelativePath="..\..\heap\JettisonedCodeBlocks.h" 1982 > 1983 </File> 1984 <File 1977 1985 RelativePath="..\..\heap\Local.h" 1978 1986 > -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj
r95140 r95681 638 638 </File> 639 639 <File 640 RelativePath="..\..\wtf\BitVector.h" 641 > 642 </File> 643 <File 640 644 RelativePath="..\..\wtf\Bitmap.h" 641 645 > -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r95655 r95681 75 75 0FD82E9014207A5F00179C94 /* ValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E8E14207A5100179C94 /* ValueProfile.cpp */; }; 76 76 0FD82EF51423075B00179C94 /* DFGIntrinsic.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82EF31423073900179C94 /* DFGIntrinsic.h */; settings = {ATTRIBUTES = (Private, ); }; }; 77 0FD82F2B1426CA6D00179C94 /* JettisonedCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82F291426CA5A00179C94 /* JettisonedCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; }; 78 0FD82F2C1426CA7400179C94 /* JettisonedCodeBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82F281426CA5A00179C94 /* JettisonedCodeBlocks.cpp */; }; 79 0FD82F4B142806A100179C94 /* BitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82F491428069200179C94 /* BitVector.h */; settings = {ATTRIBUTES = (Private, ); }; }; 77 80 1400067712A6F7830064D123 /* OSAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400067612A6F7830064D123 /* OSAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 78 81 1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */; }; … … 814 817 0FD82E8E14207A5100179C94 /* ValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ValueProfile.cpp; sourceTree = "<group>"; }; 815 818 0FD82EF31423073900179C94 /* DFGIntrinsic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGIntrinsic.h; path = dfg/DFGIntrinsic.h; sourceTree = "<group>"; }; 819 0FD82F281426CA5A00179C94 /* JettisonedCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JettisonedCodeBlocks.cpp; sourceTree = "<group>"; }; 820 0FD82F291426CA5A00179C94 /* JettisonedCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JettisonedCodeBlocks.h; sourceTree = "<group>"; }; 821 0FD82F491428069200179C94 /* BitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitVector.h; sourceTree = "<group>"; }; 816 822 1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; }; 817 823 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSAllocatorPosix.cpp; sourceTree = "<group>"; }; … … 1622 1628 isa = PBXGroup; 1623 1629 children = ( 1630 0FD82F281426CA5A00179C94 /* JettisonedCodeBlocks.cpp */, 1631 0FD82F291426CA5A00179C94 /* JettisonedCodeBlocks.h */, 1624 1632 A70456AF1427FB150037DA68 /* AllocationSpace.h */, 1625 1633 A70456AE1427FB030037DA68 /* AllocationSpace.cpp */, … … 1798 1806 isa = PBXGroup; 1799 1807 children = ( 1808 0FD82F491428069200179C94 /* BitVector.h */, 1800 1809 C22C524813FAF6EF00B7DC0D /* dtoa */, 1801 1810 06D358A00DAAD9C4003B174E /* mac */, … … 2424 2433 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */, 2425 2434 86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */, 2435 0FD82F4B142806A100179C94 /* BitVector.h in Headers */, 2436 0FD82F2B1426CA6D00179C94 /* JettisonedCodeBlocks.h in Headers */, 2426 2437 0FD82EF51423075B00179C94 /* DFGIntrinsic.h in Headers */, 2427 2438 0FD82E85141F3FE300179C94 /* BoundsCheckedPointer.h in Headers */, … … 3114 3125 buildActionMask = 2147483647; 3115 3126 files = ( 3127 0FD82F2C1426CA7400179C94 /* JettisonedCodeBlocks.cpp in Sources */, 3116 3128 0FD82E9014207A5F00179C94 /* ValueProfile.cpp in Sources */, 3117 3129 0FD82E86141F3FF100179C94 /* PredictedType.cpp in Sources */, -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r95676 r95681 1429 1429 , m_symbolTable(symTab) 1430 1430 , m_alternative(alternative) 1431 , m_speculativeSuccessCounter(0) 1432 , m_speculativeFailCounter(0) 1431 1433 , m_optimizationDelayCounter(0) 1434 , m_reoptimizationRetryCounter(0) 1432 1435 { 1433 1436 ASSERT(m_source); … … 1936 1939 return DFG::canCompileFunctionForCall(this); 1937 1940 } 1941 1942 void ProgramCodeBlock::jettison(JSGlobalData& globalData) 1943 { 1944 ASSERT(getJITType() != JITCode::BaselineJIT); 1945 ASSERT(this == replacement()); 1946 static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(globalData); 1947 } 1948 1949 void EvalCodeBlock::jettison(JSGlobalData& globalData) 1950 { 1951 ASSERT(getJITType() != JITCode::BaselineJIT); 1952 ASSERT(this == replacement()); 1953 static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(globalData); 1954 } 1955 1956 void FunctionCodeBlock::jettison(JSGlobalData& globalData) 1957 { 1958 ASSERT(getJITType() != JITCode::BaselineJIT); 1959 ASSERT(this == replacement()); 1960 static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(globalData, m_isConstructor ? CodeForConstruct : CodeForCall); 1961 } 1938 1962 #endif 1939 1963 … … 1975 1999 #endif 1976 2000 1977 if (( double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles >= 0.751978 && ( double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= 0.5)2001 if ((!numberOfNonArgumentValueProfiles || (double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles >= 0.75) 2002 && (!numberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= 0.5)) 1979 2003 return true; 1980 2004 … … 2018 2042 fprintf(stderr, " bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); 2019 2043 } 2044 fprintf(stderr, "SpecialFastCaseProfile for %p:\n", this); 2045 for (unsigned i = 0; i < numberOfSpecialFastCaseProfiles(); ++i) { 2046 RareCaseProfile* profile = specialFastCaseProfile(i); 2047 fprintf(stderr, " bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); 2048 } 2020 2049 } 2021 2050 #endif -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r95676 r95681 32 32 33 33 #include "CompactJITCodeMap.h" 34 #include "DFGOSREntry.h" 34 35 #include "EvalCodeCache.h" 35 36 #include "Instruction.h" … … 334 335 return m_jitCodeMap.get(); 335 336 } 337 338 DFG::OSREntryData* appendDFGOSREntryData(unsigned bytecodeIndex, unsigned machineCodeOffset) 339 { 340 DFG::OSREntryData entry; 341 entry.m_bytecodeIndex = bytecodeIndex; 342 entry.m_machineCodeOffset = machineCodeOffset; 343 m_dfgOSREntry.append(entry); 344 return &m_dfgOSREntry.last(); 345 } 346 unsigned numberOfDFGOSREntries() const { return m_dfgOSREntry.size(); } 347 DFG::OSREntryData* dfgOSREntryData(unsigned i) { return &m_dfgOSREntry[i]; } 348 DFG::OSREntryData* dfgOSREntryDataForBytecodeIndex(unsigned bytecodeIndex) 349 { 350 return binarySearch<DFG::OSREntryData, unsigned, DFG::getOSREntryDataBytecodeIndex>(m_dfgOSREntry.begin(), m_dfgOSREntry.size(), bytecodeIndex); 351 } 336 352 #endif 337 353 … … 361 377 } 362 378 JITCode& getJITCode() { return m_jitCode; } 379 MacroAssemblerCodePtr getJITCodeWithArityCheck() { return m_jitCodeWithArityCheck; } 363 380 JITCode::JITType getJITType() { return m_jitCode.jitType(); } 364 381 ExecutableMemoryHandle* executableMemory() { return getJITCode().getExecutableMemory(); } 365 382 virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0; 383 virtual void jettison(JSGlobalData&) = 0; 366 384 virtual CodeBlock* replacement() = 0; 367 385 virtual bool canCompileWithDFG() = 0; … … 686 704 // as this is called from the CodeBlock constructor. 687 705 706 // When we observe a lot of speculation failures, we trigger a 707 // reoptimization. But each time, we increase the optimization trigger 708 // to avoid thrashing. 709 unsigned reoptimizationRetryCounter() const 710 { 711 ASSERT(m_reoptimizationRetryCounter <= 18); 712 return m_reoptimizationRetryCounter; 713 } 714 715 void countReoptimization() 716 { 717 m_reoptimizationRetryCounter++; 718 if (m_reoptimizationRetryCounter > 18) 719 m_reoptimizationRetryCounter = 18; 720 } 721 688 722 // These functions are provided to support calling 689 // optimizeAfterWarmUp() from JIT-generated code. 723 // optimizeXYZ() methods from JIT-generated code. 724 static int32_t counterValueForOptimizeNextInvocation() 725 { 726 return 0; 727 } 728 690 729 int32_t counterValueForOptimizeAfterWarmUp() 691 730 { 692 return -1000; 731 return -1000 << reoptimizationRetryCounter(); 732 } 733 734 int32_t counterValueForOptimizeAfterLongWarmUp() 735 { 736 return -5000 << reoptimizationRetryCounter(); 693 737 } 694 738 … … 697 741 return &m_executeCounter; 698 742 } 743 744 static ptrdiff_t offsetOfExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_executeCounter); } 745 746 int32_t executeCounter() const { return m_executeCounter; } 747 748 unsigned optimizationDelayCounter() const { return m_optimizationDelayCounter; } 699 749 700 750 // Call this to force the next optimization trigger to fire. This is … … 703 753 void optimizeNextInvocation() 704 754 { 705 m_executeCounter = 0;755 m_executeCounter = counterValueForOptimizeNextInvocation(); 706 756 } 707 757 … … 725 775 { 726 776 m_executeCounter = counterValueForOptimizeAfterWarmUp(); 777 } 778 779 // Call this to force an optimization trigger to fire only after 780 // a lot of warm-up. 781 void optimizeAfterLongWarmUp() 782 { 783 m_executeCounter = counterValueForOptimizeAfterLongWarmUp(); 727 784 } 728 785 … … 747 804 void optimizeSoon() 748 805 { 749 m_executeCounter = -100; 750 } 806 m_executeCounter = -100 << reoptimizationRetryCounter(); 807 } 808 809 // The speculative JIT tracks its success rate, so that we can 810 // decide when to reoptimize. It's interesting to note that these 811 // counters may overflow without any protection. The success 812 // counter will overflow before the fail one does, becuase the 813 // fail one is used as a trigger to reoptimize. So the worst case 814 // is that the success counter overflows and we reoptimize without 815 // needing to. But this is harmless. If a method really did 816 // execute 2^32 times then compiling it again probably won't hurt 817 // anyone. 818 819 void countSpeculationSuccess() 820 { 821 m_speculativeSuccessCounter++; 822 } 823 824 void countSpeculationFailure() 825 { 826 m_speculativeFailCounter++; 827 } 828 829 uint32_t speculativeSuccessCounter() const { return m_speculativeSuccessCounter; } 830 uint32_t speculativeFailCounter() const { return m_speculativeFailCounter; } 831 832 uint32_t* addressOfSpeculativeSuccessCounter() { return &m_speculativeSuccessCounter; } 833 uint32_t* addressOfSpeculativeFailCounter() { return &m_speculativeFailCounter; } 834 835 static ptrdiff_t offsetOfSpeculativeSuccessCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeSuccessCounter); } 836 static ptrdiff_t offsetOfSpeculativeFailCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeFailCounter); } 751 837 752 838 // The amount by which the JIT will increment m_executeCounter. 753 839 static unsigned executeCounterIncrementForLoop() { return 1; } 754 840 static unsigned executeCounterIncrementForReturn() { return 15; } 841 842 // The success/failure ratio we want. 843 unsigned desiredSuccessFailRatio() { return 6; } 844 845 // The number of failures that triggers the use of the ratio. 846 unsigned largeFailCountThreshold() { return 20 << alternative()->reoptimizationRetryCounter(); } 847 unsigned largeFailCountThresholdForLoop() { return 1 << alternative()->reoptimizationRetryCounter(); } 848 849 bool shouldReoptimizeNow() 850 { 851 return desiredSuccessFailRatio() * speculativeFailCounter() >= speculativeSuccessCounter() && speculativeFailCounter() >= largeFailCountThreshold(); 852 } 853 854 bool shouldReoptimizeFromLoopNow() 855 { 856 return desiredSuccessFailRatio() * speculativeFailCounter() >= speculativeSuccessCounter() && speculativeFailCounter() >= largeFailCountThresholdForLoop(); 857 } 755 858 756 859 #if ENABLE(VALUE_PROFILER) … … 759 862 bool shouldOptimizeNow() { return false; } 760 863 #endif 864 865 void reoptimize(JSGlobalData& globalData) 866 { 867 ASSERT(replacement() != this); 868 replacement()->jettison(globalData); 869 countReoptimization(); 870 optimizeAfterWarmUp(); 871 } 761 872 762 873 #if ENABLE(VERBOSE_VALUE_PROFILE) … … 828 939 #if ENABLE(DFG_JIT) 829 940 OwnPtr<CompactJITCodeMap> m_jitCodeMap; 941 Vector<DFG::OSREntryData> m_dfgOSREntry; 830 942 #endif 831 943 #if ENABLE(VALUE_PROFILER) … … 852 964 853 965 int32_t m_executeCounter; 966 uint32_t m_speculativeSuccessCounter; 967 uint32_t m_speculativeFailCounter; 854 968 uint8_t m_optimizationDelayCounter; 969 uint8_t m_reoptimizationRetryCounter; 855 970 856 971 struct RareData { … … 910 1025 protected: 911 1026 virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*); 1027 virtual void jettison(JSGlobalData&); 912 1028 virtual CodeBlock* replacement(); 913 1029 virtual bool canCompileWithDFG(); … … 936 1052 protected: 937 1053 virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*); 1054 virtual void jettison(JSGlobalData&); 938 1055 virtual CodeBlock* replacement(); 939 1056 virtual bool canCompileWithDFG(); … … 963 1080 protected: 964 1081 virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*); 1082 virtual void jettison(JSGlobalData&); 965 1083 virtual CodeBlock* replacement(); 966 1084 virtual bool canCompileWithDFG(); -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r95676 r95681 493 493 PredictedType prediction = profile->computeUpdatedPrediction(); 494 494 #if ENABLE(DFG_DEBUG_VERBOSE) 495 printf("Dynamic [ %u,%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));495 printf("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction)); 496 496 #endif 497 497 return prediction; -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r95273 r95681 409 409 // particularly expensive. 410 410 // 411 // (d) Frequent OSR failures, even those that do not result in the code 412 // running in a hot loop, result in recompilation getting triggered. 413 // 411 414 // To ensure (c), we'd like to set the execute counter to 412 415 // counterValueForOptimizeAfterWarmUp(). This seems like it would endanger … … 416 419 // become non-negative and OSR entry will never be triggered. OSR entry 417 420 // will only happen if a loop gets hot in the old JIT, which does a pretty 418 // good job of ensuring (a) and (b). This heuristic may need to be 419 // rethought in the future, particularly if we support reoptimizing code 420 // with new value profiles gathered from code that did OSR exit. 421 422 store32(Imm32(codeBlock()->alternative()->counterValueForOptimizeAfterWarmUp()), codeBlock()->alternative()->addressOfExecuteCounter()); 421 // good job of ensuring (a) and (b). But that doesn't take care of (d), 422 // since each speculation failure would reset the execute counter. 423 // So we check here if the number of speculation failures is significantly 424 // larger than the number of successes (we want 90% success rate), and if 425 // there have been a large enough number of failures. If so, we set the 426 // counter to 0; otherwise we set the counter to 427 // counterValueForOptimizeAfterWarmUp(). 428 429 move(TrustedImmPtr(codeBlock()), GPRInfo::regT0); 430 431 load32(Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()), GPRInfo::regT2); 432 load32(Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1); 433 add32(Imm32(1), GPRInfo::regT2); 434 add32(Imm32(-1), GPRInfo::regT1); 435 store32(GPRInfo::regT2, Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter())); 436 store32(GPRInfo::regT1, Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter())); 437 438 move(TrustedImmPtr(codeBlock()->alternative()), GPRInfo::regT0); 439 440 Jump fewFails = branch32(BelowOrEqual, GPRInfo::regT2, Imm32(codeBlock()->largeFailCountThreshold())); 441 mul32(Imm32(codeBlock()->desiredSuccessFailRatio()), GPRInfo::regT2, GPRInfo::regT2); 442 443 Jump lowFailRate = branch32(BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1); 444 445 // Reoptimize as soon as possible. 446 store32(Imm32(CodeBlock::counterValueForOptimizeNextInvocation()), Address(GPRInfo::regT0, CodeBlock::offsetOfExecuteCounter())); 447 Jump doneAdjusting = jump(); 448 449 fewFails.link(this); 450 lowFailRate.link(this); 451 452 store32(Imm32(codeBlock()->alternative()->counterValueForOptimizeAfterLongWarmUp()), Address(GPRInfo::regT0, CodeBlock::offsetOfExecuteCounter())); 453 454 doneAdjusting.link(this); 423 455 424 456 // 12) Load the result of the last bytecode operation into regT0. … … 482 514 preserveReturnAddressAfterCall(GPRInfo::regT2); 483 515 emitPutToCallFrameHeader(GPRInfo::regT2, RegisterFile::ReturnPC); 516 517 addPtr(Imm32(1), AbsoluteAddress(codeBlock()->addressOfSpeculativeSuccessCounter())); 484 518 } 485 519 … … 499 533 ASSERT_UNUSED(compiledSpeculative, compiledSpeculative); 500 534 501 #if ENABLE(DFG_OSR_ENTRY)502 m_codeBlock->setJITCodeMap(m_jitCodeMapEncoder.finish());503 #endif504 505 535 linkOSRExits(speculative); 506 536 -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h
r95666 r95681 321 321 void noticeOSREntry(BasicBlock& basicBlock) 322 322 { 323 m_jitCodeMapEncoder.append(basicBlock.bytecodeBegin, differenceBetween(m_startOfCode, label())); 323 #if ENABLE(DFG_OSR_ENTRY) 324 OSREntryData* entry = codeBlock()->appendDFGOSREntryData(basicBlock.bytecodeBegin, differenceBetween(m_startOfCode, label())); 325 326 unsigned lastLiveArgument = 0; 327 unsigned lastLiveLocal = 0; 328 329 for (unsigned i = 0; i < basicBlock.m_arguments.size(); ++i) { 330 if (basicBlock.m_arguments[i].value != NoNode) 331 lastLiveArgument = i; 332 } 333 334 for (unsigned i = 0; i < basicBlock.m_locals.size(); ++i) { 335 if (basicBlock.m_locals[i].value != NoNode) 336 lastLiveLocal = i; 337 } 338 339 if (lastLiveArgument) { 340 entry->m_liveArguments.resize(lastLiveArgument + 1); 341 entry->m_liveArguments.clearAll(); 342 343 for (unsigned i = 0; i <= lastLiveArgument; ++i) { 344 if (basicBlock.m_arguments[i].value != NoNode) 345 entry->m_liveArguments.set(i); 346 } 347 } else 348 entry->m_liveArguments.clearAll(); 349 350 if (lastLiveLocal) { 351 entry->m_liveVariables.resize(lastLiveLocal + 1); 352 entry->m_liveVariables.clearAll(); 353 354 for (unsigned i = 0; i <= lastLiveLocal; ++i) { 355 if (basicBlock.m_locals[i].value != NoNode) 356 entry->m_liveVariables.set(i); 357 } 358 } else 359 entry->m_liveVariables.clearAll(); 360 #else 361 UNUSED_PARAM(basicBlock); 362 #endif 324 363 } 325 364 … … 354 393 // JIT code map for OSR entrypoints. 355 394 Label m_startOfCode; 356 CompactJITCodeMap::Encoder m_jitCodeMapEncoder;357 395 358 396 struct PropertyAccessRecord { -
trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
r95240 r95681 59 59 ASSERT(codeBlock->alternative()); 60 60 ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT); 61 ASSERT(codeBlock->jitCodeMap()); 61 ASSERT(!codeBlock->jitCodeMap()); 62 ASSERT(codeBlock->numberOfDFGOSREntries()); 62 63 63 64 #if ENABLE(JIT_VERBOSE_OSR) … … 67 68 JSGlobalData* globalData = &exec->globalData(); 68 69 CodeBlock* baselineCodeBlock = codeBlock->alternative(); 70 OSREntryData* entry = codeBlock->dfgOSREntryDataForBytecodeIndex(bytecodeIndex); 71 72 ASSERT(entry->m_bytecodeIndex == bytecodeIndex); 69 73 70 74 // The code below checks if it is safe to perform OSR entry. It may find … … 98 102 99 103 for (unsigned i = 1; i < predictions->numberOfArguments(); ++i) { 100 if (!predictionIsValid(globalData, exec->argument(i - 1), predictions->getArgumentPrediction(i))) { 104 if (i < entry->m_liveArguments.size() && entry->m_liveArguments.get(i) 105 && !predictionIsValid(globalData, exec->argument(i - 1), predictions->getArgumentPrediction(i))) { 101 106 #if ENABLE(JIT_VERBOSE_OSR) 102 107 printf(" OSR failed because argument %u is %s, expected %s.\n", i, exec->argument(i - 1).description(), predictionToString(predictions->getArgumentPrediction(i))); … … 106 111 } 107 112 108 // FIXME: we need to know if at an OSR entry, a variable is live. If it isn't109 // then we shouldn't try to verify its prediction.110 111 113 for (unsigned i = 0; i < predictions->numberOfVariables(); ++i) { 112 if (!predictionIsValid(globalData, exec->registers()[i].jsValue(), predictions->getPrediction(i))) { 114 if (i < entry->m_liveVariables.size() && entry->m_liveVariables.get(i) 115 && !predictionIsValid(globalData, exec->registers()[i].jsValue(), predictions->getPrediction(i))) { 113 116 #if ENABLE(JIT_VERBOSE_OSR) 114 117 printf(" OSR failed because variable %u is %s, expected %s.\n", i, exec->registers()[i].jsValue().description(), predictionToString(predictions->getPrediction(i))); … … 140 143 exec->setCodeBlock(codeBlock); 141 144 142 // 4) Find and return the destination machine code address. The DFG stores 143 // the machine code offsets of OSR targets in a CompactJITCodeMap. 144 // Decoding it is not super efficient, but we expect that OSR entry 145 // happens sufficiently rarely, and that OSR entrypoints are sufficiently 146 // few, that this won't hurt throughput. Note that the only real 147 // reason why we use a CompactJITCodeMap is to avoid having to introduce 148 // yet another data structure for mapping between bytecode indices and 149 // machine code offsets. 145 // 4) Find and return the destination machine code address. 150 146 151 CompactJITCodeMap::Decoder decoder(codeBlock->jitCodeMap()); 152 unsigned machineCodeOffset = std::numeric_limits<unsigned>::max(); 153 while (decoder.numberOfEntriesRemaining()) { 154 unsigned currentBytecodeIndex; 155 unsigned currentMachineCodeOffset; 156 decoder.read(currentBytecodeIndex, currentMachineCodeOffset); 157 if (currentBytecodeIndex == bytecodeIndex) { 158 machineCodeOffset = currentMachineCodeOffset; 159 break; 160 } 161 } 162 163 ASSERT(machineCodeOffset != std::numeric_limits<unsigned>::max()); 164 165 void* result = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(codeBlock->getJITCode().start()) + machineCodeOffset); 147 void* result = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(codeBlock->getJITCode().start()) + entry->m_machineCodeOffset); 166 148 167 149 #if ENABLE(JIT_VERBOSE_OSR) -
trunk/Source/JavaScriptCore/dfg/DFGOSREntry.h
r95016 r95681 27 27 #define DFGOSREntry_h 28 28 29 #include <wtf/BitVector.h> 30 29 31 namespace JSC { 30 32 … … 35 37 36 38 #if ENABLE(DFG_JIT) 39 struct OSREntryData { 40 unsigned m_bytecodeIndex; 41 unsigned m_machineCodeOffset; 42 BitVector m_liveArguments; 43 BitVector m_liveVariables; 44 }; 45 46 inline unsigned getOSREntryDataBytecodeIndex(OSREntryData* osrEntryData) 47 { 48 return osrEntryData->m_bytecodeIndex; 49 } 50 37 51 void* prepareOSREntry(ExecState*, CodeBlock*, unsigned bytecodeIndex); 38 52 #else -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r95672 r95681 878 878 } 879 879 880 if (shouldNotSpeculateInteger(node.child1())) { 881 // Do it the safe way. 882 nonSpeculativeValueToInt32(node); 883 break; 884 } 885 880 886 SpeculateIntegerOperand op1(this, node.child1()); 881 887 GPRTemporary result(this, op1); -
trunk/Source/JavaScriptCore/heap/ConservativeRoots.cpp
r88504 r95681 27 27 #include "ConservativeRoots.h" 28 28 29 #include "JettisonedCodeBlocks.h" 30 29 31 namespace JSC { 30 32 … … 32 34 { 33 35 return !((intptr_t)(p) & (sizeof(char*) - 1)); 36 } 37 38 ConservativeRoots::ConservativeRoots(const MarkedBlockSet* blocks) 39 : m_roots(m_inlineRoots) 40 , m_size(0) 41 , m_capacity(inlineCapacity) 42 , m_blocks(blocks) 43 { 44 } 45 46 ConservativeRoots::~ConservativeRoots() 47 { 48 if (m_roots != m_inlineRoots) 49 OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*)); 34 50 } 35 51 … … 45 61 } 46 62 47 inline void ConservativeRoots::add(void* p, TinyBloomFilter filter) 63 class DummyMarkHook { 64 public: 65 void mark(void*) { } 66 }; 67 68 template<typename MarkHook> 69 inline void ConservativeRoots::genericAddPointer(void* p, TinyBloomFilter filter, MarkHook& markHook) 48 70 { 71 markHook.mark(p); 72 49 73 MarkedBlock* candidate = MarkedBlock::blockFor(p); 50 74 if (filter.ruleOut(reinterpret_cast<Bits>(candidate))) { … … 71 95 } 72 96 73 void ConservativeRoots::add(void* begin, void* end) 97 template<typename MarkHook> 98 void ConservativeRoots::genericAddSpan(void* begin, void* end, MarkHook& markHook) 74 99 { 75 100 ASSERT(begin <= end); … … 80 105 TinyBloomFilter filter = m_blocks->filter(); // Make a local copy of filter to show the compiler it won't alias, and can be register-allocated. 81 106 for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it) 82 add(*it, filter); 107 genericAddPointer(*it, filter, markHook); 108 } 109 110 void ConservativeRoots::add(void* begin, void* end) 111 { 112 DummyMarkHook dummyMarkHook; 113 genericAddSpan(begin, end, dummyMarkHook); 114 } 115 116 void ConservativeRoots::add(void* begin, void* end, JettisonedCodeBlocks& jettisonedCodeBlocks) 117 { 118 genericAddSpan(begin, end, jettisonedCodeBlocks); 83 119 } 84 120 -
trunk/Source/JavaScriptCore/heap/ConservativeRoots.h
r88504 r95681 34 34 35 35 class JSCell; 36 class JettisonedCodeBlocks; 36 37 class Heap; 37 38 … … 42 43 43 44 void add(void* begin, void* end); 45 void add(void* begin, void* end, JettisonedCodeBlocks&); 44 46 45 47 size_t size(); … … 50 52 static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*); 51 53 52 void add(void*, TinyBloomFilter); 54 template<typename MarkHook> 55 void genericAddPointer(void*, TinyBloomFilter, MarkHook&); 56 57 template<typename MarkHook> 58 void genericAddSpan(void*, void* end, MarkHook&); 59 53 60 void grow(); 54 61 … … 59 66 JSCell* m_inlineRoots[inlineCapacity]; 60 67 }; 61 62 inline ConservativeRoots::ConservativeRoots(const MarkedBlockSet* blocks)63 : m_roots(m_inlineRoots)64 , m_size(0)65 , m_capacity(inlineCapacity)66 , m_blocks(blocks)67 {68 }69 70 inline ConservativeRoots::~ConservativeRoots()71 {72 if (m_roots != m_inlineRoots)73 OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*));74 }75 68 76 69 inline size_t ConservativeRoots::size() -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r95559 r95681 395 395 } 396 396 397 void Heap::addJettisonedCodeBlock(PassOwnPtr<CodeBlock> codeBlock) 398 { 399 m_jettisonedCodeBlocks.addCodeBlock(codeBlock); 400 } 401 397 402 void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector) 398 403 { … … 457 462 458 463 void* dummy; 459 464 460 465 // We gather conservative roots before clearing mark bits because conservative 461 466 // gathering uses the mark bits to determine whether a reference is valid. … … 464 469 465 470 ConservativeRoots registerFileRoots(&m_objectSpace.blocks()); 466 registerFile().gatherConservativeRoots(registerFileRoots); 471 m_jettisonedCodeBlocks.clearMarks(); 472 registerFile().gatherConservativeRoots(registerFileRoots, m_jettisonedCodeBlocks); 473 m_jettisonedCodeBlocks.deleteUnmarkedCodeBlocks(); 467 474 468 475 clearMarks(); … … 470 477 SlotVisitor& visitor = m_slotVisitor; 471 478 HeapRootVisitor heapRootVisitor(visitor); 472 479 473 480 visitor.append(machineThreadRoots); 474 481 visitor.drain(); … … 493 500 494 501 m_handleStack.visit(heapRootVisitor); 502 visitor.drain(); 503 504 m_jettisonedCodeBlocks.traceCodeBlocks(visitor); 495 505 visitor.drain(); 496 506 -
trunk/Source/JavaScriptCore/heap/Heap.h
r95559 r95681 26 26 #include "HandleHeap.h" 27 27 #include "HandleStack.h" 28 #include "JettisonedCodeBlocks.h" 28 29 #include "MarkedBlock.h" 29 30 #include "MarkedBlockSet.h" … … 99 100 void protect(JSValue); 100 101 bool unprotect(JSValue); // True when the protect count drops to 0. 102 103 void addJettisonedCodeBlock(PassOwnPtr<CodeBlock>); 101 104 102 105 size_t size(); … … 192 195 HandleHeap m_handleHeap; 193 196 HandleStack m_handleStack; 197 JettisonedCodeBlocks m_jettisonedCodeBlocks; 194 198 195 199 bool m_isSafeToCollect; -
trunk/Source/JavaScriptCore/interpreter/RegisterFile.cpp
r89465 r95681 56 56 } 57 57 58 void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JettisonedCodeBlocks& jettisonedCodeBlocks) 59 { 60 conservativeRoots.add(begin(), end(), jettisonedCodeBlocks); 61 } 62 58 63 void RegisterFile::releaseExcessCapacity() 59 64 { -
trunk/Source/JavaScriptCore/interpreter/RegisterFile.h
r89472 r95681 39 39 40 40 class ConservativeRoots; 41 class JettisonedCodeBlocks; 41 42 42 43 class RegisterFile { … … 65 66 66 67 void gatherConservativeRoots(ConservativeRoots&); 68 void gatherConservativeRoots(ConservativeRoots&, JettisonedCodeBlocks&); 67 69 68 70 Register* begin() const { return static_cast<Register*>(m_reservation.base()); } -
trunk/Source/JavaScriptCore/jit/JITStubs.cpp
r95666 r95681 1915 1915 unsigned bytecodeIndex = stackFrame.args[0].int32(); 1916 1916 1917 if (!codeBlock->hasOptimizedReplacement()) { 1917 #if ENABLE(JIT_VERBOSE_OSR) 1918 printf("Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->executeCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter()); 1919 #endif 1920 1921 if (codeBlock->hasOptimizedReplacement()) { 1922 #if ENABLE(JIT_VERBOSE_OSR) 1923 printf("Considering loop OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); 1924 #endif 1925 if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) { 1926 #if ENABLE(JIT_VERBOSE_OSR) 1927 printf("Triggering reoptimization of %p(%p) (in loop).\n", codeBlock, codeBlock->replacement()); 1928 #endif 1929 codeBlock->reoptimize(callFrame->globalData()); 1930 return; 1931 } 1932 } else { 1918 1933 if (!codeBlock->shouldOptimizeNow()) { 1919 1934 #if ENABLE(JIT_VERBOSE_OSR) … … 1953 1968 1954 1969 codeBlock->optimizeSoon(); 1970 optimizedCodeBlock->countSpeculationSuccess(); 1955 1971 STUB_SET_RETURN_ADDRESS(address); 1956 1972 return; … … 1961 1977 #endif 1962 1978 1979 // Count the OSR failure as a speculation failure. If this happens a lot, then 1980 // reoptimize. 1981 optimizedCodeBlock->countSpeculationFailure(); 1982 1983 #if ENABLE(JIT_VERBOSE_OSR) 1984 printf("Encountered loop OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); 1985 #endif 1986 1987 // We are a lot more conservative about triggering reoptimization after OSR failure than 1988 // before it. If we enter the optimize_from_loop trigger with a bucket full of fail 1989 // already, then we really would like to reoptimize immediately. But this case covers 1990 // something else: there weren't many (or any) speculation failures before, but we just 1991 // failed to enter the speculative code because some variable had the wrong value or 1992 // because the OSR code decided for any spurious reason that it did not want to OSR 1993 // right now. So, we only trigger reoptimization only upon the more conservative (non-loop) 1994 // reoptimization trigger. 1995 if (optimizedCodeBlock->shouldReoptimizeNow()) { 1996 #if ENABLE(JIT_VERBOSE_OSR) 1997 printf("Triggering reoptimization of %p(%p) (in loop after OSR fail).\n", codeBlock, codeBlock->replacement()); 1998 #endif 1999 codeBlock->reoptimize(callFrame->globalData()); 2000 return; 2001 } 2002 1963 2003 // OSR failed this time, but it might succeed next time! Let the code run a bit 1964 2004 // longer and then try again. … … 1973 2013 CodeBlock* codeBlock = callFrame->codeBlock(); 1974 2014 1975 if (codeBlock->hasOptimizedReplacement()) 2015 #if ENABLE(JIT_VERBOSE_OSR) 2016 printf("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->executeCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter()); 2017 #endif 2018 2019 if (codeBlock->hasOptimizedReplacement()) { 2020 #if ENABLE(JIT_VERBOSE_OSR) 2021 printf("Returning from old JIT call frame with optimized replacement %p(%p), with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); 2022 #endif 2023 if (codeBlock->replacement()->shouldReoptimizeNow()) { 2024 #if ENABLE(JIT_VERBOSE_OSR) 2025 printf("Triggering reoptimization of %p(%p) (in return).\n", codeBlock, codeBlock->replacement()); 2026 #endif 2027 codeBlock->reoptimize(callFrame->globalData()); 2028 } 2029 1976 2030 return; 2031 } 1977 2032 1978 2033 if (!codeBlock->shouldOptimizeNow()) { -
trunk/Source/JavaScriptCore/runtime/Executable.cpp
r95672 r95681 85 85 #endif 86 86 87 // Utility method used for jettisoning code blocks. 88 template<typename T> 89 static void jettisonCodeBlock(JSGlobalData& globalData, OwnPtr<T>& codeBlock) 90 { 91 ASSERT(codeBlock->getJITType() != JITCode::BaselineJIT); 92 ASSERT(codeBlock->alternative()); 93 OwnPtr<T> codeBlockToJettison = codeBlock.release(); 94 codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative()); 95 codeBlockToJettison->unlinkIncomingCalls(); 96 globalData.heap.addJettisonedCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release())); 97 } 98 87 99 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0 }; 88 100 … … 212 224 } 213 225 226 void EvalExecutable::jettisonOptimizedCode(JSGlobalData& globalData) 227 { 228 jettisonCodeBlock(globalData, m_evalCodeBlock); 229 m_jitCodeForCall = m_evalCodeBlock->getJITCode(); 230 ASSERT(!m_jitCodeForCallWithArityCheck); 231 } 232 214 233 void EvalExecutable::visitChildren(SlotVisitor& visitor) 215 234 { … … 329 348 330 349 return 0; 350 } 351 352 void ProgramExecutable::jettisonOptimizedCode(JSGlobalData& globalData) 353 { 354 jettisonCodeBlock(globalData, m_programCodeBlock); 355 m_jitCodeForCall = m_programCodeBlock->getJITCode(); 356 ASSERT(!m_jitCodeForCallWithArityCheck); 331 357 } 332 358 … … 535 561 } 536 562 563 void FunctionExecutable::jettisonOptimizedCodeForCall(JSGlobalData& globalData) 564 { 565 jettisonCodeBlock(globalData, m_codeBlockForCall); 566 m_jitCodeForCall = m_codeBlockForCall->getJITCode(); 567 m_jitCodeForCallWithArityCheck = m_codeBlockForCall->getJITCodeWithArityCheck(); 568 } 569 570 void FunctionExecutable::jettisonOptimizedCodeForConstruct(JSGlobalData& globalData) 571 { 572 jettisonCodeBlock(globalData, m_codeBlockForConstruct); 573 m_jitCodeForConstruct = m_codeBlockForConstruct->getJITCode(); 574 m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->getJITCodeWithArityCheck(); 575 } 576 537 577 void FunctionExecutable::visitChildren(SlotVisitor& visitor) 538 578 { -
trunk/Source/JavaScriptCore/runtime/Executable.h
r95672 r95681 328 328 329 329 JSObject* compileOptimized(ExecState*, ScopeChainNode*); 330 331 void jettisonOptimizedCode(JSGlobalData&); 330 332 331 333 EvalCodeBlock& generatedBytecode() … … 393 395 394 396 JSObject* compileOptimized(ExecState*, ScopeChainNode*); 397 398 void jettisonOptimizedCode(JSGlobalData&); 395 399 396 400 ProgramCodeBlock& generatedBytecode() … … 476 480 477 481 JSObject* compileOptimizedForCall(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec = 0); 482 483 void jettisonOptimizedCodeForCall(JSGlobalData&); 478 484 479 485 bool isGeneratedForCall() const … … 499 505 500 506 JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec = 0); 507 508 void jettisonOptimizedCodeForConstruct(JSGlobalData&); 501 509 502 510 bool isGeneratedForConstruct() const … … 539 547 } 540 548 549 void jettisonOptimizedCodeFor(JSGlobalData& globalData, CodeSpecializationKind kind) 550 { 551 if (kind == CodeForCall) 552 jettisonOptimizedCodeForCall(globalData); 553 else { 554 ASSERT(kind == CodeForConstruct); 555 jettisonOptimizedCodeForConstruct(globalData); 556 } 557 } 558 541 559 bool isGeneratedFor(CodeSpecializationKind kind) 542 560 {
Note: See TracChangeset
for help on using the changeset viewer.