Source code

Revision control

Other Tools

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
*
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/BuildId.h"
23
24
#include "wasm/WasmCode.h"
25
#include "wasm/WasmTable.h"
26
27
namespace js {
28
namespace wasm {
29
30
struct CompileArgs;
31
32
// In the context of wasm, the OptimizedEncodingListener specifically is
33
// listening for the completion of tier-2.
34
35
typedef RefPtr<JS::OptimizedEncodingListener> Tier2Listener;
36
37
// A struct containing the typed, imported values that are harvested from the
38
// import object and passed to Module::instantiate(). This struct must be
39
// stored in a (Persistent)Rooted, not in the heap due to its use of TraceRoot()
40
// and complete lack of barriers.
41
42
struct ImportValues {
43
JSFunctionVector funcs;
44
WasmTableObjectVector tables;
45
WasmMemoryObject* memory;
46
WasmGlobalObjectVector globalObjs;
47
ValVector globalValues;
48
49
ImportValues() : memory(nullptr) {}
50
51
void trace(JSTracer* trc) {
52
funcs.trace(trc);
53
tables.trace(trc);
54
if (memory) {
55
TraceRoot(trc, &memory, "import values memory");
56
}
57
globalObjs.trace(trc);
58
globalValues.trace(trc);
59
}
60
};
61
62
// Module represents a compiled wasm module and primarily provides three
63
// operations: instantiation, tiered compilation, serialization. A Module can be
64
// instantiated any number of times to produce new Instance objects. A Module
65
// can have a single tier-2 task initiated to augment a Module's code with a
66
// higher tier. A Module can have its optimized code serialized at any point
67
// where the LinkData is also available, which is primarily (1) at the end of
68
// module generation, (2) at the end of tier-2 compilation.
69
//
70
// Fully linked-and-instantiated code (represented by Code and its owned
71
// ModuleSegment) can be shared between instances, provided none of those
72
// instances are being debugged. If patchable code is needed then each instance
73
// must have its own Code. Module eagerly creates a new Code and gives it to the
74
// first instance; it then instantiates new Code objects from a copy of the
75
// unlinked code that it keeps around for that purpose.
76
77
class Module : public JS::WasmModule {
78
const SharedCode code_;
79
const ImportVector imports_;
80
const ExportVector exports_;
81
const DataSegmentVector dataSegments_;
82
const ElemSegmentVector elemSegments_;
83
const CustomSectionVector customSections_;
84
85
// These fields are only meaningful when code_->metadata().debugEnabled.
86
// `debugCodeClaimed_` is set to false initially and then to true when
87
// `code_` is already being used for an instance and can't be shared because
88
// it may be patched by the debugger. Subsequent instances must then create
89
// copies by linking the `debugUnlinkedCode_` using `debugLinkData_`.
90
// This could all be removed if debugging didn't need to perform
91
// per-instance code patching.
92
93
mutable Atomic<bool> debugCodeClaimed_;
94
const UniqueConstBytes debugUnlinkedCode_;
95
const UniqueLinkData debugLinkData_;
96
const SharedBytes debugBytecode_;
97
98
// This field is set during tier-2 compilation and cleared on success or
99
// failure. These happen on different threads and are serialized by the
100
// control flow of helper tasks.
101
102
mutable Tier2Listener tier2Listener_;
103
104
// This flag is used for logging (and testing) purposes to indicate
105
// whether the module was deserialized (from a cache).
106
107
const bool loggingDeserialized_;
108
109
// This flag is only used for testing purposes and is cleared on success or
110
// failure. The field is racily polled from various threads.
111
112
mutable Atomic<bool> testingTier2Active_;
113
114
// Cached malloc allocation size for GC memory tracking.
115
116
size_t gcMallocBytesExcludingCode_;
117
118
bool instantiateFunctions(JSContext* cx,
119
const JSFunctionVector& funcImports) const;
120
bool instantiateMemory(JSContext* cx,
121
MutableHandleWasmMemoryObject memory) const;
122
bool instantiateImportedTable(JSContext* cx, const TableDesc& td,
123
Handle<WasmTableObject*> table,
124
WasmTableObjectVector* tableObjs,
125
SharedTableVector* tables) const;
126
bool instantiateLocalTable(JSContext* cx, const TableDesc& td,
127
WasmTableObjectVector* tableObjs,
128
SharedTableVector* tables) const;
129
bool instantiateTables(JSContext* cx,
130
const WasmTableObjectVector& tableImports,
131
MutableHandle<WasmTableObjectVector> tableObjs,
132
SharedTableVector* tables) const;
133
bool instantiateGlobals(JSContext* cx, const ValVector& globalImportValues,
134
WasmGlobalObjectVector& globalObjs) const;
135
bool initSegments(JSContext* cx, HandleWasmInstanceObject instance,
136
HandleWasmMemoryObject memory,
137
const ValVector& globalImportValues) const;
138
SharedCode getDebugEnabledCode() const;
139
bool makeStructTypeDescrs(
140
JSContext* cx,
141
MutableHandle<StructTypeDescrVector> structTypeDescrs) const;
142
143
class Tier2GeneratorTaskImpl;
144
145
public:
146
Module(const Code& code, ImportVector&& imports, ExportVector&& exports,
147
DataSegmentVector&& dataSegments, ElemSegmentVector&& elemSegments,
148
CustomSectionVector&& customSections,
149
UniqueConstBytes debugUnlinkedCode = nullptr,
150
UniqueLinkData debugLinkData = nullptr,
151
const ShareableBytes* debugBytecode = nullptr,
152
bool loggingDeserialized = false)
153
: code_(&code),
154
imports_(std::move(imports)),
155
exports_(std::move(exports)),
156
dataSegments_(std::move(dataSegments)),
157
elemSegments_(std::move(elemSegments)),
158
customSections_(std::move(customSections)),
159
debugCodeClaimed_(false),
160
debugUnlinkedCode_(std::move(debugUnlinkedCode)),
161
debugLinkData_(std::move(debugLinkData)),
162
debugBytecode_(debugBytecode),
163
loggingDeserialized_(loggingDeserialized),
164
testingTier2Active_(false) {
165
MOZ_ASSERT_IF(metadata().debugEnabled,
166
debugUnlinkedCode_ && debugLinkData_);
167
initGCMallocBytesExcludingCode();
168
}
169
~Module() override;
170
171
const Code& code() const { return *code_; }
172
const ModuleSegment& moduleSegment(Tier t) const { return code_->segment(t); }
173
const Metadata& metadata() const { return code_->metadata(); }
174
const MetadataTier& metadata(Tier t) const { return code_->metadata(t); }
175
const ImportVector& imports() const { return imports_; }
176
const ExportVector& exports() const { return exports_; }
177
const CustomSectionVector& customSections() const { return customSections_; }
178
const Bytes& debugBytecode() const { return debugBytecode_->bytes; }
179
uint32_t codeLength(Tier t) const { return code_->segment(t).length(); }
180
const StructTypeVector& structTypes() const { return code_->structTypes(); }
181
182
// Instantiate this module with the given imports:
183
184
bool instantiate(JSContext* cx, ImportValues& imports,
185
HandleObject instanceProto,
186
MutableHandleWasmInstanceObject instanceObj) const;
187
188
// Tier-2 compilation may be initiated after the Module is constructed at
189
// most once. When tier-2 compilation completes, ModuleGenerator calls
190
// finishTier2() from a helper thread, passing tier-variant data which will
191
// be installed and made visible.
192
193
void startTier2(const CompileArgs& args, const ShareableBytes& bytecode,
194
JS::OptimizedEncodingListener* listener);
195
bool finishTier2(const LinkData& linkData2, UniqueCodeTier code2) const;
196
197
void testingBlockOnTier2Complete() const;
198
bool testingTier2Active() const { return testingTier2Active_; }
199
200
// Code caching support.
201
202
size_t serializedSize(const LinkData& linkData) const;
203
void serialize(const LinkData& linkData, uint8_t* begin, size_t size) const;
204
void serialize(const LinkData& linkData,
205
JS::OptimizedEncodingListener& listener) const;
206
static RefPtr<Module> deserialize(const uint8_t* begin, size_t size,
207
Metadata* maybeMetadata = nullptr);
208
bool loggingDeserialized() const { return loggingDeserialized_; }
209
210
// JS API and JS::WasmModule implementation:
211
212
JSObject* createObject(JSContext* cx) override;
213
214
// about:memory reporting:
215
216
void addSizeOfMisc(MallocSizeOf mallocSizeOf, Metadata::SeenSet* seenMetadata,
217
Code::SeenSet* seenCode, size_t* code, size_t* data) const;
218
219
// GC malloc memory tracking:
220
221
void initGCMallocBytesExcludingCode();
222
size_t gcMallocBytesExcludingCode() const {
223
return gcMallocBytesExcludingCode_;
224
}
225
226
// Generated code analysis support:
227
228
bool extractCode(JSContext* cx, Tier tier, MutableHandleValue vp) const;
229
};
230
231
typedef RefPtr<Module> MutableModule;
232
typedef RefPtr<const Module> SharedModule;
233
234
// JS API implementations:
235
236
MOZ_MUST_USE bool GetOptimizedEncodingBuildId(JS::BuildIdCharVector* buildId);
237
238
} // namespace wasm
239
} // namespace js
240
241
#endif // wasm_module_h