Changeset 248878 in webkit
- Timestamp:
- Aug 19, 2019, 5:21:29 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 10 added
- 35 edited
- 6 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r248876 r248878 1 2019-08-19 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] OSR entry to Wasm OMG 4 https://bugs.webkit.org/show_bug.cgi?id=200362 5 6 Reviewed by Michael Saboff. 7 8 * wasm/stress/osr-entry-basic.js: Added. 9 (instance.exports.loop): 10 * wasm/stress/osr-entry-many-locals-f32.js: Added. 11 * wasm/stress/osr-entry-many-locals-f64.js: Added. 12 * wasm/stress/osr-entry-many-locals-i32.js: Added. 13 * wasm/stress/osr-entry-many-locals-i64.js: Added. 14 * wasm/stress/osr-entry-many-stacks-f32.js: Added. 15 * wasm/stress/osr-entry-many-stacks-f64.js: Added. 16 * wasm/stress/osr-entry-many-stacks-i32.js: Added. 17 * wasm/stress/osr-entry-many-stacks-i64.js: Added. 18 1 19 2019-08-19 Alexey Shvayka <shvaikalesh@gmail.com> 2 20 -
trunk/Source/JavaScriptCore/ChangeLog
r248876 r248878 1 2019-08-19 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] OSR entry to Wasm OMG 4 https://bugs.webkit.org/show_bug.cgi?id=200362 5 6 Reviewed by Michael Saboff. 7 8 This patch implements Wasm OSR entry mechanism from BBQ tier to OMG tier. 9 We found that one of JetStream2 test heavily relies on OSR entry feature. gcc-loops-wasm consumes 10 most of time in BBQ tier since one of the function takes significantly long time. And since we did 11 not have OSR entry feature, we cannot use OMG function until that BBQ function finishes. 12 13 To implement Wasm OSR feature, we first capture all locals and stacks in the patchpoint to generate 14 the stackmap. Once the threshold is crossed, the patchpoint calls `MacroAssembler::probe` feature to 15 capture whole register context, and C++ runtime function reads stackmap and Probe::Context to perform 16 OSR entry. This patch intentionally makes OSR entry written in C++ runtime side as much as possible 17 to make it easily reusable for the other tiers. For example, we are planning to introduce Wasm interpreter, 18 and it can easily use this tier-up function. Because of this simplicity, this generic implementation can 19 cover both BBQ Air and BBQ B3 tier-up features. So, in the feature, it is possible that we revive BBQ B3, 20 and construct the wasm pipeline like, interpreter->BBQ B3->OMG B3. 21 22 To generate OMG code for OSR entry, we add a new mode OMGForOSREntry, which mimics the FTLForOSREntry. 23 In FTLForOSREntry, we cut unrelated blocks including the usual entry point in DFG tier and later convert 24 graph to SSA. This is possible because DFG is not SSA. On the other hand, B3 is SSA and we cannot take the 25 same thing without a hack. 26 27 This patch introduce a hack: making all wasm locals and stack values B3::Variable for OMGForOSREntry mode. 28 Then, we can cut blocks easily and we can generate the B3 graph without doing reachability analysis from the 29 OSR entry point. B3 will remove unreachable blocks later. 30 31 Tier-up function mimics DFG->FTL OSR entry heuristics and threshold as much as possible. And this patch adjusts 32 the tier-up count threshold to make it close to DFG->FTL ones. Wasm tier-up is now using ExecutionCounter, which 33 is inherited from Wasm::TierUpCount. Since wasm can execute concurrently, the tier-up counter can be racily updated. 34 But this is OK in practice. Even if we see some more tier-up function calls or tier-up function calls are delayed, 35 the critical part is guarded by a lock in tier-up function. 36 37 In iMac Pro, it shows ~4x runtime improvement for gcc-loops-wasm. On iOS device (iPhone XR), we saw ~2x improvement. 38 39 ToT: 40 HashSet-wasm:Score: 24.6pt stdev=4.6% 41 :Time:Geometric: 204ms stdev=4.4% 42 Runtime:Time: 689ms stdev=1.0% 43 Startup:Time: 60.3ms stdev=8.4% 44 gcc-loops-wasm:Score: 8.41pt stdev=6.7% 45 :Time:Geometric: 597ms stdev=6.5% 46 Runtime:Time: 8.509s stdev=0.7% 47 Startup:Time: 42ms stdev=12.4% 48 quicksort-wasm:Score: 347pt stdev=20.9% 49 :Time:Geometric: 15ms stdev=18.6% 50 Runtime:Time: 28.2ms stdev=7.9% 51 Startup:Time: 8.2ms stdev=35.0% 52 richards-wasm:Score: 77.6pt stdev=4.5% 53 :Time:Geometric: 64.6ms stdev=4.4% 54 Runtime:Time: 544ms stdev=3.3% 55 Startup:Time: 7.67ms stdev=6.7% 56 tsf-wasm:Score: 47.9pt stdev=4.5% 57 :Time:Geometric: 104ms stdev=4.8% 58 Runtime:Time: 259ms stdev=4.4% 59 Startup:Time: 42.2ms stdev=8.5% 60 61 Patched: 62 HashSet-wasm:Score: 24.1pt stdev=4.1% 63 :Time:Geometric: 208ms stdev=4.1% 64 Runtime:Time: 684ms stdev=1.1% 65 Startup:Time: 63.2ms stdev=8.1% 66 gcc-loops-wasm:Score: 15.7pt stdev=5.1% 67 :Time:Geometric: 319ms stdev=5.3% 68 Runtime:Time: 2.491s stdev=0.7% 69 Startup:Time: 41ms stdev=11.0% 70 quicksort-wasm:Score: 353pt stdev=13.7% 71 :Time:Geometric: 14ms stdev=12.7% 72 Runtime:Time: 26.2ms stdev=2.9% 73 Startup:Time: 8.0ms stdev=23.7% 74 richards-wasm:Score: 77.4pt stdev=5.3% 75 :Time:Geometric: 64.7ms stdev=5.3% 76 Runtime:Time: 536ms stdev=1.5% 77 Startup:Time: 7.83ms stdev=9.6% 78 tsf-wasm:Score: 47.3pt stdev=5.7% 79 :Time:Geometric: 106ms stdev=6.1% 80 Runtime:Time: 250ms stdev=3.5% 81 Startup:Time: 45ms stdev=13.8% 82 83 * JavaScriptCore.xcodeproj/project.pbxproj: 84 * Sources.txt: 85 * assembler/MacroAssemblerARM64.h: 86 (JSC::MacroAssemblerARM64::branchAdd32): 87 * b3/B3ValueRep.h: 88 * bytecode/CodeBlock.h: 89 * bytecode/ExecutionCounter.cpp: 90 (JSC::applyMemoryUsageHeuristics): 91 (JSC::ExecutionCounter<countingVariant>::setThreshold): 92 * bytecode/ExecutionCounter.h: 93 (JSC::ExecutionCounter::clippedThreshold): 94 * dfg/DFGJITCode.h: 95 * dfg/DFGOperations.cpp: 96 * jit/AssemblyHelpers.h: 97 (JSC::AssemblyHelpers::prologueStackPointerDelta): 98 * runtime/Options.h: 99 * wasm/WasmAirIRGenerator.cpp: 100 (JSC::Wasm::AirIRGenerator::createStack): 101 (JSC::Wasm::AirIRGenerator::emitPatchpoint): 102 (JSC::Wasm::AirIRGenerator::outerLoopIndex const): 103 (JSC::Wasm::AirIRGenerator::AirIRGenerator): 104 (JSC::Wasm::AirIRGenerator::emitEntryTierUpCheck): 105 (JSC::Wasm::AirIRGenerator::emitLoopTierUpCheck): 106 (JSC::Wasm::AirIRGenerator::addLoop): 107 (JSC::Wasm::AirIRGenerator::addElse): 108 (JSC::Wasm::AirIRGenerator::addBranch): 109 (JSC::Wasm::AirIRGenerator::addSwitch): 110 (JSC::Wasm::AirIRGenerator::endBlock): 111 (JSC::Wasm::AirIRGenerator::addEndToUnreachable): 112 (JSC::Wasm::AirIRGenerator::unifyValuesWithBlock): 113 (JSC::Wasm::AirIRGenerator::dump): 114 (JSC::Wasm::AirIRGenerator::emitTierUpCheck): Deleted. 115 * wasm/WasmB3IRGenerator.cpp: 116 (JSC::Wasm::B3IRGenerator::Stack::Stack): 117 (JSC::Wasm::B3IRGenerator::Stack::append): 118 (JSC::Wasm::B3IRGenerator::Stack::takeLast): 119 (JSC::Wasm::B3IRGenerator::Stack::last): 120 (JSC::Wasm::B3IRGenerator::Stack::size const): 121 (JSC::Wasm::B3IRGenerator::Stack::isEmpty const): 122 (JSC::Wasm::B3IRGenerator::Stack::convertToExpressionList): 123 (JSC::Wasm::B3IRGenerator::Stack::at const): 124 (JSC::Wasm::B3IRGenerator::Stack::variableAt const): 125 (JSC::Wasm::B3IRGenerator::Stack::shrink): 126 (JSC::Wasm::B3IRGenerator::Stack::swap): 127 (JSC::Wasm::B3IRGenerator::Stack::dump const): 128 (JSC::Wasm::B3IRGenerator::createStack): 129 (JSC::Wasm::B3IRGenerator::outerLoopIndex const): 130 (JSC::Wasm::B3IRGenerator::B3IRGenerator): 131 (JSC::Wasm::B3IRGenerator::emitEntryTierUpCheck): 132 (JSC::Wasm::B3IRGenerator::emitLoopTierUpCheck): 133 (JSC::Wasm::B3IRGenerator::addLoop): 134 (JSC::Wasm::B3IRGenerator::addElse): 135 (JSC::Wasm::B3IRGenerator::addBranch): 136 (JSC::Wasm::B3IRGenerator::addSwitch): 137 (JSC::Wasm::B3IRGenerator::endBlock): 138 (JSC::Wasm::B3IRGenerator::addEndToUnreachable): 139 (JSC::Wasm::B3IRGenerator::unifyValuesWithBlock): 140 (JSC::Wasm::B3IRGenerator::dump): 141 (JSC::Wasm::parseAndCompile): 142 (JSC::Wasm::B3IRGenerator::emitTierUpCheck): Deleted. 143 (JSC::Wasm::dumpExpressionStack): Deleted. 144 * wasm/WasmB3IRGenerator.h: 145 * wasm/WasmBBQPlan.cpp: 146 (JSC::Wasm::BBQPlan::compileFunctions): 147 * wasm/WasmBBQPlan.h: 148 * wasm/WasmBBQPlanInlines.h: 149 (JSC::Wasm::BBQPlan::initializeCallees): 150 * wasm/WasmCallee.h: 151 * wasm/WasmCodeBlock.cpp: 152 (JSC::Wasm::CodeBlock::CodeBlock): 153 * wasm/WasmCodeBlock.h: 154 (JSC::Wasm::CodeBlock::wasmBBQCalleeFromFunctionIndexSpace): 155 (JSC::Wasm::CodeBlock::entrypointLoadLocationFromFunctionIndexSpace): 156 (JSC::Wasm::CodeBlock::tierUpCount): Deleted. 157 * wasm/WasmCompilationMode.cpp: 158 (JSC::Wasm::makeString): 159 * wasm/WasmCompilationMode.h: 160 * wasm/WasmContext.cpp: Copied from Source/JavaScriptCore/wasm/WasmCompilationMode.cpp. 161 (JSC::Wasm::Context::scratchBufferForSize): 162 * wasm/WasmContext.h: 163 * wasm/WasmContextInlines.h: 164 (JSC::Wasm::Context::tryLoadInstanceFromTLS): 165 * wasm/WasmFunctionParser.h: 166 (JSC::Wasm::FunctionParser<Context>::FunctionParser): 167 (JSC::Wasm::FunctionParser<Context>::parseBody): 168 (JSC::Wasm::FunctionParser<Context>::parseExpression): 169 * wasm/WasmOMGForOSREntryPlan.cpp: Copied from Source/JavaScriptCore/wasm/WasmOMGPlan.cpp. 170 (JSC::Wasm::OMGForOSREntryPlan::OMGForOSREntryPlan): 171 (JSC::Wasm::OMGForOSREntryPlan::work): 172 * wasm/WasmOMGForOSREntryPlan.h: Copied from Source/JavaScriptCore/wasm/WasmOMGPlan.h. 173 * wasm/WasmOMGPlan.cpp: 174 (JSC::Wasm::OMGPlan::work): 175 (JSC::Wasm::OMGPlan::runForIndex): Deleted. 176 * wasm/WasmOMGPlan.h: 177 * wasm/WasmOSREntryData.h: Copied from Source/JavaScriptCore/wasm/WasmContext.h. 178 (JSC::Wasm::OSREntryValue::OSREntryValue): 179 (JSC::Wasm::OSREntryValue::type const): 180 (JSC::Wasm::OSREntryData::OSREntryData): 181 (JSC::Wasm::OSREntryData::functionIndex const): 182 (JSC::Wasm::OSREntryData::loopIndex const): 183 (JSC::Wasm::OSREntryData::values): 184 * wasm/WasmOperations.cpp: Added. 185 (JSC::Wasm::shouldTriggerOMGCompile): 186 (JSC::Wasm::triggerOMGReplacementCompile): 187 (JSC::Wasm::doOSREntry): 188 (JSC::Wasm::triggerOSREntryNow): 189 (JSC::Wasm::triggerTierUpNow): 190 * wasm/WasmOperations.h: Copied from Source/JavaScriptCore/wasm/WasmCompilationMode.h. 191 * wasm/WasmThunks.cpp: 192 (JSC::Wasm::triggerOMGEntryTierUpThunkGenerator): 193 (JSC::Wasm::triggerOMGTierUpThunkGenerator): Deleted. 194 * wasm/WasmThunks.h: 195 * wasm/WasmTierUpCount.cpp: Copied from Source/JavaScriptCore/wasm/WasmCompilationMode.cpp. 196 (JSC::Wasm::TierUpCount::TierUpCount): 197 (JSC::Wasm::TierUpCount::addOSREntryData): 198 * wasm/WasmTierUpCount.h: 199 (JSC::Wasm::TierUpCount::loopIncrement): 200 (JSC::Wasm::TierUpCount::functionEntryIncrement): 201 (JSC::Wasm::TierUpCount::osrEntryTriggers): 202 (JSC::Wasm::TierUpCount::outerLoops): 203 (JSC::Wasm::TierUpCount::getLock): 204 (JSC::Wasm::TierUpCount::optimizeAfterWarmUp): 205 (JSC::Wasm::TierUpCount::checkIfOptimizationThresholdReached): 206 (JSC::Wasm::TierUpCount::dontOptimizeAnytimeSoon): 207 (JSC::Wasm::TierUpCount::optimizeNextInvocation): 208 (JSC::Wasm::TierUpCount::optimizeSoon): 209 (JSC::Wasm::TierUpCount::setOptimizationThresholdBasedOnCompilationResult): 210 (JSC::Wasm::TierUpCount::TierUpCount): Deleted. 211 (JSC::Wasm::TierUpCount::loopDecrement): Deleted. 212 (JSC::Wasm::TierUpCount::functionEntryDecrement): Deleted. 213 (JSC::Wasm::TierUpCount::shouldStartTierUp): Deleted. 214 (JSC::Wasm::TierUpCount::count): Deleted. 215 * wasm/WasmValidate.cpp: 216 (JSC::Wasm::Validate::createStack): 217 (JSC::Wasm::Validate::addLoop): 218 (JSC::Wasm::Validate::addElse): 219 (JSC::Wasm::Validate::checkBranchTarget): 220 (JSC::Wasm::Validate::addBranch): 221 (JSC::Wasm::Validate::addSwitch): 222 (JSC::Wasm::Validate::endBlock): 223 (JSC::Wasm::Validate::unify): 224 (JSC::Wasm::dumpExpressionStack): 225 (JSC::Wasm::Validate::dump): 226 1 227 2019-08-19 Alexey Shvayka <shvaikalesh@gmail.com> 2 228 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r248866 r248878 1811 1811 E35CA1561DBC3A5F00F83516 /* DOMJITAbstractHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1812 1812 E35E03601B7AB43E0073AD2A /* InspectorInstrumentationObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1813 E36B767022F8D61900D09818 /* WasmOMGForOSREntryPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = E36B766F22F8D61100D09818 /* WasmOMGForOSREntryPlan.h */; }; 1813 1814 E36CC9472086314F0051FFD6 /* WasmCreationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = E36CC9462086314F0051FFD6 /* WasmCreationMode.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1814 1815 E3794E761B77EB97005543AE /* ModuleAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3794E741B77EB97005543AE /* ModuleAnalyzer.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1820 1821 E39BF39922A2288B00BD183E /* SymbolTableInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39BF39822A2288B00BD183E /* SymbolTableInlines.h */; }; 1821 1822 E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1823 E39D8B2E23021E2600265852 /* WasmOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D8B2D23021E1E00265852 /* WasmOperations.h */; }; 1822 1824 E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1823 1825 E39EEAF322812450008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E39EEAF22281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h */; }; … … 1831 1833 E3BFD0BC1DAF808E0065DEA2 /* AccessCaseSnippetParams.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BFD0BA1DAF807C0065DEA2 /* AccessCaseSnippetParams.h */; }; 1832 1834 E3C295DD1ED2CBDA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C295DC1ED2CBAA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h */; }; 1835 E3C694B323026877006FBE42 /* WasmOSREntryData.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C694B123026873006FBE42 /* WasmOSREntryData.h */; }; 1833 1836 E3C79CAB1DB9A4DC00D1ECA4 /* DOMJITEffect.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C79CAA1DB9A4D600D1ECA4 /* DOMJITEffect.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1834 1837 E3D239C91B829C1C00BBEF67 /* JSModuleEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D239C71B829C1C00BBEF67 /* JSModuleEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 4903 4906 E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorInstrumentationObject.h; sourceTree = "<group>"; }; 4904 4907 E35E03611B7AB4850073AD2A /* InspectorInstrumentationObject.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = InspectorInstrumentationObject.js; sourceTree = "<group>"; }; 4908 E36B766E22F8D61100D09818 /* WasmOMGForOSREntryPlan.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmOMGForOSREntryPlan.cpp; sourceTree = "<group>"; }; 4909 E36B766F22F8D61100D09818 /* WasmOMGForOSREntryPlan.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmOMGForOSREntryPlan.h; sourceTree = "<group>"; }; 4905 4910 E36CC9462086314F0051FFD6 /* WasmCreationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCreationMode.h; sourceTree = "<group>"; }; 4906 4911 E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleAnalyzer.cpp; sourceTree = "<group>"; }; … … 4917 4922 E38D999B221B789F00D50474 /* JSNonDestructibleProxy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSNonDestructibleProxy.cpp; sourceTree = "<group>"; }; 4918 4923 E39006202208BFC3001019CF /* SubspaceAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubspaceAccess.h; sourceTree = "<group>"; }; 4924 E3915C062309682900CB2561 /* WasmContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmContext.cpp; sourceTree = "<group>"; }; 4919 4925 E393ADD71FE702CC0022D681 /* WeakMapImplInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakMapImplInlines.h; sourceTree = "<group>"; }; 4920 4926 E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodesAnalyzeModule.cpp; sourceTree = "<group>"; }; 4921 4927 E39BF39822A2288B00BD183E /* SymbolTableInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolTableInlines.h; sourceTree = "<group>"; }; 4928 E39D8B2C23021E1E00265852 /* WasmOperations.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmOperations.cpp; sourceTree = "<group>"; }; 4929 E39D8B2D23021E1E00265852 /* WasmOperations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmOperations.h; sourceTree = "<group>"; }; 4922 4930 E39D9D841D39000600667282 /* InterpreterInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterpreterInlines.h; sourceTree = "<group>"; }; 4923 4931 E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleRecord.cpp; sourceTree = "<group>"; }; … … 4940 4948 E3BFD0BA1DAF807C0065DEA2 /* AccessCaseSnippetParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessCaseSnippetParams.h; sourceTree = "<group>"; }; 4941 4949 E3C295DC1ED2CBAA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectPropertyChangeAdaptiveWatchpoint.h; sourceTree = "<group>"; }; 4950 E3C694B123026873006FBE42 /* WasmOSREntryData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmOSREntryData.h; sourceTree = "<group>"; }; 4951 E3C694B223026874006FBE42 /* WasmTierUpCount.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmTierUpCount.cpp; sourceTree = "<group>"; }; 4942 4952 E3C79CAA1DB9A4D600D1ECA4 /* DOMJITEffect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITEffect.h; sourceTree = "<group>"; }; 4943 4953 E3D239C61B829C1C00BBEF67 /* JSModuleEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleEnvironment.cpp; sourceTree = "<group>"; }; … … 6709 6719 E37CFB2D22F27C57009A7B38 /* WasmCompilationMode.cpp */, 6710 6720 E3BD2B7522F275020011765C /* WasmCompilationMode.h */, 6721 E3915C062309682900CB2561 /* WasmContext.cpp */, 6711 6722 AD412B321E7B2E8A008AF157 /* WasmContext.h */, 6712 6723 A27958D7FA1142B0AC9E364D /* WasmContextInlines.h */, … … 6742 6753 ADD8FA441EB3077100DF542F /* WasmNameSectionParser.cpp */, 6743 6754 ADD8FA431EB3077100DF542F /* WasmNameSectionParser.h */, 6755 E36B766E22F8D61100D09818 /* WasmOMGForOSREntryPlan.cpp */, 6756 E36B766F22F8D61100D09818 /* WasmOMGForOSREntryPlan.h */, 6744 6757 5311BD481EA581E500525281 /* WasmOMGPlan.cpp */, 6745 6758 5311BD491EA581E500525281 /* WasmOMGPlan.h */, 6746 6759 53C6FEF01E8AFE0C00B18425 /* WasmOpcodeOrigin.cpp */, 6747 6760 53C6FEEE1E8ADFA900B18425 /* WasmOpcodeOrigin.h */, 6761 E39D8B2C23021E1E00265852 /* WasmOperations.cpp */, 6762 E39D8B2D23021E1E00265852 /* WasmOperations.h */, 6763 E3C694B123026873006FBE42 /* WasmOSREntryData.h */, 6748 6764 ADB6F67C1E15D7500082F384 /* WasmPageCount.cpp */, 6749 6765 79B759731DFA4C600052174C /* WasmPageCount.h */, … … 6763 6779 5250D2CF1E8DA05A0029A932 /* WasmThunks.cpp */, 6764 6780 5250D2D01E8DA05A0029A932 /* WasmThunks.h */, 6781 E3C694B223026874006FBE42 /* WasmTierUpCount.cpp */, 6765 6782 53E9E0AE1EAEC45700FEE251 /* WasmTierUpCount.h */, 6766 6783 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */, … … 10133 10150 AD7B4B2E1FA3E29800C9DF79 /* WasmNameSection.h in Headers */, 10134 10151 ADD8FA461EB3079700DF542F /* WasmNameSectionParser.h in Headers */, 10152 E36B767022F8D61900D09818 /* WasmOMGForOSREntryPlan.h in Headers */, 10135 10153 5311BD4B1EA581E500525281 /* WasmOMGPlan.h in Headers */, 10136 10154 53C6FEEF1E8ADFA900B18425 /* WasmOpcodeOrigin.h in Headers */, 10155 E39D8B2E23021E2600265852 /* WasmOperations.h in Headers */, 10137 10156 53B4BD121F68B32500D2BEA3 /* WasmOps.h in Headers */, 10157 E3C694B323026877006FBE42 /* WasmOSREntryData.h in Headers */, 10138 10158 79B759761DFA4C600052174C /* WasmPageCount.h in Headers */, 10139 10159 53F40E8D1D5901F20099A1B6 /* WasmParser.h in Headers */, -
trunk/Source/JavaScriptCore/Sources.txt
r248187 r248878 1001 1001 wasm/WasmCodeBlock.cpp 1002 1002 wasm/WasmCompilationMode.cpp 1003 wasm/WasmContext.cpp 1003 1004 wasm/WasmEmbedder.h 1004 1005 wasm/WasmFaultSignalHandler.cpp … … 1015 1016 wasm/WasmModuleParser.cpp 1016 1017 wasm/WasmNameSectionParser.cpp 1018 wasm/WasmOMGForOSREntryPlan.cpp 1017 1019 wasm/WasmOMGPlan.cpp 1018 1020 wasm/WasmOpcodeOrigin.cpp 1021 wasm/WasmOperations.cpp 1019 1022 wasm/WasmPageCount.cpp 1020 1023 wasm/WasmPlan.cpp … … 1025 1028 wasm/WasmTable.h 1026 1029 wasm/WasmThunks.cpp 1030 wasm/WasmTierUpCount.cpp 1027 1031 wasm/WasmValidate.cpp 1028 1032 wasm/WasmWorklist.cpp -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
r248686 r248878 2972 2972 } 2973 2973 2974 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, Address address) 2975 { 2976 load32(address, getCachedDataTempRegisterIDAndInvalidate()); 2977 2978 if (isUInt12(imm.m_value)) 2979 m_assembler.add<32, S>(dataTempRegister, dataTempRegister, UInt12(imm.m_value)); 2980 else if (isUInt12(-imm.m_value)) 2981 m_assembler.sub<32, S>(dataTempRegister, dataTempRegister, UInt12(-imm.m_value)); 2982 else { 2983 move(imm, getCachedMemoryTempRegisterIDAndInvalidate()); 2984 m_assembler.add<32, S>(dataTempRegister, dataTempRegister, memoryTempRegister); 2985 } 2986 2987 store32(dataTempRegister, address); 2988 return Jump(makeBranch(cond)); 2989 } 2990 2974 2991 Jump branchAdd64(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) 2975 2992 { -
trunk/Source/JavaScriptCore/b3/B3ValueRep.h
r248710 r248878 48 48 49 49 class ValueRep { 50 WTF_MAKE_FAST_ALLOCATED; 50 51 public: 51 enum Kind {52 enum Kind : uint8_t { 52 53 // As an input representation, this means that B3 can pick any representation. As an output 53 54 // representation, this means that we don't know. This will only arise as an output … … 282 283 283 284 private: 284 Kind m_kind;285 285 union U { 286 286 Reg reg; … … 294 294 } 295 295 } u; 296 Kind m_kind; 296 297 }; 297 298 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r248846 r248878 1060 1060 1061 1061 #define CODEBLOCK_LOG_EVENT(codeBlock, summary, details) \ 1062 (codeBlock->vm()->logEvent(codeBlock, summary, [&] () { return toCString details; })) 1062 do { \ 1063 if (codeBlock) \ 1064 (codeBlock->vm()->logEvent(codeBlock, summary, [&] () { return toCString details; })); \ 1065 } while (0) 1063 1066 1064 1067 -
trunk/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp
r225618 r248878 76 76 double applyMemoryUsageHeuristics(int32_t value, CodeBlock* codeBlock) 77 77 { 78 double multiplier = 1.0; 79 if (codeBlock) { 78 80 #if ENABLE(JIT) 79 double multiplier = 80 ExecutableAllocator::memoryPressureMultiplier( 81 codeBlock->baselineAlternative()->predictedMachineCodeSize()); 82 #else 83 // This code path will probably not be taken, but if it is, we fake it. 84 double multiplier = 1.0; 85 UNUSED_PARAM(codeBlock); 81 multiplier = 82 ExecutableAllocator::memoryPressureMultiplier( 83 codeBlock->baselineAlternative()->predictedMachineCodeSize()); 86 84 #endif 85 } 87 86 ASSERT(multiplier >= 1.0); 88 87 return multiplier * value; … … 162 161 } 163 162 164 threshold = clippedThreshold(codeBlock ->globalObject(), threshold);163 threshold = clippedThreshold(codeBlock ? codeBlock->globalObject() : nullptr, threshold); 165 164 166 165 m_counter = static_cast<int32_t>(-threshold); -
trunk/Source/JavaScriptCore/bytecode/ExecutionCounter.h
r248546 r248878 90 90 { 91 91 int32_t maxThreshold; 92 if (Options::randomizeExecutionCountsBetweenCheckpoints() )92 if (Options::randomizeExecutionCountsBetweenCheckpoints() && globalObject) 93 93 maxThreshold = globalObject->weakRandomInteger() % maximumExecutionCountsBetweenCheckpoints(); 94 94 else -
trunk/Source/JavaScriptCore/dfg/DFGJITCode.h
r245017 r248878 168 168 HashMap<unsigned, TriggerReason> tierUpEntryTriggers; 169 169 170 // Set of bytecode that were the target of a TierUp operation.171 HashSet<unsigned, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> tierUpEntrySeen;172 173 170 WriteBarrier<CodeBlock> m_osrEntryBlock; 174 171 unsigned osrEntryRetry; -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r248798 r248878 3541 3541 3542 3542 JITCode* jitCode = codeBlock->jitCode()->dfg(); 3543 jitCode->tierUpEntrySeen.add(bytecodeIndex);3544 3543 3545 3544 if (Options::verboseOSR()) { -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r247101 r248878 483 483 484 484 #if CPU(X86_64) || CPU(X86) 485 static size_t prologueStackPointerDelta()485 static constexpr size_t prologueStackPointerDelta() 486 486 { 487 487 // Prologue only saves the framePointerRegister … … 523 523 524 524 #if CPU(ARM_THUMB2) || CPU(ARM64) 525 static size_t prologueStackPointerDelta()525 static constexpr size_t prologueStackPointerDelta() 526 526 { 527 527 // Prologue saves the framePointerRegister and linkRegister … … 564 564 565 565 #if CPU(MIPS) 566 static size_t prologueStackPointerDelta()566 static constexpr size_t prologueStackPointerDelta() 567 567 { 568 568 // Prologue saves the framePointerRegister and returnAddressRegister -
trunk/Source/JavaScriptCore/runtime/Options.h
r248829 r248878 482 482 \ 483 483 v(bool, useBBQTierUpChecks, true, Normal, "Enables tier up checks for our BBQ code.") \ 484 v(unsigned, webAssemblyOMGTierUpCount, 5000, Normal, "The countdown before we tier up a function to OMG.") \ 485 v(unsigned, webAssemblyLoopDecrement, 15, Normal, "The amount the tier up countdown is decremented on each loop backedge.") \ 486 v(unsigned, webAssemblyFunctionEntryDecrement, 1, Normal, "The amount the tier up countdown is decremented on each function entry.") \ 484 v(bool, useWebAssemblyOSR, true, Normal, nullptr) \ 485 v(int32, thresholdForOMGOptimizeAfterWarmUp, 50000, Normal, "The count before we tier up a function to OMG.") \ 486 v(int32, thresholdForOMGOptimizeSoon, 500, Normal, nullptr) \ 487 v(int32, omgTierUpCounterIncrementForLoop, 1, Normal, "The amount the tier up counter is incremented on each loop backedge.") \ 488 v(int32, omgTierUpCounterIncrementForEntry, 15, Normal, "The amount the tier up counter is incremented on each function entry.") \ 487 489 /* FIXME: enable fast memories on iOS and pre-allocate them. https://bugs.webkit.org/show_bug.cgi?id=170774 */ \ 488 490 v(bool, useWebAssemblyFastMemory, !isIOS(), Normal, "If true, we will try to use a 32-bit address space with a signal handler to bounds check wasm memory.") \ -
trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp
r248846 r248878 53 53 #include "WasmMemory.h" 54 54 #include "WasmOMGPlan.h" 55 #include "WasmOSREntryData.h" 55 56 #include "WasmOpcodeOrigin.h" 57 #include "WasmOperations.h" 56 58 #include "WasmSignatureInlines.h" 57 59 #include "WasmThunks.h" … … 204 206 using ControlType = ControlData; 205 207 using ExpressionList = Vector<ExpressionType, 1>; 208 using Stack = ExpressionList; 206 209 using ResultList = ControlData::ResultList; 207 210 using ControlEntry = FunctionParser<AirIRGenerator>::ControlEntry; 208 211 209 212 static ExpressionType emptyExpression() { return { }; }; 213 Stack createStack() { return Stack(); } 210 214 211 215 using ErrorType = String; … … 268 272 ControlData WARN_UNUSED_RETURN addTopLevel(Type signature); 269 273 ControlData WARN_UNUSED_RETURN addBlock(Type signature); 270 ControlData WARN_UNUSED_RETURN addLoop(Type signature );274 ControlData WARN_UNUSED_RETURN addLoop(Type signature, const Stack&, uint32_t loopIndex); 271 275 PartialResult WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature, ControlData& result); 272 PartialResult WARN_UNUSED_RETURN addElse(ControlData&, const ExpressionList&);276 PartialResult WARN_UNUSED_RETURN addElse(ControlData&, const Stack&); 273 277 PartialResult WARN_UNUSED_RETURN addElseToUnreachable(ControlData&); 274 278 275 279 PartialResult WARN_UNUSED_RETURN addReturn(const ControlData&, const ExpressionList& returnValues); 276 PartialResult WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const ExpressionList& returnValues);277 PartialResult WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTargets, const ExpressionList& expressionStack);278 PartialResult WARN_UNUSED_RETURN endBlock(ControlEntry&, ExpressionList& expressionStack);280 PartialResult WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const Stack& returnValues); 281 PartialResult WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTargets, const Stack& expressionStack); 282 PartialResult WARN_UNUSED_RETURN endBlock(ControlEntry&, Stack& expressionStack); 279 283 PartialResult WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&); 280 284 … … 289 293 PartialResult addFloatingPointBinOp(Type, B3::Air::Opcode, ExpressionType lhs, ExpressionType rhs, ExpressionType& result); 290 294 291 void dump(const Vector<ControlEntry>& controlStack, const ExpressionList* expressionStack);295 void dump(const Vector<ControlEntry>& controlStack, const Stack* expressionStack); 292 296 void setParser(FunctionParser<AirIRGenerator>* parser) { m_parser = parser; }; 293 297 … … 446 450 patch->append(dummyValue, tmp.rep); 447 451 switch (tmp.rep.kind()) { 452 case B3::ValueRep::ColdAny: // B3::Value propagates ColdAny information and later Air will allocate appropriate stack. 448 453 case B3::ValueRep::SomeRegister: 449 454 inst.args.append(tmp.tmp); … … 579 584 void emitThrowException(CCallHelpers&, ExceptionType); 580 585 581 void emitTierUpCheck(uint32_t decrementCount, B3::Origin); 586 void emitEntryTierUpCheck(int32_t incrementCount, B3::Origin); 587 void emitLoopTierUpCheck(int32_t incrementCount, const Stack&, uint32_t, uint32_t, B3::Origin); 582 588 583 589 void emitWriteBarrierForJSWrapper(); … … 587 593 588 594 void unify(const ExpressionType& dst, const ExpressionType& source); 589 void unifyValuesWithBlock(const ExpressionList& resultStack, const ResultList& stack);595 void unifyValuesWithBlock(const Stack& resultStack, const ResultList& stack); 590 596 591 597 template <typename IntType> … … 606 612 607 613 B3::Origin origin(); 614 615 uint32_t outerLoopIndex() const 616 { 617 if (m_outerLoops.isEmpty()) 618 return UINT32_MAX; 619 return m_outerLoops.last(); 620 } 608 621 609 622 FunctionParser<AirIRGenerator>* m_parser { nullptr }; … … 611 624 const MemoryMode m_mode { MemoryMode::BoundsChecking }; 612 625 const unsigned m_functionIndex { UINT_MAX }; 613 constTierUpCount* m_tierUp { nullptr };626 TierUpCount* m_tierUp { nullptr }; 614 627 615 628 B3::Procedure& m_proc; 616 629 Code& m_code; 630 Vector<uint32_t> m_outerLoops; 617 631 BasicBlock* m_currentBlock { nullptr }; 618 632 BasicBlock* m_rootBlock { nullptr }; … … 828 842 }); 829 843 830 emit TierUpCheck(TierUpCount::functionEntryDecrement(), B3::Origin());844 emitEntryTierUpCheck(TierUpCount::functionEntryIncrement(), B3::Origin()); 831 845 } 832 846 … … 1579 1593 } 1580 1594 1581 void AirIRGenerator::emit TierUpCheck(uint32_t decrementCount, B3::Origin origin)1595 void AirIRGenerator::emitEntryTierUpCheck(int32_t incrementCount, B3::Origin origin) 1582 1596 { 1583 1597 UNUSED_PARAM(origin); … … 1587 1601 1588 1602 auto countdownPtr = g64(); 1589 auto oldCountdown = g64(); 1590 auto newCountdown = g64(); 1591 1592 append(Move, Arg::bigImm(reinterpret_cast<uint64_t>(m_tierUp)), countdownPtr); 1593 append(Move32, Arg::addr(countdownPtr), oldCountdown); 1594 1595 RELEASE_ASSERT(Arg::isValidImmForm(decrementCount)); 1596 append(Move32, oldCountdown, newCountdown); 1597 append(Sub32, Arg::imm(decrementCount), newCountdown); 1598 append(Move32, newCountdown, Arg::addr(countdownPtr)); 1603 1604 append(Move, Arg::bigImm(reinterpret_cast<uint64_t>(&m_tierUp->m_counter)), countdownPtr); 1599 1605 1600 1606 auto* patch = addPatchpoint(B3::Void); … … 1603 1609 effects.writes = B3::HeapRange::top(); 1604 1610 patch->effects = effects; 1611 patch->clobber(RegisterSet::macroScratchRegisters()); 1605 1612 1606 1613 patch->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) { 1607 MacroAssembler::Jump tierUp = jit.branch32(MacroAssembler::Above, params[0].gpr(), params[1].gpr()); 1608 MacroAssembler::Label tierUpResume = jit.label(); 1614 AllowMacroScratchRegisterUsage allowScratch(jit); 1615 1616 CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr())); 1617 CCallHelpers::Label tierUpResume = jit.label(); 1609 1618 1610 1619 params.addLatePath([=] (CCallHelpers& jit) { … … 1623 1632 1624 1633 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 1625 MacroAssembler::repatchNearCall(linkBuffer.locationOfNearCall<NoPtrTag>(call), CodeLocationLabel<JITThunkPtrTag>(Thunks::singleton().stub(triggerOMGTierUpThunkGenerator).code())); 1626 1634 MacroAssembler::repatchNearCall(linkBuffer.locationOfNearCall<NoPtrTag>(call), CodeLocationLabel<JITThunkPtrTag>(Thunks::singleton().stub(triggerOMGEntryTierUpThunkGenerator).code())); 1627 1635 }); 1628 1636 }); 1629 1637 }); 1630 1638 1631 emitPatchpoint(patch, Tmp(), newCountdown, oldCountdown); 1632 } 1633 1634 AirIRGenerator::ControlData AirIRGenerator::addLoop(Type signature) 1639 emitPatchpoint(patch, Tmp(), countdownPtr); 1640 } 1641 1642 void AirIRGenerator::emitLoopTierUpCheck(int32_t incrementCount, const Stack& expressionStack, uint32_t loopIndex, uint32_t outerLoopIndex, B3::Origin origin) 1643 { 1644 UNUSED_PARAM(origin); 1645 1646 if (!m_tierUp) 1647 return; 1648 1649 ASSERT(m_tierUp->osrEntryTriggers().size() == loopIndex); 1650 m_tierUp->osrEntryTriggers().append(TierUpCount::TriggerReason::DontTrigger); 1651 m_tierUp->outerLoops().append(outerLoopIndex); 1652 1653 auto countdownPtr = g64(); 1654 1655 append(Move, Arg::bigImm(reinterpret_cast<uint64_t>(&m_tierUp->m_counter)), countdownPtr); 1656 1657 auto* patch = addPatchpoint(B3::Void); 1658 B3::Effects effects = B3::Effects::none(); 1659 effects.reads = B3::HeapRange::top(); 1660 effects.writes = B3::HeapRange::top(); 1661 effects.exitsSideways = true; 1662 patch->effects = effects; 1663 1664 patch->clobber(RegisterSet::macroScratchRegisters()); 1665 RegisterSet clobberLate; 1666 clobberLate.add(GPRInfo::argumentGPR0); 1667 patch->clobberLate(clobberLate); 1668 1669 Vector<ConstrainedTmp> patchArgs; 1670 patchArgs.append(countdownPtr); 1671 1672 Vector<B3::Type> types; 1673 for (auto& local : m_locals) { 1674 patchArgs.append(ConstrainedTmp(local, B3::ValueRep::ColdAny)); 1675 types.append(toB3Type(local.type())); 1676 } 1677 for (auto& expression : expressionStack) { 1678 patchArgs.append(ConstrainedTmp(expression, B3::ValueRep::ColdAny)); 1679 types.append(toB3Type(expression.type())); 1680 } 1681 1682 TierUpCount::TriggerReason* forceEntryTrigger = &(m_tierUp->osrEntryTriggers().last()); 1683 static_assert(!static_cast<uint8_t>(TierUpCount::TriggerReason::DontTrigger), "the JIT code assumes non-zero means 'enter'"); 1684 static_assert(sizeof(TierUpCount::TriggerReason) == 1, "branchTest8 assumes this size"); 1685 patch->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) { 1686 AllowMacroScratchRegisterUsage allowScratch(jit); 1687 CCallHelpers::Jump forceOSREntry = jit.branchTest8(CCallHelpers::NonZero, CCallHelpers::AbsoluteAddress(forceEntryTrigger)); 1688 CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr())); 1689 MacroAssembler::Label tierUpResume = jit.label(); 1690 1691 OSREntryData& osrEntryData = m_tierUp->addOSREntryData(m_functionIndex, loopIndex); 1692 for (unsigned index = 0; index < types.size(); ++index) 1693 osrEntryData.values().constructAndAppend(params[index + 1], types[index]); 1694 OSREntryData* osrEntryDataPtr = &osrEntryData; 1695 1696 params.addLatePath([=] (CCallHelpers& jit) { 1697 AllowMacroScratchRegisterUsage allowScratch(jit); 1698 forceOSREntry.link(&jit); 1699 tierUp.link(&jit); 1700 1701 jit.probe(triggerOSREntryNow, osrEntryDataPtr); 1702 jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::argumentGPR0).linkTo(tierUpResume, &jit); 1703 jit.farJump(GPRInfo::argumentGPR1, WasmEntryPtrTag); 1704 }); 1705 }); 1706 1707 emitPatchpoint(patch, Tmp(), WTFMove(patchArgs)); 1708 } 1709 1710 AirIRGenerator::ControlData AirIRGenerator::addLoop(Type signature, const Stack& expressionStack, uint32_t loopIndex) 1635 1711 { 1636 1712 BasicBlock* body = m_code.addBlock(); … … 1640 1716 m_currentBlock->setSuccessors(body); 1641 1717 1718 uint32_t outerLoopIndex = this->outerLoopIndex(); 1719 m_outerLoops.append(loopIndex); 1642 1720 m_currentBlock = body; 1643 emit TierUpCheck(TierUpCount::loopDecrement(), origin());1721 emitLoopTierUpCheck(TierUpCount::loopIncrement(), expressionStack, loopIndex, outerLoopIndex, origin()); 1644 1722 1645 1723 return ControlData(origin(), signature, tmpForType(signature), BlockType::Loop, continuation, body); … … 1671 1749 } 1672 1750 1673 auto AirIRGenerator::addElse(ControlData& data, const ExpressionList& currentStack) -> PartialResult1751 auto AirIRGenerator::addElse(ControlData& data, const Stack& currentStack) -> PartialResult 1674 1752 { 1675 1753 unifyValuesWithBlock(currentStack, data.result); … … 1722 1800 // NOTE: All branches in Wasm are on 32-bit ints 1723 1801 1724 auto AirIRGenerator::addBranch(ControlData& data, ExpressionType condition, const ExpressionList& returnValues) -> PartialResult1802 auto AirIRGenerator::addBranch(ControlData& data, ExpressionType condition, const Stack& returnValues) -> PartialResult 1725 1803 { 1726 1804 unifyValuesWithBlock(returnValues, data.resultForBranch()); … … 1740 1818 } 1741 1819 1742 auto AirIRGenerator::addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const ExpressionList& expressionStack) -> PartialResult1820 auto AirIRGenerator::addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const Stack& expressionStack) -> PartialResult 1743 1821 { 1744 1822 auto& successors = m_currentBlock->successors(); … … 1803 1881 } 1804 1882 1805 auto AirIRGenerator::endBlock(ControlEntry& entry, ExpressionList& expressionStack) -> PartialResult1883 auto AirIRGenerator::endBlock(ControlEntry& entry, Stack& expressionStack) -> PartialResult 1806 1884 { 1807 1885 ControlData& data = entry.controlData; … … 1824 1902 data.special->setSuccessors(m_currentBlock); 1825 1903 } 1904 1905 if (data.type() == BlockType::Loop) 1906 m_outerLoops.removeLast(); 1826 1907 1827 1908 for (const auto& result : data.result) … … 2120 2201 } 2121 2202 2122 void AirIRGenerator::unifyValuesWithBlock(const ExpressionList& resultStack, const ResultList& result)2203 void AirIRGenerator::unifyValuesWithBlock(const Stack& resultStack, const ResultList& result) 2123 2204 { 2124 2205 ASSERT(result.size() <= resultStack.size()); … … 2128 2209 } 2129 2210 2130 void AirIRGenerator::dump(const Vector<ControlEntry>&, const ExpressionList*)2211 void AirIRGenerator::dump(const Vector<ControlEntry>&, const Stack*) 2131 2212 { 2132 2213 } -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
r248846 r248878 60 60 #include "WasmMemory.h" 61 61 #include "WasmOMGPlan.h" 62 #include "WasmOSREntryData.h" 62 63 #include "WasmOpcodeOrigin.h" 64 #include "WasmOperations.h" 63 65 #include "WasmSignatureInlines.h" 64 66 #include "WasmThunks.h" … … 158 160 159 161 typedef Value* ExpressionType; 160 typedef ControlData ControlType;161 162 typedef Vector<ExpressionType, 1> ExpressionList; 162 typedef ControlData::ResultList ResultList; 163 typedef FunctionParser<B3IRGenerator>::ControlEntry ControlEntry; 163 164 friend class Stack; 165 class Stack { 166 public: 167 Stack(B3IRGenerator* generator) 168 : m_generator(generator) 169 { 170 } 171 172 void append(ExpressionType expression) 173 { 174 if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) { 175 Variable* variable = m_generator->m_proc.addVariable(expression->type()); 176 m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, Set, m_generator->origin(), variable, expression); 177 m_stack.append(variable); 178 return; 179 } 180 m_data.append(expression); 181 } 182 183 ExpressionType takeLast() 184 { 185 if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) 186 return m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, B3::Get, m_generator->origin(), m_stack.takeLast()); 187 return m_data.takeLast(); 188 } 189 190 ExpressionType last() 191 { 192 if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) 193 return m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, B3::Get, m_generator->origin(), m_stack.last()); 194 return m_data.last(); 195 } 196 197 unsigned size() const 198 { 199 if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) 200 return m_stack.size(); 201 return m_data.size(); 202 } 203 bool isEmpty() const { return size() == 0; } 204 205 ExpressionList convertToExpressionList() 206 { 207 if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) { 208 ExpressionList results; 209 for (unsigned i = 0; i < m_stack.size(); ++i) 210 results.append(at(i)); 211 return results; 212 } 213 return m_data; 214 } 215 216 ExpressionType at(unsigned i) const 217 { 218 if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) 219 return m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, B3::Get, m_generator->origin(), m_stack.at(i)); 220 return m_data.at(i); 221 } 222 223 Variable* variableAt(unsigned i) const 224 { 225 if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) 226 return m_stack.at(i); 227 return nullptr; 228 } 229 230 void shrink(unsigned i) 231 { 232 if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) { 233 m_stack.shrink(i); 234 return; 235 } 236 m_data.shrink(i); 237 } 238 239 void swap(Stack& stack) 240 { 241 std::swap(m_generator, stack.m_generator); 242 m_data.swap(stack.m_data); 243 m_stack.swap(stack.m_stack); 244 } 245 246 void dump() const 247 { 248 CommaPrinter comma(", ", ""); 249 dataLog(comma, "ExpressionStack:"); 250 if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) { 251 for (const auto& variable : m_stack) 252 dataLog(comma, *variable); 253 return; 254 } 255 for (const auto& expression : m_data) 256 dataLog(comma, *expression); 257 } 258 259 private: 260 B3IRGenerator* m_generator { nullptr }; 261 ExpressionList m_data; 262 Vector<Variable*> m_stack; 263 }; 264 Stack createStack() { return Stack(this); } 265 266 using ControlType = ControlData; 267 using ResultList = ControlData::ResultList; 268 using ControlEntry = FunctionParser<B3IRGenerator>::ControlEntry; 164 269 165 270 static constexpr ExpressionType emptyExpression() { return nullptr; } … … 180 285 } while (0) 181 286 182 B3IRGenerator(const ModuleInformation&, Procedure&, InternalFunction*, Vector<UnlinkedWasmToWasmCall>&, MemoryMode, CompilationMode, unsigned functionIndex, TierUpCount*, ThrowWasmException);287 B3IRGenerator(const ModuleInformation&, Procedure&, InternalFunction*, Vector<UnlinkedWasmToWasmCall>&, unsigned& osrEntryScratchBufferSize, MemoryMode, CompilationMode, unsigned functionIndex, unsigned loopIndexForOSREntry, TierUpCount*, ThrowWasmException); 183 288 184 289 PartialResult WARN_UNUSED_RETURN addArguments(const Signature&); … … 220 325 ControlData WARN_UNUSED_RETURN addTopLevel(Type signature); 221 326 ControlData WARN_UNUSED_RETURN addBlock(Type signature); 222 ControlData WARN_UNUSED_RETURN addLoop(Type signature );327 ControlData WARN_UNUSED_RETURN addLoop(Type signature, const Stack&, uint32_t); 223 328 PartialResult WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature, ControlData& result); 224 PartialResult WARN_UNUSED_RETURN addElse(ControlData&, const ExpressionList&);329 PartialResult WARN_UNUSED_RETURN addElse(ControlData&, const Stack&); 225 330 PartialResult WARN_UNUSED_RETURN addElseToUnreachable(ControlData&); 226 331 227 332 PartialResult WARN_UNUSED_RETURN addReturn(const ControlData&, const ExpressionList& returnValues); 228 PartialResult WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const ExpressionList& returnValues);229 PartialResult WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTargets, const ExpressionList& expressionStack);230 PartialResult WARN_UNUSED_RETURN endBlock(ControlEntry&, ExpressionList& expressionStack);333 PartialResult WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const Stack& returnValues); 334 PartialResult WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTargets, const Stack& expressionStack); 335 PartialResult WARN_UNUSED_RETURN endBlock(ControlEntry&, Stack& expressionStack); 231 336 PartialResult WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&); 232 337 … … 236 341 PartialResult WARN_UNUSED_RETURN addUnreachable(); 237 342 238 void dump(const Vector<ControlEntry>& controlStack, const ExpressionList* expressionStack);343 void dump(const Vector<ControlEntry>& controlStack, const Stack* expressionStack); 239 344 void setParser(FunctionParser<B3IRGenerator>* parser) { m_parser = parser; }; 240 345 … … 247 352 void emitExceptionCheck(CCallHelpers&, ExceptionType); 248 353 249 void emitTierUpCheck(uint32_t decrementCount, Origin); 354 void emitEntryTierUpCheck(int32_t incrementCount, B3::Origin); 355 void emitLoopTierUpCheck(int32_t incrementCount, const Stack&, uint32_t, uint32_t, B3::Origin); 250 356 251 357 void emitWriteBarrierForJSWrapper(); … … 256 362 257 363 void unify(const ExpressionType phi, const ExpressionType source); 258 void unifyValuesWithBlock(const ExpressionList& resultStack, const ResultList& stack);364 void unifyValuesWithBlock(const Stack& resultStack, const ResultList& stack); 259 365 260 366 void emitChecksForModOrDiv(B3::Opcode, ExpressionType left, ExpressionType right); … … 267 373 268 374 Origin origin(); 375 376 uint32_t outerLoopIndex() const 377 { 378 if (m_outerLoops.isEmpty()) 379 return UINT32_MAX; 380 return m_outerLoops.last(); 381 } 269 382 270 383 FunctionParser<B3IRGenerator>* m_parser { nullptr }; … … 273 386 const CompilationMode m_compilationMode { CompilationMode::BBQMode }; 274 387 const unsigned m_functionIndex { UINT_MAX }; 275 const TierUpCount* m_tierUp { nullptr }; 388 const unsigned m_loopIndexForOSREntry { UINT_MAX }; 389 TierUpCount* m_tierUp { nullptr }; 276 390 277 391 Procedure& m_proc; 392 BasicBlock* m_rootBlock { nullptr }; 278 393 BasicBlock* m_currentBlock { nullptr }; 394 Vector<uint32_t> m_outerLoops; 279 395 Vector<Variable*> m_locals; 280 396 Vector<UnlinkedWasmToWasmCall>& m_unlinkedWasmToWasmCalls; // List each call site and the function index whose address it should be patched with. 397 unsigned& m_osrEntryScratchBufferSize; 281 398 HashMap<ValueKey, Value*> m_constantPool; 282 399 InsertionSet m_constantInsertionValues; … … 338 455 } 339 456 340 B3IRGenerator::B3IRGenerator(const ModuleInformation& info, Procedure& procedure, InternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, MemoryMode mode, CompilationMode compilationMode, unsigned functionIndex, TierUpCount* tierUp, ThrowWasmException throwWasmException)457 B3IRGenerator::B3IRGenerator(const ModuleInformation& info, Procedure& procedure, InternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, unsigned& osrEntryScratchBufferSize, MemoryMode mode, CompilationMode compilationMode, unsigned functionIndex, unsigned loopIndexForOSREntry, TierUpCount* tierUp, ThrowWasmException throwWasmException) 341 458 : m_info(info) 342 459 , m_mode(mode) 343 460 , m_compilationMode(compilationMode) 344 461 , m_functionIndex(functionIndex) 462 , m_loopIndexForOSREntry(loopIndexForOSREntry) 345 463 , m_tierUp(tierUp) 346 464 , m_proc(procedure) 347 465 , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls) 466 , m_osrEntryScratchBufferSize(osrEntryScratchBufferSize) 348 467 , m_constantInsertionValues(m_proc) 349 468 , m_numImportFunctions(info.importFunctionCount()) 350 469 { 351 m_currentBlock = m_proc.addBlock(); 470 m_rootBlock = m_proc.addBlock(); 471 m_currentBlock = m_rootBlock; 352 472 353 473 // FIXME we don't really need to pin registers here if there's no memory. It makes wasm -> wasm thunks simpler for now. https://bugs.webkit.org/show_bug.cgi?id=166623 … … 465 585 } 466 586 467 emitTierUpCheck(TierUpCount::functionEntryDecrement(), Origin()); 587 emitEntryTierUpCheck(TierUpCount::functionEntryIncrement(), Origin()); 588 589 if (m_compilationMode == CompilationMode::OMGForOSREntryMode) 590 m_currentBlock = m_proc.addBlock(); 468 591 } 469 592 … … 1068 1191 } 1069 1192 1070 void B3IRGenerator::emit TierUpCheck(uint32_t decrementCount, Origin origin)1193 void B3IRGenerator::emitEntryTierUpCheck(int32_t incrementCount, Origin origin) 1071 1194 { 1072 1195 if (!m_tierUp) … … 1074 1197 1075 1198 ASSERT(m_tierUp); 1076 Value* countDownLocation = constant(pointerType(), reinterpret_cast<uint64_t>(m_tierUp), origin); 1077 Value* oldCountDown = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, countDownLocation); 1078 Value* newCountDown = m_currentBlock->appendNew<Value>(m_proc, Sub, origin, oldCountDown, constant(Int32, decrementCount, origin)); 1079 m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin, newCountDown, countDownLocation); 1199 Value* countDownLocation = constant(pointerType(), reinterpret_cast<uint64_t>(&m_tierUp->m_counter), origin); 1080 1200 1081 1201 PatchpointValue* patch = m_currentBlock->appendNew<PatchpointValue>(m_proc, B3::Void, origin); … … 1085 1205 effects.writes = B3::HeapRange::top(); 1086 1206 patch->effects = effects; 1087 1088 patch->append(newCountDown, ValueRep::SomeRegister); 1089 patch->append( oldCountDown, ValueRep::SomeRegister);1207 patch->clobber(RegisterSet::macroScratchRegisters()); 1208 1209 patch->append(countDownLocation, ValueRep::SomeRegister); 1090 1210 patch->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { 1091 MacroAssembler::Jump tierUp = jit.branch32(MacroAssembler::Above, params[0].gpr(), params[1].gpr()); 1092 MacroAssembler::Label tierUpResume = jit.label(); 1211 AllowMacroScratchRegisterUsage allowScratch(jit); 1212 CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr())); 1213 CCallHelpers::Label tierUpResume = jit.label(); 1093 1214 1094 1215 params.addLatePath([=] (CCallHelpers& jit) { … … 1107 1228 1108 1229 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 1109 MacroAssembler::repatchNearCall(linkBuffer.locationOfNearCall<NoPtrTag>(call), CodeLocationLabel<JITThunkPtrTag>(Thunks::singleton().stub(triggerOMGTierUpThunkGenerator).code())); 1110 1230 MacroAssembler::repatchNearCall(linkBuffer.locationOfNearCall<NoPtrTag>(call), CodeLocationLabel<JITThunkPtrTag>(Thunks::singleton().stub(triggerOMGEntryTierUpThunkGenerator).code())); 1111 1231 }); 1112 1232 }); … … 1114 1234 } 1115 1235 1116 B3IRGenerator::ControlData B3IRGenerator::addLoop(Type signature) 1236 void B3IRGenerator::emitLoopTierUpCheck(int32_t incrementCount, const Stack& expressionStack, uint32_t loopIndex, uint32_t outerLoopIndex, B3::Origin origin) 1237 { 1238 if (!m_tierUp) 1239 return; 1240 1241 ASSERT(m_tierUp); 1242 1243 ASSERT(m_tierUp->osrEntryTriggers().size() == loopIndex); 1244 m_tierUp->osrEntryTriggers().append(TierUpCount::TriggerReason::DontTrigger); 1245 m_tierUp->outerLoops().append(outerLoopIndex); 1246 1247 Value* countDownLocation = constant(pointerType(), reinterpret_cast<uint64_t>(&m_tierUp->m_counter), origin); 1248 1249 Vector<ExpressionType> stackmap; 1250 Vector<B3::Type> types; 1251 for (auto& local : m_locals) { 1252 ExpressionType result = m_currentBlock->appendNew<VariableValue>(m_proc, B3::Get, origin, local); 1253 stackmap.append(result); 1254 types.append(result->type()); 1255 } 1256 for (unsigned i = 0; i < expressionStack.size(); ++i) { 1257 ExpressionType result = expressionStack.at(i); 1258 stackmap.append(result); 1259 types.append(result->type()); 1260 } 1261 1262 PatchpointValue* patch = m_currentBlock->appendNew<PatchpointValue>(m_proc, B3::Void, origin); 1263 Effects effects = Effects::none(); 1264 // FIXME: we should have a more precise heap range for the tier up count. 1265 effects.reads = B3::HeapRange::top(); 1266 effects.writes = B3::HeapRange::top(); 1267 effects.exitsSideways = true; 1268 patch->effects = effects; 1269 1270 patch->clobber(RegisterSet::macroScratchRegisters()); 1271 RegisterSet clobberLate; 1272 clobberLate.add(GPRInfo::argumentGPR0); 1273 patch->clobberLate(clobberLate); 1274 1275 patch->append(countDownLocation, ValueRep::SomeRegister); 1276 patch->appendVectorWithRep(stackmap, ValueRep::ColdAny); 1277 1278 TierUpCount::TriggerReason* forceEntryTrigger = &(m_tierUp->osrEntryTriggers().last()); 1279 static_assert(!static_cast<uint8_t>(TierUpCount::TriggerReason::DontTrigger), "the JIT code assumes non-zero means 'enter'"); 1280 static_assert(sizeof(TierUpCount::TriggerReason) == 1, "branchTest8 assumes this size"); 1281 patch->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { 1282 AllowMacroScratchRegisterUsage allowScratch(jit); 1283 CCallHelpers::Jump forceOSREntry = jit.branchTest8(CCallHelpers::NonZero, CCallHelpers::AbsoluteAddress(forceEntryTrigger)); 1284 CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr())); 1285 MacroAssembler::Label tierUpResume = jit.label(); 1286 1287 OSREntryData& osrEntryData = m_tierUp->addOSREntryData(m_functionIndex, loopIndex); 1288 for (unsigned index = 0; index < types.size(); ++index) 1289 osrEntryData.values().constructAndAppend(params[index + 1], types[index]); 1290 OSREntryData* osrEntryDataPtr = &osrEntryData; 1291 1292 params.addLatePath([=] (CCallHelpers& jit) { 1293 AllowMacroScratchRegisterUsage allowScratch(jit); 1294 forceOSREntry.link(&jit); 1295 tierUp.link(&jit); 1296 1297 jit.probe(triggerOSREntryNow, osrEntryDataPtr); 1298 jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::argumentGPR0).linkTo(tierUpResume, &jit); 1299 jit.farJump(GPRInfo::argumentGPR1, WasmEntryPtrTag); 1300 }); 1301 }); 1302 } 1303 1304 B3IRGenerator::ControlData B3IRGenerator::addLoop(Type signature, const Stack& stack, uint32_t loopIndex) 1117 1305 { 1118 1306 BasicBlock* body = m_proc.addBlock(); … … 1120 1308 1121 1309 m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), body); 1122 1310 if (loopIndex == m_loopIndexForOSREntry) { 1311 m_currentBlock = m_rootBlock; 1312 m_osrEntryScratchBufferSize = m_locals.size() + stack.size(); 1313 Value* pointer = m_rootBlock->appendNew<ArgumentRegValue>(m_proc, Origin(), GPRInfo::argumentGPR0); 1314 1315 auto loadFromScratchBuffer = [&] (B3::Type type, unsigned index) { 1316 size_t offset = sizeof(uint64_t) * index; 1317 switch (type.kind()) { 1318 case B3::Int32: 1319 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(), pointer, offset); 1320 case B3::Int64: 1321 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Int64, origin(), pointer, offset); 1322 case B3::Float: 1323 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Float, origin(), pointer, offset); 1324 case B3::Double: 1325 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Double, origin(), pointer, offset); 1326 default: 1327 RELEASE_ASSERT_NOT_REACHED(); 1328 break; 1329 } 1330 }; 1331 1332 unsigned indexInBuffer = 0; 1333 for (auto& local : m_locals) 1334 m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), local, loadFromScratchBuffer(local->type(), indexInBuffer++)); 1335 for (unsigned i = 0; i < stack.size(); ++i) { 1336 auto* variable = stack.variableAt(i); 1337 m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), variable, loadFromScratchBuffer(variable->type(), indexInBuffer++)); 1338 } 1339 m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), body); 1340 body->addPredecessor(m_currentBlock); 1341 } 1342 1343 uint32_t outerLoopIndex = this->outerLoopIndex(); 1344 m_outerLoops.append(loopIndex); 1123 1345 m_currentBlock = body; 1124 emit TierUpCheck(TierUpCount::loopDecrement(), origin());1346 emitLoopTierUpCheck(TierUpCount::loopIncrement(), stack, loopIndex, outerLoopIndex, origin()); 1125 1347 1126 1348 return ControlData(m_proc, origin(), signature, BlockType::Loop, continuation, body); … … 1155 1377 } 1156 1378 1157 auto B3IRGenerator::addElse(ControlData& data, const ExpressionList& currentStack) -> PartialResult1379 auto B3IRGenerator::addElse(ControlData& data, const Stack& currentStack) -> PartialResult 1158 1380 { 1159 1381 unifyValuesWithBlock(currentStack, data.result); … … 1180 1402 } 1181 1403 1182 auto B3IRGenerator::addBranch(ControlData& data, ExpressionType condition, const ExpressionList& returnValues) -> PartialResult1404 auto B3IRGenerator::addBranch(ControlData& data, ExpressionType condition, const Stack& returnValues) -> PartialResult 1183 1405 { 1184 1406 unifyValuesWithBlock(returnValues, data.resultForBranch()); … … 1200 1422 } 1201 1423 1202 auto B3IRGenerator::addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const ExpressionList& expressionStack) -> PartialResult1424 auto B3IRGenerator::addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const Stack& expressionStack) -> PartialResult 1203 1425 { 1204 1426 for (size_t i = 0; i < targets.size(); ++i) … … 1214 1436 } 1215 1437 1216 auto B3IRGenerator::endBlock(ControlEntry& entry, ExpressionList& expressionStack) -> PartialResult1438 auto B3IRGenerator::endBlock(ControlEntry& entry, Stack& expressionStack) -> PartialResult 1217 1439 { 1218 1440 ControlData& data = entry.controlData; … … 1222 1444 data.continuation->addPredecessor(m_currentBlock); 1223 1445 1446 if (data.type() == BlockType::Loop) 1447 m_outerLoops.removeLast(); 1448 1224 1449 return addEndToUnreachable(entry); 1225 1450 } … … 1243 1468 // TopLevel does not have any code after this so we need to make sure we emit a return here. 1244 1469 if (data.type() == BlockType::TopLevel) 1245 return addReturn(entry.controlData, entry.enclosedExpressionStack );1470 return addReturn(entry.controlData, entry.enclosedExpressionStack.convertToExpressionList()); 1246 1471 1247 1472 return { }; … … 1507 1732 } 1508 1733 1509 void B3IRGenerator::unifyValuesWithBlock(const ExpressionList& resultStack, const ResultList& result)1734 void B3IRGenerator::unifyValuesWithBlock(const Stack& resultStack, const ResultList& result) 1510 1735 { 1511 1736 ASSERT(result.size() <= resultStack.size()); 1512 1737 1513 1738 for (size_t i = 0; i < result.size(); ++i) 1514 unify(result[result.size() - 1 - i], resultStack[resultStack.size() - 1 - i]); 1515 } 1516 1517 static void dumpExpressionStack(const CommaPrinter& comma, const B3IRGenerator::ExpressionList& expressionStack) 1518 { 1519 dataLog(comma, "ExpressionStack:"); 1520 for (const auto& expression : expressionStack) 1521 dataLog(comma, *expression); 1522 } 1523 1524 void B3IRGenerator::dump(const Vector<ControlEntry>& controlStack, const ExpressionList* expressionStack) 1739 unify(result[result.size() - 1 - i], resultStack.at(resultStack.size() - 1 - i)); 1740 } 1741 1742 void B3IRGenerator::dump(const Vector<ControlEntry>& controlStack, const Stack* expressionStack) 1525 1743 { 1526 1744 dataLogLn("Constants:"); … … 1535 1753 for (size_t i = controlStack.size(); i--;) { 1536 1754 dataLog(" ", controlStack[i].controlData, ": "); 1537 CommaPrinter comma(", ", ""); 1538 dumpExpressionStack(comma, *expressionStack); 1755 expressionStack->dump(); 1539 1756 expressionStack = &controlStack[i].enclosedExpressionStack; 1540 1757 dataLogLn(); … … 1550 1767 } 1551 1768 1552 Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature& signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ModuleInformation& info, MemoryMode mode, CompilationMode compilationMode, uint32_t functionIndex, TierUpCount* tierUp, ThrowWasmException throwWasmException)1769 Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature& signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, unsigned& osrEntryScratchBufferSize, const ModuleInformation& info, MemoryMode mode, CompilationMode compilationMode, uint32_t functionIndex, uint32_t loopIndexForOSREntry, TierUpCount* tierUp, ThrowWasmException throwWasmException) 1553 1770 { 1554 1771 auto result = makeUnique<InternalFunction>(); … … 1574 1791 : Options::webAssemblyOMGOptimizationLevel()); 1575 1792 1576 B3IRGenerator irGenerator(info, procedure, result.get(), unlinkedWasmToWasmCalls, mode, compilationMode, functionIndex, tierUp, throwWasmException);1793 B3IRGenerator irGenerator(info, procedure, result.get(), unlinkedWasmToWasmCalls, osrEntryScratchBufferSize, mode, compilationMode, functionIndex, loopIndexForOSREntry, tierUp, throwWasmException); 1577 1794 FunctionParser<B3IRGenerator> parser(irGenerator, functionStart, functionLength, signature, info); 1578 1795 WASM_FAIL_IF_HELPER_FAILS(parser.parse()); -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h
r248187 r248878 52 52 }; 53 53 54 Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext&, const uint8_t*, size_t, const Signature&, Vector<UnlinkedWasmToWasmCall>&, const ModuleInformation&, MemoryMode, CompilationMode, uint32_t functionIndex, TierUpCount* = nullptr, ThrowWasmException = nullptr);54 Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext&, const uint8_t*, size_t, const Signature&, Vector<UnlinkedWasmToWasmCall>&, unsigned& osrEntryScratchBufferSize, const ModuleInformation&, MemoryMode, CompilationMode, uint32_t functionIndex, uint32_t loopIndexForOSREntry, TierUpCount* = nullptr, ThrowWasmException = nullptr); 55 55 56 56 } } // namespace JSC::Wasm -
trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.cpp
r248846 r248878 268 268 269 269 m_unlinkedWasmToWasmCalls[functionIndex] = Vector<UnlinkedWasmToWasmCall>(); 270 TierUpCount* tierUp = Options::useBBQTierUpChecks() ? &m_tierUpCounts[functionIndex] : nullptr; 270 if (Options::useBBQTierUpChecks()) 271 m_tierUpCounts[functionIndex] = makeUnique<TierUpCount>(); 272 else 273 m_tierUpCounts[functionIndex] = nullptr; 274 TierUpCount* tierUp = m_tierUpCounts[functionIndex].get(); 271 275 Expected<std::unique_ptr<InternalFunction>, String> parseAndCompileResult; 276 unsigned osrEntryScratchBufferSize = 0; 272 277 273 278 // FIXME: Some webpages use very large Wasm module, and it exhausts all executable memory in ARM64 devices since the size of executable memory region is only limited to 128MB. … … 281 286 parseAndCompileResult = parseAndCompileAir(m_compilationContexts[functionIndex], function.data.data(), function.data.size(), signature, m_unlinkedWasmToWasmCalls[functionIndex], m_moduleInformation.get(), m_mode, functionIndex, tierUp, m_throwWasmException); 282 287 else 283 parseAndCompileResult = parseAndCompile(m_compilationContexts[functionIndex], function.data.data(), function.data.size(), signature, m_unlinkedWasmToWasmCalls[functionIndex], m_moduleInformation.get(), m_mode, CompilationMode::BBQMode, functionIndex, tierUp, m_throwWasmException);288 parseAndCompileResult = parseAndCompile(m_compilationContexts[functionIndex], function.data.data(), function.data.size(), signature, m_unlinkedWasmToWasmCalls[functionIndex], osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::BBQMode, functionIndex, UINT32_MAX, tierUp, m_throwWasmException); 284 289 285 290 if (UNLIKELY(!parseAndCompileResult)) { -
trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.h
r235420 r248878 104 104 } 105 105 106 Vector<TierUpCount> takeTierUpCounts()107 {108 RELEASE_ASSERT(!failed() && !hasWork());109 return WTFMove(m_tierUpCounts);110 }111 112 106 enum class State : uint8_t { 113 107 Initial, … … 147 141 HashMap<uint32_t, std::unique_ptr<InternalFunction>, typename DefaultHash<uint32_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> m_embedderToWasmInternalFunctions; 148 142 Vector<CompilationContext> m_compilationContexts; 149 Vector< TierUpCount> m_tierUpCounts;143 Vector<std::unique_ptr<TierUpCount>> m_tierUpCounts; 150 144 151 145 Vector<Vector<UnlinkedWasmToWasmCall>> m_unlinkedWasmToWasmCalls; -
trunk/Source/JavaScriptCore/wasm/WasmBBQPlanInlines.h
r248187 r248878 43 43 RefPtr<Wasm::Callee> embedderEntrypointCallee; 44 44 if (auto embedderToWasmFunction = m_embedderToWasmInternalFunctions.get(internalFunctionIndex)) { 45 embedderEntrypointCallee = Wasm:: Callee::create(CompilationMode::BBQMode,WTFMove(embedderToWasmFunction->entrypoint));45 embedderEntrypointCallee = Wasm::EmbedderEntrypointCallee::create(WTFMove(embedderToWasmFunction->entrypoint)); 46 46 MacroAssembler::repatchPointer(embedderToWasmFunction->calleeMoveLocation, CalleeBits::boxWasm(embedderEntrypointCallee.get())); 47 47 } … … 49 49 InternalFunction* function = m_wasmInternalFunctions[internalFunctionIndex].get(); 50 50 size_t functionIndexSpace = internalFunctionIndex + m_moduleInformation->importFunctionCount(); 51 Ref<Wasm::Callee> wasmEntrypointCallee = Wasm:: Callee::create(CompilationMode::BBQMode, WTFMove(function->entrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace));51 Ref<Wasm::Callee> wasmEntrypointCallee = Wasm::BBQCallee::create(WTFMove(function->entrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), WTFMove(m_tierUpCounts[internalFunctionIndex])); 52 52 MacroAssembler::repatchPointer(function->calleeMoveLocation, CalleeBits::boxWasm(wasmEntrypointCallee.ptr())); 53 53 -
trunk/Source/JavaScriptCore/wasm/WasmCallee.h
r248187 r248878 33 33 #include "WasmFormat.h" 34 34 #include "WasmIndexOrName.h" 35 #include "WasmTierUpCount.h" 35 36 #include <wtf/ThreadSafeRefCounted.h> 36 37 37 38 namespace JSC { namespace Wasm { 38 39 39 class Callee final: public ThreadSafeRefCounted<Callee> {40 class Callee : public ThreadSafeRefCounted<Callee> { 40 41 WTF_MAKE_FAST_ALLOCATED; 41 42 public: 42 static Ref<Callee> create(Wasm::CompilationMode compilationMode, Wasm::Entrypoint&& entrypoint)43 {44 Callee* callee = new Callee(compilationMode, WTFMove(entrypoint));45 return adoptRef(*callee);46 }47 48 static Ref<Callee> create(Wasm::CompilationMode compilationMode, Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name)49 {50 Callee* callee = new Callee(compilationMode, WTFMove(entrypoint), index, WTFMove(name));51 return adoptRef(*callee);52 }53 54 43 MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint() const { return m_entrypoint.compilation->code().retagged<WasmEntryPtrTag>(); } 55 44 … … 65 54 } 66 55 67 JS_EXPORT_PRIVATE ~Callee();56 JS_EXPORT_PRIVATE virtual ~Callee(); 68 57 69 pr ivate:58 protected: 70 59 JS_EXPORT_PRIVATE Callee(Wasm::CompilationMode, Wasm::Entrypoint&&); 71 60 JS_EXPORT_PRIVATE Callee(Wasm::CompilationMode, Wasm::Entrypoint&&, size_t, std::pair<const Name*, RefPtr<NameSection>>&&); 72 61 62 private: 73 63 CompilationMode m_compilationMode; 74 64 Wasm::Entrypoint m_entrypoint; … … 76 66 }; 77 67 68 class OMGCallee final : public Callee { 69 public: 70 static Ref<OMGCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls) 71 { 72 return adoptRef(*new OMGCallee(WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls))); 73 } 74 75 Vector<UnlinkedWasmToWasmCall>& wasmToWasmCallsites() { return m_wasmToWasmCallsites; } 76 77 private: 78 OMGCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls) 79 : Callee(Wasm::CompilationMode::OMGMode, WTFMove(entrypoint), index, WTFMove(name)) 80 , m_wasmToWasmCallsites(WTFMove(unlinkedCalls)) 81 { 82 } 83 84 Vector<UnlinkedWasmToWasmCall> m_wasmToWasmCallsites; 85 }; 86 87 class OMGForOSREntryCallee final : public Callee { 88 public: 89 static Ref<OMGForOSREntryCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, unsigned osrEntryScratchBufferSize, uint32_t loopIndex, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls) 90 { 91 return adoptRef(*new OMGForOSREntryCallee(WTFMove(entrypoint), index, WTFMove(name), osrEntryScratchBufferSize, loopIndex, WTFMove(unlinkedCalls))); 92 } 93 94 unsigned osrEntryScratchBufferSize() const { return m_osrEntryScratchBufferSize; } 95 uint32_t loopIndex() const { return m_loopIndex; } 96 Vector<UnlinkedWasmToWasmCall>& wasmToWasmCallsites() { return m_wasmToWasmCallsites; } 97 98 private: 99 OMGForOSREntryCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, unsigned osrEntryScratchBufferSize, uint32_t loopIndex, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls) 100 : Callee(Wasm::CompilationMode::OMGForOSREntryMode, WTFMove(entrypoint), index, WTFMove(name)) 101 , m_wasmToWasmCallsites(WTFMove(unlinkedCalls)) 102 , m_osrEntryScratchBufferSize(osrEntryScratchBufferSize) 103 , m_loopIndex(loopIndex) 104 { 105 } 106 107 Vector<UnlinkedWasmToWasmCall> m_wasmToWasmCallsites; 108 unsigned m_osrEntryScratchBufferSize; 109 uint32_t m_loopIndex; 110 }; 111 112 class EmbedderEntrypointCallee final : public Callee { 113 public: 114 static Ref<EmbedderEntrypointCallee> create(Wasm::Entrypoint&& entrypoint) 115 { 116 return adoptRef(*new EmbedderEntrypointCallee(WTFMove(entrypoint))); 117 } 118 119 private: 120 EmbedderEntrypointCallee(Wasm::Entrypoint&& entrypoint) 121 : Callee(Wasm::CompilationMode::EmbedderEntrypointMode, WTFMove(entrypoint)) 122 { 123 } 124 }; 125 126 class BBQCallee final : public Callee { 127 public: 128 static Ref<BBQCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, std::unique_ptr<TierUpCount>&& tierUpCount) 129 { 130 return adoptRef(*new BBQCallee(WTFMove(entrypoint), index, WTFMove(name), WTFMove(tierUpCount))); 131 } 132 133 OMGForOSREntryCallee* osrEntryCallee() { return m_osrEntryCallee.get(); } 134 void setOSREntryCallee(Ref<OMGForOSREntryCallee>&& osrEntryCallee) 135 { 136 m_osrEntryCallee = WTFMove(osrEntryCallee); 137 } 138 139 bool didStartCompilingOSREntryCallee() const { return m_didStartCompilingOSREntryCallee; } 140 void setDidStartCompilingOSREntryCallee(bool value) { m_didStartCompilingOSREntryCallee = value; } 141 142 OMGCallee* replacement() { return m_replacement.get(); } 143 void setReplacement(Ref<OMGCallee>&& replacement) 144 { 145 m_replacement = WTFMove(replacement); 146 } 147 148 TierUpCount* tierUpCount() { return m_tierUpCount.get(); } 149 150 private: 151 BBQCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, std::unique_ptr<TierUpCount>&& tierUpCount) 152 : Callee(Wasm::CompilationMode::BBQMode, WTFMove(entrypoint), index, WTFMove(name)) 153 , m_tierUpCount(WTFMove(tierUpCount)) 154 { 155 } 156 157 RefPtr<OMGForOSREntryCallee> m_osrEntryCallee; 158 RefPtr<OMGCallee> m_replacement; 159 std::unique_ptr<TierUpCount> m_tierUpCount; 160 bool m_didStartCompilingOSREntryCallee { false }; 161 }; 162 78 163 } } // namespace JSC::Wasm 79 164 -
trunk/Source/JavaScriptCore/wasm/WasmCodeBlock.cpp
r230096 r248878 72 72 m_wasmToWasmExitStubs = m_plan->takeWasmToWasmExitStubs(); 73 73 m_wasmToWasmCallsites = m_plan->takeWasmToWasmCallsites(); 74 m_tierUpCounts = m_plan->takeTierUpCounts();75 74 76 75 setCompilationFinished(); -
trunk/Source/JavaScriptCore/wasm/WasmCodeBlock.h
r230748 r248878 97 97 } 98 98 99 Callee& wasmBBQCalleeFromFunctionIndexSpace(unsigned functionIndexSpace) 100 { 101 ASSERT(runnable()); 102 RELEASE_ASSERT(functionIndexSpace >= functionImportCount()); 103 unsigned calleeIndex = functionIndexSpace - functionImportCount(); 104 return *m_callees[calleeIndex].get(); 105 } 106 99 107 MacroAssemblerCodePtr<WasmEntryPtrTag>* entrypointLoadLocationFromFunctionIndexSpace(unsigned functionIndexSpace) 100 108 { … … 102 110 unsigned calleeIndex = functionIndexSpace - functionImportCount(); 103 111 return &m_wasmIndirectCallEntryPoints[calleeIndex]; 104 }105 106 TierUpCount& tierUpCount(uint32_t functionIndex)107 {108 return m_tierUpCounts[functionIndex];109 112 } 110 113 … … 116 119 private: 117 120 friend class OMGPlan; 121 friend class OMGForOSREntryPlan; 118 122 119 123 CodeBlock(Context*, MemoryMode, ModuleInformation&, CreateEmbedderWrapper&&, ThrowWasmException); … … 125 129 HashMap<uint32_t, RefPtr<Callee>, typename DefaultHash<uint32_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> m_embedderCallees; 126 130 Vector<MacroAssemblerCodePtr<WasmEntryPtrTag>> m_wasmIndirectCallEntryPoints; 127 Vector<TierUpCount> m_tierUpCounts;128 131 Vector<Vector<UnlinkedWasmToWasmCall>> m_wasmToWasmCallsites; 129 132 Vector<MacroAssemblerCodeRef<WasmEntryPtrTag>> m_wasmToWasmExitStubs; -
trunk/Source/JavaScriptCore/wasm/WasmCompilationMode.cpp
r248187 r248878 38 38 case CompilationMode::OMGMode: 39 39 return "OMG"; 40 case CompilationMode::OMGForOSREntryMode: 41 return "OMGForOSREntry"; 42 case CompilationMode::EmbedderEntrypointMode: 43 return "EmbedderEntrypoint"; 40 44 } 41 45 RELEASE_ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/wasm/WasmCompilationMode.h
r248187 r248878 31 31 BBQMode, 32 32 OMGMode, 33 OMGForOSREntryMode, 34 EmbedderEntrypointMode, 33 35 }; 34 36 -
trunk/Source/JavaScriptCore/wasm/WasmContext.cpp
r248876 r248878 25 25 26 26 #include "config.h" 27 #include "WasmCo mpilationMode.h"27 #include "WasmContext.h" 28 28 29 #i nclude <wtf/Assertions.h>29 #if ENABLE(WEBASSEMBLY) 30 30 31 31 namespace JSC { namespace Wasm { 32 32 33 const char* makeString(CompilationMode mode)33 uint64_t* Context::scratchBufferForSize(size_t size) 34 34 { 35 switch (mode) { 36 case CompilationMode::BBQMode: 37 return "BBQ"; 38 case CompilationMode::OMGMode: 39 return "OMG"; 35 if (!size) 36 return nullptr; 37 38 auto locker = holdLock(m_scratchBufferLock); 39 if (size > m_sizeOfLastScratchBuffer) { 40 m_sizeOfLastScratchBuffer = size * 2; 41 42 auto newBuffer = makeUniqueArray<uint64_t>(m_sizeOfLastScratchBuffer); 43 RELEASE_ASSERT(newBuffer); 44 m_scratchBuffers.append(WTFMove(newBuffer)); 40 45 } 41 RELEASE_ASSERT_NOT_REACHED();42 return "";46 // Scanning scratch buffers for GC is not necessary since while performing OSR entry, we do not perform GC. 47 return m_scratchBuffers.last().get(); 43 48 } 44 49 45 50 } } // namespace JSC::Wasm 51 52 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WasmContext.h
r243886 r248878 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include <wtf/Lock.h> 31 #include <wtf/UniqueArray.h> 32 #include <wtf/Vector.h> 33 30 34 namespace JSC { namespace Wasm { 31 35 … … 44 48 } 45 49 50 static Instance* tryLoadInstanceFromTLS(); 51 52 uint64_t* scratchBufferForSize(size_t numberOfSlots); 53 46 54 private: 47 55 Instance* instance { nullptr }; 56 Vector<UniqueArray<uint64_t>> m_scratchBuffers; 57 size_t m_sizeOfLastScratchBuffer { 0 }; 58 Lock m_scratchBufferLock; 48 59 }; 49 60 -
trunk/Source/JavaScriptCore/wasm/WasmContextInlines.h
r243886 r248878 67 67 } 68 68 69 inline Instance* Context::tryLoadInstanceFromTLS() 70 { 71 #if ENABLE(FAST_TLS_JIT) 72 if (useFastTLS()) 73 return bitwise_cast<Instance*>(_pthread_getspecific_direct(WTF_WASM_CONTEXT_KEY)); 74 #endif 75 return nullptr; 76 } 77 69 78 } } // namespace JSC::Wasm 70 79 -
trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h
r246589 r248878 44 44 class FunctionParser : public Parser<void> { 45 45 public: 46 typedef typename Context::ExpressionType ExpressionType; 47 typedef typename Context::ControlType ControlType; 48 typedef typename Context::ExpressionList ExpressionList; 46 using ExpressionType = typename Context::ExpressionType; 47 using ControlType = typename Context::ControlType; 48 using ExpressionList = typename Context::ExpressionList; 49 using Stack = typename Context::Stack; 49 50 50 51 FunctionParser(Context&, const uint8_t* functionStart, size_t functionLength, const Signature&, const ModuleInformation&); … … 53 54 54 55 struct ControlEntry { 55 ExpressionListenclosedExpressionStack;56 Stack enclosedExpressionStack; 56 57 ControlType controlData; 57 58 }; … … 85 86 86 87 Context& m_context; 87 ExpressionListm_expressionStack;88 Stack m_expressionStack; 88 89 Vector<ControlEntry> m_controlStack; 89 90 const Signature& m_signature; … … 96 97 97 98 unsigned m_unreachableBlocks { 0 }; 99 unsigned m_loopIndex { 0 }; 98 100 }; 99 101 … … 102 104 : Parser(functionStart, functionLength) 103 105 , m_context(context) 106 , m_expressionStack(context.createStack()) 104 107 , m_signature(signature) 105 108 , m_info(info) … … 137 140 auto FunctionParser<Context>::parseBody() -> PartialResult 138 141 { 139 m_controlStack.append({ ExpressionList(), m_context.addTopLevel(m_signature.returnType()) });142 m_controlStack.append({ m_context.createStack(), m_context.addTopLevel(m_signature.returnType()) }); 140 143 uint8_t op; 141 144 while (m_controlStack.size()) { … … 424 427 WASM_PARSER_FAIL_IF(!args.tryReserveCapacity(calleeSignature.argumentCount()), "can't allocate enough memory for call's ", calleeSignature.argumentCount(), " arguments"); 425 428 for (size_t i = firstArgumentIndex; i < m_expressionStack.size(); ++i) 426 args.uncheckedAppend(m_expressionStack [i]);429 args.uncheckedAppend(m_expressionStack.at(i)); 427 430 m_expressionStack.shrink(firstArgumentIndex); 428 431 … … 454 457 size_t firstArgumentIndex = m_expressionStack.size() - argumentCount; 455 458 for (size_t i = firstArgumentIndex; i < m_expressionStack.size(); ++i) 456 args.uncheckedAppend(m_expressionStack [i]);459 args.uncheckedAppend(m_expressionStack.at(i)); 457 460 m_expressionStack.shrink(firstArgumentIndex); 458 461 … … 470 473 WASM_PARSER_FAIL_IF(!parseResultType(inlineSignature), "can't get block's inline signature"); 471 474 m_controlStack.append({ WTFMove(m_expressionStack), m_context.addBlock(inlineSignature) }); 472 m_expressionStack = ExpressionList();475 m_expressionStack = m_context.createStack(); 473 476 return { }; 474 477 } … … 477 480 Type inlineSignature; 478 481 WASM_PARSER_FAIL_IF(!parseResultType(inlineSignature), "can't get loop's inline signature"); 479 m_controlStack.append({ WTFMove(m_expressionStack), m_context.addLoop(inlineSignature) }); 480 m_expressionStack = ExpressionList(); 482 auto expressionStack = WTFMove(m_expressionStack); 483 auto loop = m_context.addLoop(inlineSignature, expressionStack, m_loopIndex++); 484 m_controlStack.append({ expressionStack, loop }); 485 m_expressionStack = m_context.createStack(); 481 486 return { }; 482 487 } … … 490 495 WASM_TRY_ADD_TO_CONTEXT(addIf(condition, inlineSignature, control)); 491 496 m_controlStack.append({ WTFMove(m_expressionStack), control }); 492 m_expressionStack = ExpressionList();497 m_expressionStack = m_context.createStack(); 493 498 return { }; 494 499 } -
trunk/Source/JavaScriptCore/wasm/WasmOMGForOSREntryPlan.cpp
r248876 r248878 1 1 /* 2 * Copyright (C) 201 7-2018Apple Inc. All rights reserved.2 * Copyright (C) 2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 25 25 26 26 #include "config.h" 27 #include "WasmOMG Plan.h"27 #include "WasmOMGForOSREntryPlan.h" 28 28 29 29 #if ENABLE(WEBASSEMBLY) … … 51 51 namespace JSC { namespace Wasm { 52 52 53 namespace WasmOMG PlanInternal {53 namespace WasmOMGForOSREntryPlanInternal { 54 54 static const bool verbose = false; 55 55 } 56 56 57 OMG Plan::OMGPlan(Context* context, Ref<Module>&& module, uint32_t functionIndex, MemoryMode mode, CompletionTask&& task)57 OMGForOSREntryPlan::OMGForOSREntryPlan(Context* context, Ref<Module>&& module, Ref<BBQCallee>&& callee, uint32_t functionIndex, uint32_t loopIndex, MemoryMode mode, CompletionTask&& task) 58 58 : Base(context, makeRef(const_cast<ModuleInformation&>(module->moduleInformation())), WTFMove(task)) 59 59 , m_module(WTFMove(module)) 60 60 , m_codeBlock(*m_module->codeBlockFor(mode)) 61 , m_callee(WTFMove(callee)) 61 62 , m_functionIndex(functionIndex) 63 , m_loopIndex(loopIndex) 62 64 { 63 65 setMode(mode); 64 66 ASSERT(m_codeBlock->runnable()); 65 67 ASSERT(m_codeBlock.ptr() == m_module->codeBlockFor(m_mode)); 66 dataLogLnIf(WasmOMG PlanInternal::verbose, "Starting OMGplan for ", functionIndex, " of module: ", RawPointer(&m_module.get()));68 dataLogLnIf(WasmOMGForOSREntryPlanInternal::verbose, "Starting OMGForOSREntry plan for ", functionIndex, " of module: ", RawPointer(&m_module.get())); 67 69 } 68 70 69 void OMG Plan::work(CompilationEffort)71 void OMGForOSREntryPlan::work(CompilationEffort) 70 72 { 71 73 ASSERT(m_codeBlock->runnable()); … … 82 84 Vector<UnlinkedWasmToWasmCall> unlinkedCalls; 83 85 CompilationContext context; 84 auto parseAndCompileResult = parseAndCompile(context, function.data.data(), function.data.size(), signature, unlinkedCalls, m_moduleInformation.get(), m_mode, CompilationMode::OMGMode, m_functionIndex); 86 unsigned osrEntryScratchBufferSize = 0; 87 auto parseAndCompileResult = parseAndCompile(context, function.data.data(), function.data.size(), signature, unlinkedCalls, osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::OMGForOSREntryMode, m_functionIndex, m_loopIndex); 85 88 86 89 if (UNLIKELY(!parseAndCompileResult)) { … … 97 100 98 101 omgEntrypoint.compilation = makeUnique<B3::Compilation>( 99 FINALIZE_CODE(linkBuffer, B3CompilationPtrTag, "WebAssembly OMG function[%i] %s name %s", m_functionIndex, signature.toString().ascii().data(), makeString(IndexOrName(functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace))).ascii().data()),102 FINALIZE_CODE(linkBuffer, B3CompilationPtrTag, "WebAssembly OMGForOSREntry function[%i] %s name %s", m_functionIndex, signature.toString().ascii().data(), makeString(IndexOrName(functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace))).ascii().data()), 100 103 WTFMove(context.wasmEntrypointByproducts)); 101 104 … … 103 106 104 107 MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint; 108 ASSERT(m_codeBlock.ptr() == m_module->codeBlockFor(mode())); 109 Ref<OMGForOSREntryCallee> callee = OMGForOSREntryCallee::create(WTFMove(omgEntrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), osrEntryScratchBufferSize, m_loopIndex, WTFMove(unlinkedCalls)); 105 110 { 106 ASSERT(m_codeBlock.ptr() == m_module->codeBlockFor(mode()));107 Ref<Callee> callee = Callee::create(CompilationMode::OMGMode, WTFMove(omgEntrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace));108 111 MacroAssembler::repatchPointer(parseAndCompileResult.value()->calleeMoveLocation, CalleeBits::boxWasm(callee.ptr())); 109 ASSERT(!m_codeBlock->m_optimizedCallees[m_functionIndex]);110 112 entrypoint = callee->entrypoint(); 111 113 112 // We want to make sure we publish our callee at the same time as we link our callsites. This enables us to ensure we 113 // always call the fastest code. Any function linked after us will see our new code and the new callsites, which they 114 // will update. It's also ok if they publish their code before we reset the instruction caches because after we release 115 // the lock our code is ready to be published too. 116 LockHolder holder(m_codeBlock->m_lock); 117 m_codeBlock->m_optimizedCallees[m_functionIndex] = WTFMove(callee); 118 119 for (auto& call : unlinkedCalls) { 114 auto locker = holdLock(m_codeBlock->m_lock); 115 for (auto& call : callee->wasmToWasmCallsites()) { 120 116 MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint; 121 117 if (call.functionIndexSpace < m_module->moduleInformation().importFunctionCount()) … … 126 122 MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint)); 127 123 } 128 unlinkedCalls = std::exchange(m_codeBlock->m_wasmToWasmCallsites[m_functionIndex], unlinkedCalls);129 124 } 125 resetInstructionCacheOnAllThreads(); 126 WTF::storeStoreFence(); 127 { 128 auto locker = holdLock(m_codeBlock->m_lock); 129 { 130 auto locker = holdLock(m_callee->tierUpCount()->getLock()); 131 m_callee->setOSREntryCallee(callee.copyRef()); 132 m_callee->tierUpCount()->osrEntryTriggers()[m_loopIndex] = TierUpCount::TriggerReason::CompilationDone; 133 m_callee->tierUpCount()->m_compilationStatusForOMGForOSREntry = TierUpCount::CompilationStatus::Compiled; 134 } 135 WTF::storeStoreFence(); 136 // It is possible that a new OMG callee is added while we release m_codeBlock->lock. 137 // Until we add OMGForOSREntry callee to BBQCallee's m_osrEntryCallee, this new OMG function linking does not happen for this OMGForOSREntry callee. 138 // We re-link this OMGForOSREntry callee again not to miss that chance. 139 for (auto& call : callee->wasmToWasmCallsites()) { 140 MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint; 141 if (call.functionIndexSpace < m_module->moduleInformation().importFunctionCount()) 142 entrypoint = m_codeBlock->m_wasmToWasmExitStubs[call.functionIndexSpace].code(); 143 else 144 entrypoint = m_codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(call.functionIndexSpace).entrypoint().retagged<WasmEntryPtrTag>(); 130 145 131 // It's important to make sure we do this before we make any of the code we just compiled visible. If we didn't, we could end up 132 // where we are tiering up some function A to A' and we repatch some function B to call A' instead of A. Another CPU could see 133 // the updates to B but still not have reset its cache of A', which would lead to all kinds of badness. 134 resetInstructionCacheOnAllThreads(); 135 WTF::storeStoreFence(); // This probably isn't necessary but it's good to be paranoid. 136 137 m_codeBlock->m_wasmIndirectCallEntryPoints[m_functionIndex] = entrypoint; 138 { 139 LockHolder holder(m_codeBlock->m_lock); 140 141 auto repatchCalls = [&] (const Vector<UnlinkedWasmToWasmCall>& callsites) { 142 for (auto& call : callsites) { 143 dataLogLnIf(WasmOMGPlanInternal::verbose, "Considering repatching call at: ", RawPointer(call.callLocation.dataLocation()), " that targets ", call.functionIndexSpace); 144 if (call.functionIndexSpace == functionIndexSpace) { 145 dataLogLnIf(WasmOMGPlanInternal::verbose, "Repatching call at: ", RawPointer(call.callLocation.dataLocation()), " to ", RawPointer(entrypoint.executableAddress())); 146 MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint)); 147 } 148 } 149 150 }; 151 152 for (unsigned i = 0; i < m_codeBlock->m_wasmToWasmCallsites.size(); ++i) { 153 if (i != functionIndexSpace) 154 repatchCalls(m_codeBlock->m_wasmToWasmCallsites[i]); 146 MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint)); 155 147 } 156 157 // Make sure we repatch any recursive calls.158 repatchCalls(unlinkedCalls);159 148 } 160 161 dataLogLnIf(WasmOMGPlanInternal::verbose, "Finished with tier up count at: ", m_codeBlock->tierUpCount(m_functionIndex).count()); 149 dataLogLnIf(WasmOMGForOSREntryPlanInternal::verbose, "Finished OMGForOSREntry ", m_functionIndex, " with tier up count at: ", m_callee->tierUpCount()->count()); 162 150 complete(holdLock(m_lock)); 163 }164 165 void OMGPlan::runForIndex(Instance* instance, uint32_t functionIndex)166 {167 Wasm::CodeBlock& codeBlock = *instance->codeBlock();168 ASSERT(instance->memory()->mode() == codeBlock.mode());169 170 if (codeBlock.tierUpCount(functionIndex).shouldStartTierUp()) {171 Ref<Plan> plan = adoptRef(*new OMGPlan(instance->context(), Ref<Wasm::Module>(instance->module()), functionIndex, codeBlock.mode(), Plan::dontFinalize()));172 ensureWorklist().enqueue(plan.copyRef());173 if (UNLIKELY(!Options::useConcurrentJIT()))174 plan->waitForCompletion();175 }176 151 } 177 152 -
trunk/Source/JavaScriptCore/wasm/WasmOMGForOSREntryPlan.h
r248876 r248878 1 1 /* 2 * Copyright (C) 201 7Apple Inc. All rights reserved.2 * Copyright (C) 2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 #include "WasmContext.h" 31 31 #include "WasmModule.h" 32 #include "WasmOperations.h" 32 33 #include "WasmPlan.h" 33 34 34 35 namespace JSC { 35 36 37 class BBQCallee; 36 38 class CallLinkInfo; 37 39 38 40 namespace Wasm { 39 41 40 class OMG Plan final : public Plan {42 class OMGForOSREntryPlan final : public Plan { 41 43 public: 42 44 using Base = Plan; … … 46 48 bool multiThreaded() const override { return false; } 47 49 48 static void runForIndex(Instance*, uint32_t functionIndex); 50 // Note: CompletionTask should not hold a reference to the Plan otherwise there will be a reference cycle. 51 OMGForOSREntryPlan(Context*, Ref<Module>&&, Ref<BBQCallee>&&, uint32_t functionIndex, uint32_t loopIndex, MemoryMode, CompletionTask&&); 49 52 50 53 private: 51 54 // For some reason friendship doesn't extend to parent classes... 52 55 using Base::m_lock; 53 54 // Note: CompletionTask should not hold a reference to the Plan otherwise there will be a reference cycle.55 OMGPlan(Context*, Ref<Module>&&, uint32_t functionIndex, MemoryMode, CompletionTask&&);56 56 57 57 bool isComplete() const override { return m_completed; } … … 61 61 runCompletionTasks(locker); 62 62 } 63 63 64 64 Ref<Module> m_module; 65 65 Ref<CodeBlock> m_codeBlock; 66 Ref<BBQCallee> m_callee; 66 67 bool m_completed { false }; 67 68 uint32_t m_functionIndex; 69 uint32_t m_loopIndex; 68 70 }; 69 71 -
trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.cpp
r248846 r248878 81 81 82 82 Vector<UnlinkedWasmToWasmCall> unlinkedCalls; 83 unsigned osrEntryScratchBufferSize; 83 84 CompilationContext context; 84 auto parseAndCompileResult = parseAndCompile(context, function.data.data(), function.data.size(), signature, unlinkedCalls, m_moduleInformation.get(), m_mode, CompilationMode::OMGMode, m_functionIndex);85 auto parseAndCompileResult = parseAndCompile(context, function.data.data(), function.data.size(), signature, unlinkedCalls, osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::OMGMode, m_functionIndex, UINT32_MAX); 85 86 86 87 if (UNLIKELY(!parseAndCompileResult)) { … … 105 106 { 106 107 ASSERT(m_codeBlock.ptr() == m_module->codeBlockFor(mode())); 107 Ref< Callee> callee = Callee::create(CompilationMode::OMGMode, WTFMove(omgEntrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace));108 Ref<OMGCallee> callee = OMGCallee::create(WTFMove(omgEntrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), WTFMove(unlinkedCalls)); 108 109 MacroAssembler::repatchPointer(parseAndCompileResult.value()->calleeMoveLocation, CalleeBits::boxWasm(callee.ptr())); 109 110 ASSERT(!m_codeBlock->m_optimizedCallees[m_functionIndex]); … … 115 116 // the lock our code is ready to be published too. 116 117 LockHolder holder(m_codeBlock->m_lock); 117 m_codeBlock->m_optimizedCallees[m_functionIndex] = WTFMove(callee); 118 119 for (auto& call : unlinkedCalls) { 118 m_codeBlock->m_optimizedCallees[m_functionIndex] = callee.copyRef(); 119 { 120 BBQCallee& bbqCallee = *static_cast<BBQCallee*>(m_codeBlock->m_callees[m_functionIndex].get()); 121 auto locker = holdLock(bbqCallee.tierUpCount()->getLock()); 122 bbqCallee.setReplacement(callee.copyRef()); 123 bbqCallee.tierUpCount()->m_compilationStatusForOMG = TierUpCount::CompilationStatus::Compiled; 124 } 125 for (auto& call : callee->wasmToWasmCallsites()) { 120 126 MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint; 121 127 if (call.functionIndexSpace < m_module->moduleInformation().importFunctionCount()) … … 126 132 MacroAssembler::repatchNearCall(call.callLocation, CodeLocationLabel<WasmEntryPtrTag>(entrypoint)); 127 133 } 128 unlinkedCalls = std::exchange(m_codeBlock->m_wasmToWasmCallsites[m_functionIndex], unlinkedCalls);129 134 } 130 135 … … 147 152 } 148 153 } 149 150 154 }; 151 155 152 156 for (unsigned i = 0; i < m_codeBlock->m_wasmToWasmCallsites.size(); ++i) { 153 if (i != functionIndexSpace) 154 repatchCalls(m_codeBlock->m_wasmToWasmCallsites[i]); 157 repatchCalls(m_codeBlock->m_wasmToWasmCallsites[i]); 158 if (OMGCallee* replacementCallee = static_cast<BBQCallee*>(m_codeBlock->m_callees[i].get())->replacement()) 159 repatchCalls(replacementCallee->wasmToWasmCallsites()); 160 if (OMGForOSREntryCallee* osrEntryCallee = static_cast<BBQCallee*>(m_codeBlock->m_callees[i].get())->osrEntryCallee()) 161 repatchCalls(osrEntryCallee->wasmToWasmCallsites()); 155 162 } 156 157 // Make sure we repatch any recursive calls.158 repatchCalls(unlinkedCalls);159 163 } 160 164 161 dataLogLnIf(WasmOMGPlanInternal::verbose, "Finished with tier up count at: ", m_codeBlock->tierUpCount(m_functionIndex).count());165 dataLogLnIf(WasmOMGPlanInternal::verbose, "Finished OMG ", m_functionIndex, " with tier up count at: ", static_cast<BBQCallee*>(m_codeBlock->m_callees[m_functionIndex].get())->tierUpCount()->count()); 162 166 complete(holdLock(m_lock)); 163 }164 165 void OMGPlan::runForIndex(Instance* instance, uint32_t functionIndex)166 {167 Wasm::CodeBlock& codeBlock = *instance->codeBlock();168 ASSERT(instance->memory()->mode() == codeBlock.mode());169 170 if (codeBlock.tierUpCount(functionIndex).shouldStartTierUp()) {171 Ref<Plan> plan = adoptRef(*new OMGPlan(instance->context(), Ref<Wasm::Module>(instance->module()), functionIndex, codeBlock.mode(), Plan::dontFinalize()));172 ensureWorklist().enqueue(plan.copyRef());173 if (UNLIKELY(!Options::useConcurrentJIT()))174 plan->waitForCompletion();175 }176 167 } 177 168 -
trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.h
r224020 r248878 46 46 bool multiThreaded() const override { return false; } 47 47 48 static void runForIndex(Instance*, uint32_t functionIndex); 48 // Note: CompletionTask should not hold a reference to the Plan otherwise there will be a reference cycle. 49 OMGPlan(Context*, Ref<Module>&&, uint32_t functionIndex, MemoryMode, CompletionTask&&); 49 50 50 51 private: 51 52 // For some reason friendship doesn't extend to parent classes... 52 53 using Base::m_lock; 53 54 // Note: CompletionTask should not hold a reference to the Plan otherwise there will be a reference cycle.55 OMGPlan(Context*, Ref<Module>&&, uint32_t functionIndex, MemoryMode, CompletionTask&&);56 54 57 55 bool isComplete() const override { return m_completed; } -
trunk/Source/JavaScriptCore/wasm/WasmOSREntryData.h
r248876 r248878 1 1 /* 2 * Copyright (C) 201 7Apple Inc. All rights reserved.2 * Copyright (C) 2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "B3ValueRep.h" 31 #include "WasmFormat.h" 32 #include <wtf/Vector.h> 33 30 34 namespace JSC { namespace Wasm { 31 35 32 class Instance; 33 34 struct Context { 35 Instance* load() const; 36 void store(Instance*, void* softStackLimit); 37 38 static bool useFastTLS(); 39 40 Instance** pointerToInstance() 36 class OSREntryValue : public B3::ValueRep { 37 public: 38 OSREntryValue(const B3::ValueRep& valueRep, B3::Type type) 39 : B3::ValueRep(valueRep) 40 , m_type(type) 41 41 { 42 ASSERT(!useFastTLS());43 return &instance;44 42 } 45 43 44 B3::Type type() const { return m_type; } 45 46 46 private: 47 Instance* instance { nullptr }; 47 B3::Type m_type; 48 }; 49 50 class OSREntryData { 51 WTF_MAKE_NONCOPYABLE(OSREntryData); 52 WTF_MAKE_FAST_ALLOCATED; 53 public: 54 OSREntryData(uint32_t functionIndex, uint32_t loopIndex) 55 : m_functionIndex(functionIndex) 56 , m_loopIndex(loopIndex) 57 { 58 } 59 60 uint32_t functionIndex() const { return m_functionIndex; } 61 uint32_t loopIndex() const { return m_loopIndex; } 62 Vector<OSREntryValue>& values() { return m_values; } 63 64 private: 65 uint32_t m_functionIndex; 66 uint32_t m_loopIndex; 67 Vector<OSREntryValue> m_values; 48 68 }; 49 69 -
trunk/Source/JavaScriptCore/wasm/WasmOperations.h
r248876 r248878 26 26 #pragma once 27 27 28 namespace JSC { namespace Wasm { 28 #if ENABLE(WEBASSEMBLY) 29 29 30 enum class CompilationMode : uint8_t { 31 BBQMode, 32 OMGMode, 33 }; 30 #include "SlowPathReturnType.h" 34 31 35 const char* makeString(CompilationMode); 32 namespace JSC { 33 namespace Probe { 34 class Context; 35 } // namespace JSC::Probe 36 namespace Wasm { 37 38 class Instance; 39 40 void JIT_OPERATION triggerOSREntryNow(Probe::Context&) WTF_INTERNAL; 41 void JIT_OPERATION triggerTierUpNow(Instance*, uint32_t functionIndex) WTF_INTERNAL; 36 42 37 43 } } // namespace JSC::Wasm 44 45 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WasmThunks.cpp
r248686 r248878 37 37 #include "WasmExceptionType.h" 38 38 #include "WasmInstance.h" 39 #include "WasmO MGPlan.h"39 #include "WasmOperations.h" 40 40 41 41 namespace JSC { namespace Wasm { … … 78 78 } 79 79 80 MacroAssemblerCodeRef<JITThunkPtrTag> triggerOMG TierUpThunkGenerator(const AbstractLocker&)80 MacroAssemblerCodeRef<JITThunkPtrTag> triggerOMGEntryTierUpThunkGenerator(const AbstractLocker&) 81 81 { 82 82 // We expect that the user has already put the function index into GPRInfo::argumentGPR1 … … 91 91 92 92 jit.loadWasmContextInstance(GPRInfo::argumentGPR0); 93 typedef void (*Run)(Instance*, uint32_t); 94 Run run = OMGPlan::runForIndex; 95 jit.move(MacroAssembler::TrustedImmPtr(tagCFunctionPtr<OperationPtrTag>(run)), GPRInfo::argumentGPR2); 93 jit.move(MacroAssembler::TrustedImmPtr(tagCFunctionPtr<OperationPtrTag>(triggerTierUpNow)), GPRInfo::argumentGPR2); 96 94 jit.call(GPRInfo::argumentGPR2, OperationPtrTag); 97 95 … … 101 99 jit.ret(); 102 100 LinkBuffer linkBuffer(jit, GLOBAL_THUNK_ID); 103 return FINALIZE_CODE(linkBuffer, JITThunkPtrTag, "Trigger OMG tier up");101 return FINALIZE_CODE(linkBuffer, JITThunkPtrTag, "Trigger OMG entry tier up"); 104 102 } 105 103 -
trunk/Source/JavaScriptCore/wasm/WasmThunks.h
r241923 r248878 35 35 MacroAssemblerCodeRef<JITThunkPtrTag> throwExceptionFromWasmThunkGenerator(const AbstractLocker&); 36 36 MacroAssemblerCodeRef<JITThunkPtrTag> throwStackOverflowFromWasmThunkGenerator(const AbstractLocker&); 37 MacroAssemblerCodeRef<JITThunkPtrTag> triggerOMG TierUpThunkGenerator(const AbstractLocker&);37 MacroAssemblerCodeRef<JITThunkPtrTag> triggerOMGEntryTierUpThunkGenerator(const AbstractLocker&); 38 38 39 39 typedef MacroAssemblerCodeRef<JITThunkPtrTag> (*ThunkGenerator)(const AbstractLocker&); -
trunk/Source/JavaScriptCore/wasm/WasmTierUpCount.cpp
r248876 r248878 25 25 26 26 #include "config.h" 27 #include "Wasm CompilationMode.h"27 #include "WasmTierUpCount.h" 28 28 29 #include <wtf/Assertions.h> 29 #if ENABLE(WEBASSEMBLY) 30 31 #include "WasmOSREntryData.h" 30 32 31 33 namespace JSC { namespace Wasm { 32 34 33 const char* makeString(CompilationMode mode)35 TierUpCount::TierUpCount() 34 36 { 35 switch (mode) { 36 case CompilationMode::BBQMode: 37 return "BBQ"; 38 case CompilationMode::OMGMode: 39 return "OMG"; 40 } 41 RELEASE_ASSERT_NOT_REACHED(); 42 return ""; 37 setNewThreshold(Options::thresholdForOMGOptimizeAfterWarmUp(), nullptr); 43 38 } 44 39 45 } } // namespace JSC::Wasm 40 TierUpCount::~TierUpCount() = default; 41 42 OSREntryData& TierUpCount::addOSREntryData(uint32_t functionIndex, uint32_t loopIndex) 43 { 44 m_osrEntryData.append(makeUnique<OSREntryData>(functionIndex, loopIndex)); 45 return *m_osrEntryData.last().get(); 46 } 47 48 } } // namespace JSC::Table 49 50 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WasmTierUpCount.h
r215898 r248878 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "CompilationResult.h" 31 #include "ExecutionCounter.h" 30 32 #include "Options.h" 31 33 #include <wtf/Atomics.h> 34 #include <wtf/SegmentedVector.h> 32 35 #include <wtf/StdLibExtras.h> 33 36 34 37 namespace JSC { namespace Wasm { 38 39 class OSREntryData; 35 40 36 41 // This class manages the tier up counts for Wasm binaries. The main interesting thing about … … 39 44 // don't care too much if the countdown is slightly off. The tier up trigger is atomic, however, 40 45 // so tier up will be triggered exactly once. 41 class TierUpCount {46 class TierUpCount : public UpperTierExecutionCounter { 42 47 WTF_MAKE_NONCOPYABLE(TierUpCount); 43 48 public: 44 TierUpCount() 45 : m_count(Options::webAssemblyOMGTierUpCount()) 46 , m_tierUpStarted(false) 49 enum class TriggerReason : uint8_t { 50 DontTrigger, 51 CompilationDone, 52 StartCompilation, 53 }; 54 55 enum class CompilationStatus : uint8_t { 56 NotCompiled, 57 StartCompilation, 58 Compiled, 59 Failed, 60 }; 61 62 TierUpCount(); 63 ~TierUpCount(); 64 65 static int32_t loopIncrement() { return Options::omgTierUpCounterIncrementForLoop(); } 66 static int32_t functionEntryIncrement() { return Options::omgTierUpCounterIncrementForEntry(); } 67 68 SegmentedVector<TriggerReason, 16>& osrEntryTriggers() { return m_osrEntryTriggers; } 69 Vector<uint32_t>& outerLoops() { return m_outerLoops; } 70 Lock& getLock() { return m_lock; } 71 72 OSREntryData& addOSREntryData(uint32_t functionIndex, uint32_t loopIndex); 73 74 void optimizeAfterWarmUp(uint32_t functionIndex) 47 75 { 76 dataLogLnIf(Options::verboseOSR(), functionIndex, ": OMG-optimizing after warm-up."); 77 setNewThreshold(Options::thresholdForOMGOptimizeAfterWarmUp(), nullptr); 48 78 } 49 79 50 TierUpCount(TierUpCount&& other)80 bool checkIfOptimizationThresholdReached() 51 81 { 52 ASSERT(other.m_count == Options::webAssemblyOMGTierUpCount()); 53 m_count = other.m_count; 82 return checkIfThresholdCrossedAndSet(nullptr); 54 83 } 55 84 56 static uint32_t loopDecrement() { return Options::webAssemblyLoopDecrement(); } 57 static uint32_t functionEntryDecrement() { return Options::webAssemblyFunctionEntryDecrement(); } 58 59 bool shouldStartTierUp() 85 void dontOptimizeAnytimeSoon(uint32_t functionIndex) 60 86 { 61 return !m_tierUpStarted.exchange(true); 87 dataLogLnIf(Options::verboseOSR(), functionIndex, ": Not OMG-optimizing anytime soon."); 88 deferIndefinitely(); 62 89 } 63 90 64 int32_t count() { return bitwise_cast<int32_t>(m_count); } 91 void optimizeNextInvocation(uint32_t functionIndex) 92 { 93 dataLogLnIf(Options::verboseOSR(), functionIndex, ": OMG-optimizing next invocation."); 94 setNewThreshold(0, nullptr); 95 } 65 96 66 private: 67 uint32_t m_count; 68 Atomic<bool> m_tierUpStarted; 97 void optimizeSoon(uint32_t functionIndex) 98 { 99 dataLogLnIf(Options::verboseOSR(), functionIndex, ": OMG-optimizing soon."); 100 // FIXME: Need adjustment once we get more information about wasm functions. 101 setNewThreshold(Options::thresholdForOMGOptimizeSoon(), nullptr); 102 } 103 104 void setOptimizationThresholdBasedOnCompilationResult(uint32_t functionIndex, CompilationResult result) 105 { 106 switch (result) { 107 case CompilationSuccessful: 108 optimizeNextInvocation(functionIndex); 109 return; 110 case CompilationFailed: 111 dontOptimizeAnytimeSoon(functionIndex); 112 return; 113 case CompilationDeferred: 114 optimizeAfterWarmUp(functionIndex); 115 return; 116 case CompilationInvalidated: 117 // This is weird - it will only happen in cases when the DFG code block (i.e. 118 // the code block that this JITCode belongs to) is also invalidated. So it 119 // doesn't really matter what we do. But, we do the right thing anyway. Note 120 // that us counting the reoptimization actually means that we might count it 121 // twice. But that's generally OK. It's better to overcount reoptimizations 122 // than it is to undercount them. 123 optimizeAfterWarmUp(functionIndex); 124 return; 125 } 126 RELEASE_ASSERT_NOT_REACHED(); 127 } 128 129 Atomic<bool> m_tierUpStarted { false }; 130 Lock m_lock; 131 CompilationStatus m_compilationStatusForOMG { CompilationStatus::NotCompiled }; 132 CompilationStatus m_compilationStatusForOMGForOSREntry { CompilationStatus::NotCompiled }; 133 SegmentedVector<TriggerReason, 16> m_osrEntryTriggers; 134 Vector<uint32_t> m_outerLoops; 135 Vector<std::unique_ptr<OSREntryData>> m_osrEntryData; 69 136 }; 70 137 -
trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp
r246645 r248878 80 80 typedef Unexpected<ErrorType> UnexpectedResult; 81 81 typedef Expected<void, ErrorType> Result; 82 typedef Type ExpressionType; 82 using ExpressionType = Type; 83 using ExpressionList = Vector<ExpressionType, 1>; 84 using Stack = ExpressionList; 83 85 typedef ControlData ControlType; 84 typedef Vector<ExpressionType, 1> ExpressionList;85 86 typedef FunctionParser<Validate>::ControlEntry ControlEntry; 86 87 87 88 static constexpr ExpressionType emptyExpression() { return Void; } 89 Stack createStack() { return Stack(); } 88 90 89 91 template <typename ...Args> … … 134 136 ControlData WARN_UNUSED_RETURN addTopLevel(Type signature); 135 137 ControlData WARN_UNUSED_RETURN addBlock(Type signature); 136 ControlData WARN_UNUSED_RETURN addLoop(Type signature );138 ControlData WARN_UNUSED_RETURN addLoop(Type signature, const Stack&, uint32_t); 137 139 Result WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature, ControlData& result); 138 Result WARN_UNUSED_RETURN addElse(ControlData&, const ExpressionList&);140 Result WARN_UNUSED_RETURN addElse(ControlData&, const Stack&); 139 141 Result WARN_UNUSED_RETURN addElseToUnreachable(ControlData&); 140 142 141 Result WARN_UNUSED_RETURN addReturn(ControlData& topLevel, const ExpressionList& returnValues);142 Result WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const ExpressionList& expressionStack);143 Result WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const ExpressionList& expressionStack);144 Result WARN_UNUSED_RETURN endBlock(ControlEntry&, ExpressionList& expressionStack);143 Result WARN_UNUSED_RETURN addReturn(ControlData& topLevel, const Stack& returnValues); 144 Result WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const Stack& expressionStack); 145 Result WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const Stack& expressionStack); 146 Result WARN_UNUSED_RETURN endBlock(ControlEntry&, Stack& expressionStack); 145 147 Result WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&); 146 148 Result WARN_UNUSED_RETURN addGrowMemory(ExpressionType delta, ExpressionType& result); … … 162 164 } 163 165 164 void dump(const Vector<ControlEntry>&, const ExpressionList*);166 void dump(const Vector<ControlEntry>&, const Stack*); 165 167 void setParser(FunctionParser<Validate>*) { } 166 168 167 169 private: 168 Result WARN_UNUSED_RETURN unify(const ExpressionList&, const ControlData&);169 170 Result WARN_UNUSED_RETURN checkBranchTarget(ControlData& target, const ExpressionList& expressionStack);170 Result WARN_UNUSED_RETURN unify(const Stack&, const ControlData&); 171 172 Result WARN_UNUSED_RETURN checkBranchTarget(ControlData& target, const Stack& expressionStack); 171 173 172 174 Vector<Type> m_locals; … … 300 302 } 301 303 302 Validate::ControlType Validate::addLoop(Type signature )304 Validate::ControlType Validate::addLoop(Type signature, const Stack&, uint32_t) 303 305 { 304 306 return ControlData(BlockType::Loop, signature); … … 320 322 } 321 323 322 auto Validate::addElse(ControlType& current, const ExpressionList& values) -> Result324 auto Validate::addElse(ControlType& current, const Stack& values) -> Result 323 325 { 324 326 WASM_FAIL_IF_HELPER_FAILS(unify(values, current)); … … 343 345 } 344 346 345 auto Validate::checkBranchTarget(ControlType& target, const ExpressionList& expressionStack) -> Result347 auto Validate::checkBranchTarget(ControlType& target, const Stack& expressionStack) -> Result 346 348 { 347 349 if (target.branchTargetSignature() == Void) … … 354 356 } 355 357 356 auto Validate::addBranch(ControlType& target, ExpressionType condition, const ExpressionList& stack) -> Result358 auto Validate::addBranch(ControlType& target, ExpressionType condition, const Stack& stack) -> Result 357 359 { 358 360 // Void means this is an unconditional branch. … … 361 363 } 362 364 363 auto Validate::addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const ExpressionList& expressionStack) -> Result365 auto Validate::addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const Stack& expressionStack) -> Result 364 366 { 365 367 WASM_VALIDATOR_FAIL_IF(condition != I32, "br_table with non-i32 condition ", condition); … … 384 386 } 385 387 386 auto Validate::endBlock(ControlEntry& entry, ExpressionList& stack) -> Result388 auto Validate::endBlock(ControlEntry& entry, Stack& stack) -> Result 387 389 { 388 390 WASM_FAIL_IF_HELPER_FAILS(unify(stack, entry.controlData)); … … 427 429 } 428 430 429 auto Validate::unify(const ExpressionList& values, const ControlType& block) -> Result431 auto Validate::unify(const Stack& values, const ControlType& block) -> Result 430 432 { 431 433 if (block.signature() == Void) { … … 439 441 } 440 442 441 static void dumpExpressionStack(const CommaPrinter& comma, const Validate:: ExpressionList& expressionStack)443 static void dumpExpressionStack(const CommaPrinter& comma, const Validate::Stack& expressionStack) 442 444 { 443 445 dataLog(comma, " ExpressionStack:"); … … 446 448 } 447 449 448 void Validate::dump(const Vector<ControlEntry>& controlStack, const ExpressionList* expressionStack)450 void Validate::dump(const Vector<ControlEntry>& controlStack, const Stack* expressionStack) 449 451 { 450 452 for (size_t i = controlStack.size(); i--;) { -
trunk/Tools/ChangeLog
r248859 r248878 1 2019-08-19 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] OSR entry to Wasm OMG 4 https://bugs.webkit.org/show_bug.cgi?id=200362 5 6 Reviewed by Michael Saboff. 7 8 * Scripts/run-jsc-stress-tests: 9 1 10 2019-08-19 Zhifei Fang <zhifei_fang@apple.com> 2 11 -
trunk/Tools/Scripts/run-jsc-stress-tests
r248829 r248878 489 489 # We force all tests to use a smaller (1.5M) stack so that stack overflow tests can run faster. 490 490 BASE_OPTIONS = ["--useFTLJIT=false", "--useFunctionDotArguments=true", "--validateExceptionChecks=true", "--useDollarVM=true", "--maxPerThreadStackUsage=1572864"] 491 EAGER_OPTIONS = ["--thresholdForJITAfterWarmUp=10", "--thresholdForJITSoon=10", "--thresholdForOptimizeAfterWarmUp=20", "--thresholdForOptimizeAfterLongWarmUp=20", "--thresholdForOptimizeSoon=20", "--thresholdForFTLOptimizeAfterWarmUp=20", "--thresholdForFTLOptimizeSoon=20", "-- maximumEvalCacheableSourceLength=150000", "--useEagerCodeBlockJettisonTiming=true"]491 EAGER_OPTIONS = ["--thresholdForJITAfterWarmUp=10", "--thresholdForJITSoon=10", "--thresholdForOptimizeAfterWarmUp=20", "--thresholdForOptimizeAfterLongWarmUp=20", "--thresholdForOptimizeSoon=20", "--thresholdForFTLOptimizeAfterWarmUp=20", "--thresholdForFTLOptimizeSoon=20", "--thresholdForOMGOptimizeAfterWarmUp=20", "--thresholdForOMGOptimizeSoon=20", "--maximumEvalCacheableSourceLength=150000", "--useEagerCodeBlockJettisonTiming=true"] 492 492 # NOTE: Tests rely on this using scribbleFreeCells. 493 493 NO_CJIT_OPTIONS = ["--useConcurrentJIT=false", "--thresholdForJITAfterWarmUp=100", "--scribbleFreeCells=true"] … … 1086 1086 if $mode != "quick" 1087 1087 run("wasm-no-cjit-yes-tls-context", "-m", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS)) 1088 run("wasm-eager", "-m", *(FTL_OPTIONS + EAGER_OPTIONS)) 1088 1089 run("wasm-eager-jettison", "-m", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS) 1089 1090 run("wasm-no-call-ic", "-m", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS) … … 1104 1105 if $mode != "quick" 1105 1106 run("wasm-no-cjit-yes-tls-context", "-m", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions)) 1107 run("wasm-eager", "-m", *(FTL_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions)) 1106 1108 run("wasm-eager-jettison", "-m", "--forceCodeBlockToJettisonDueToOldAge=true", *(FTL_OPTIONS + optionalTestSpecificOptions)) 1107 1109 run("wasm-no-call-ic", "-m", "--useCallICsForWebAssemblyToJSCalls=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
Note:
See TracChangeset
for help on using the changeset viewer.