WasmModule.h (8436B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * 4 * Copyright 2015 Mozilla Foundation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #ifndef wasm_module_h 20 #define wasm_module_h 21 22 #include "js/WasmModule.h" 23 #include "js/BuildId.h" 24 25 #include "wasm/WasmCode.h" 26 #include "wasm/WasmException.h" 27 #include "wasm/WasmJS.h" 28 #include "wasm/WasmSerialize.h" 29 #include "wasm/WasmTable.h" 30 31 using mozilla::Maybe; 32 33 namespace JS { 34 class OptimizedEncodingListener; 35 } 36 37 namespace js { 38 namespace wasm { 39 40 struct CompileArgs; 41 42 // In the context of wasm, the OptimizedEncodingListener specifically is 43 // listening for the completion of complete tier-2. 44 45 using CompleteTier2Listener = RefPtr<JS::OptimizedEncodingListener>; 46 47 // Report tier-2 compilation results off-thread. If `maybeFuncIndex` is 48 // `Some`, this report is for a partial tier-2 compilation of the specified 49 // function. Otherwise it's for a complete tier-2 compilation. 50 51 void ReportTier2ResultsOffThread(bool cancelled, bool success, 52 Maybe<uint32_t> maybeFuncIndex, 53 const ScriptedCaller& scriptedCaller, 54 const UniqueChars& error, 55 const UniqueCharsVector& warnings); 56 57 // A struct containing the typed, imported values that are harvested from the 58 // import object and passed to Module::instantiate(). This struct must be 59 // stored in a (Persistent)Rooted, not in the heap due to its use of TraceRoot() 60 // and complete lack of barriers. 61 62 struct ImportValues { 63 JSObjectVector funcs; 64 WasmTableObjectVector tables; 65 WasmMemoryObjectVector memories; 66 WasmTagObjectVector tagObjs; 67 WasmGlobalObjectVector globalObjs; 68 ValVector globalValues; 69 70 ImportValues() {} 71 72 void trace(JSTracer* trc) { 73 funcs.trace(trc); 74 tables.trace(trc); 75 memories.trace(trc); 76 tagObjs.trace(trc); 77 globalObjs.trace(trc); 78 globalValues.trace(trc); 79 } 80 }; 81 82 // Module represents a compiled wasm module and primarily provides three 83 // operations: instantiation, tiered compilation, serialization. A Module can be 84 // instantiated any number of times to produce new Instance objects. A Module 85 // can have a single tier-2 task initiated to augment a Module's code with a 86 // higher tier. A Module can have its optimized code serialized at any point 87 // where the LinkData is also available, which is primarily (1) at the end of 88 // module generation, (2) at the end of tier-2 compilation. 89 // 90 // Fully linked-and-instantiated code (represented by SharedCode) can be shared 91 // between instances. 92 93 class Module : public JS::WasmModule { 94 // This has the same lifetime end as Module itself -- it can be dropped when 95 // Module itself is dropped. 96 const SharedModuleMetadata moduleMeta_; 97 98 // This contains all compilation artifacts for the module. 99 const SharedCode code_; 100 101 // This field is set during complete tier-2 compilation and cleared on 102 // success or failure. These happen on different threads and are serialized 103 // by the control flow of helper tasks. 104 105 mutable CompleteTier2Listener completeTier2Listener_; 106 107 // This flag is used for logging (and testing) purposes to indicate 108 // whether the module was deserialized (from a cache). 109 110 const bool loggingDeserialized_; 111 112 // This flag is only used for testing purposes and is cleared on success or 113 // failure. The field is racily polled from various threads. 114 115 mutable mozilla::Atomic<bool> testingTier2Active_; 116 117 // Cached malloc allocation size for GC memory tracking. 118 119 size_t gcMallocBytesExcludingCode_; 120 121 bool instantiateFunctions(JSContext* cx, 122 const JSObjectVector& funcImports) const; 123 bool instantiateMemories( 124 JSContext* cx, const WasmMemoryObjectVector& memoryImports, 125 MutableHandle<WasmMemoryObjectVector> memoryObjs) const; 126 bool instantiateTags(JSContext* cx, WasmTagObjectVector& tagObjs) const; 127 bool instantiateImportedTable(JSContext* cx, const TableDesc& td, 128 Handle<WasmTableObject*> table, 129 WasmTableObjectVector* tableObjs, 130 SharedTableVector* tables) const; 131 bool instantiateLocalTable(JSContext* cx, const TableDesc& td, 132 WasmTableObjectVector* tableObjs, 133 SharedTableVector* tables) const; 134 bool instantiateTables(JSContext* cx, 135 const WasmTableObjectVector& tableImports, 136 MutableHandle<WasmTableObjectVector> tableObjs, 137 SharedTableVector* tables) const; 138 bool instantiateGlobals(JSContext* cx, const ValVector& globalImportValues, 139 WasmGlobalObjectVector& globalObjs) const; 140 141 class CompleteTier2GeneratorTaskImpl; 142 143 public: 144 class PartialTier2CompileTaskImpl; 145 146 Module(const ModuleMetadata& moduleMeta, const Code& code, 147 bool loggingDeserialized = false) 148 : moduleMeta_(&moduleMeta), 149 code_(&code), 150 loggingDeserialized_(loggingDeserialized), 151 testingTier2Active_(false) { 152 initGCMallocBytesExcludingCode(); 153 } 154 ~Module() override; 155 156 const Code& code() const { return *code_; } 157 const ModuleMetadata& moduleMeta() const { return *moduleMeta_; } 158 const CodeMetadata& codeMeta() const { return code_->codeMeta(); } 159 const CodeTailMetadata& codeTailMeta() const { return code_->codeTailMeta(); } 160 const CodeMetadataForAsmJS* codeMetaForAsmJS() const { 161 return code_->codeMetaForAsmJS(); 162 } 163 const BytecodeSource& debugBytecode() const { 164 return codeTailMeta().debugBytecode.source(); 165 } 166 uint32_t tier1CodeMemoryUsed() const { return code_->tier1CodeMemoryUsed(); } 167 168 // Instantiate this module with the given imports: 169 170 bool instantiate(JSContext* cx, ImportValues& imports, 171 HandleObject instanceProto, 172 MutableHandle<WasmInstanceObject*> instanceObj) const; 173 174 // Tier-2 compilation may be initiated after the Module is constructed at 175 // most once. When tier-2 compilation completes, ModuleGenerator calls 176 // finishTier2() from a helper thread, passing tier-variant data which will 177 // be installed and made visible. 178 179 void startTier2(const ShareableBytes* codeSection, 180 JS::OptimizedEncodingListener* listener); 181 bool finishTier2(UniqueCodeBlock tier2CodeBlock, UniqueLinkData tier2LinkData, 182 const CompileAndLinkStats& tier2Stats) const; 183 184 void testingBlockOnTier2Complete() const; 185 bool testingTier2Active() const { return testingTier2Active_; } 186 187 // Code caching support. 188 189 bool canSerialize() const; 190 [[nodiscard]] bool serialize(Bytes* bytes) const; 191 static RefPtr<Module> deserialize(const uint8_t* begin, size_t size); 192 bool loggingDeserialized() const { return loggingDeserialized_; } 193 194 // JS API and JS::WasmModule implementation: 195 196 JSObject* createObject(JSContext* cx) const override; 197 JSObject* createObjectForAsmJS(JSContext* cx) const override; 198 199 // about:memory reporting: 200 201 void addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, 202 CodeMetadata::SeenSet* seenCodeMeta, 203 CodeMetadataForAsmJS::SeenSet* seenCodeMetaForAsmJS, 204 Code::SeenSet* seenCode, size_t* code, size_t* data) const; 205 206 // GC malloc memory tracking: 207 208 void initGCMallocBytesExcludingCode(); 209 size_t gcMallocBytesExcludingCode() const { 210 return gcMallocBytesExcludingCode_; 211 } 212 213 // Generated code analysis support: 214 215 bool extractCode(JSContext* cx, Tier tier, MutableHandleValue vp) const; 216 217 WASM_DECLARE_FRIEND_SERIALIZE(Module); 218 }; 219 220 using MutableModule = RefPtr<Module>; 221 using SharedModule = RefPtr<const Module>; 222 223 // JS API implementations: 224 225 [[nodiscard]] bool GetOptimizedEncodingBuildId(JS::BuildIdCharVector* buildId); 226 227 } // namespace wasm 228 } // namespace js 229 230 #endif // wasm_module_h