Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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/TypeDecls.h"
23 :
24 : #include "wasm/WasmCode.h"
25 : #include "wasm/WasmTable.h"
26 :
27 : namespace js {
28 : namespace wasm {
29 :
30 : // LinkData contains all the metadata necessary to patch all the locations
31 : // that depend on the absolute address of a CodeSegment.
32 : //
33 : // LinkData is built incrementing by ModuleGenerator and then stored immutably
34 : // in Module.
35 :
36 : struct LinkDataTierCacheablePod
37 : {
38 : uint32_t functionCodeLength;
39 : uint32_t interruptOffset;
40 : uint32_t outOfBoundsOffset;
41 : uint32_t unalignedAccessOffset;
42 :
43 0 : LinkDataTierCacheablePod() { mozilla::PodZero(this); }
44 : };
45 :
46 0 : struct LinkDataTier : LinkDataTierCacheablePod
47 : {
48 : const Tier tier;
49 :
50 0 : explicit LinkDataTier(Tier tier)
51 0 : : tier(tier)
52 : {
53 0 : MOZ_ASSERT(tier == Tier::Baseline || tier == Tier::Ion);
54 0 : }
55 :
56 0 : LinkDataTierCacheablePod& pod() { return *this; }
57 0 : const LinkDataTierCacheablePod& pod() const { return *this; }
58 :
59 : struct InternalLink {
60 : enum Kind {
61 : RawPointer,
62 : CodeLabel,
63 : InstructionImmediate
64 : };
65 : MOZ_INIT_OUTSIDE_CTOR uint32_t patchAtOffset;
66 : MOZ_INIT_OUTSIDE_CTOR uint32_t targetOffset;
67 :
68 : InternalLink() = default;
69 : explicit InternalLink(Kind kind);
70 : bool isRawPointerPatch();
71 : };
72 : typedef Vector<InternalLink, 0, SystemAllocPolicy> InternalLinkVector;
73 :
74 0 : struct SymbolicLinkArray : EnumeratedArray<SymbolicAddress, SymbolicAddress::Limit, Uint32Vector> {
75 : WASM_DECLARE_SERIALIZABLE(SymbolicLinkArray)
76 : };
77 :
78 : InternalLinkVector internalLinks;
79 : SymbolicLinkArray symbolicLinks;
80 :
81 : WASM_DECLARE_SERIALIZABLE(LinkData)
82 : };
83 :
84 : typedef UniquePtr<LinkDataTier> UniqueLinkDataTier;
85 :
86 0 : struct LinkData
87 : {
88 : // `tier_` will become more complicated once tiering is implemented.
89 : UniqueLinkDataTier tier_;
90 :
91 0 : LinkData() : tier_(nullptr) {}
92 :
93 : // Construct the tier_ object.
94 : bool initTier(Tier tier);
95 :
96 : Tiers tiers() const;
97 : const LinkDataTier& linkData(Tier tier) const;
98 : LinkDataTier& linkData(Tier tier);
99 :
100 : WASM_DECLARE_SERIALIZABLE(LinkData)
101 : };
102 :
103 : // Module represents a compiled wasm module and primarily provides two
104 : // operations: instantiation and serialization. A Module can be instantiated any
105 : // number of times to produce new Instance objects. A Module can be serialized
106 : // any number of times such that the serialized bytes can be deserialized later
107 : // to produce a new, equivalent Module.
108 : //
109 : // Fully linked-and-instantiated code (represented by Code and its owned
110 : // CodeSegment) can be shared between instances, provided none of those
111 : // instances are being debugged. If patchable code is needed then each instance
112 : // must have its own Code. Module eagerly creates a new Code and gives it to the
113 : // first instance; it then instantiates new Code objects from a copy of the
114 : // unlinked code that it keeps around for that purpose.
115 :
116 : class Module : public JS::WasmModule
117 : {
118 : const Assumptions assumptions_;
119 : const SharedCode code_;
120 : const UniqueConstBytes unlinkedCodeForDebugging_;
121 : const LinkData linkData_;
122 : const ImportVector imports_;
123 : const ExportVector exports_;
124 : const DataSegmentVector dataSegments_;
125 : const ElemSegmentVector elemSegments_;
126 : const SharedBytes bytecode_;
127 :
128 : // `codeIsBusy_` is set to false initially and then to true when `code_` is
129 : // already being used for an instance and can't be shared because it may be
130 : // patched by the debugger. Subsequent instances must then create copies
131 : // by linking the `unlinkedCodeForDebugging_`.
132 :
133 : mutable mozilla::Atomic<bool> codeIsBusy_;
134 :
135 : bool instantiateFunctions(JSContext* cx, Handle<FunctionVector> funcImports) const;
136 : bool instantiateMemory(JSContext* cx, MutableHandleWasmMemoryObject memory) const;
137 : bool instantiateTable(JSContext* cx,
138 : MutableHandleWasmTableObject table,
139 : SharedTableVector* tables) const;
140 : bool initSegments(JSContext* cx,
141 : HandleWasmInstanceObject instance,
142 : Handle<FunctionVector> funcImports,
143 : HandleWasmMemoryObject memory,
144 : const ValVector& globalImports) const;
145 :
146 : public:
147 0 : Module(Assumptions&& assumptions,
148 : const Code& code,
149 : UniqueConstBytes unlinkedCodeForDebugging,
150 : LinkData&& linkData,
151 : ImportVector&& imports,
152 : ExportVector&& exports,
153 : DataSegmentVector&& dataSegments,
154 : ElemSegmentVector&& elemSegments,
155 : const ShareableBytes& bytecode)
156 0 : : assumptions_(Move(assumptions)),
157 : code_(&code),
158 0 : unlinkedCodeForDebugging_(Move(unlinkedCodeForDebugging)),
159 0 : linkData_(Move(linkData)),
160 0 : imports_(Move(imports)),
161 0 : exports_(Move(exports)),
162 0 : dataSegments_(Move(dataSegments)),
163 0 : elemSegments_(Move(elemSegments)),
164 : bytecode_(&bytecode),
165 0 : codeIsBusy_(false)
166 : {
167 0 : MOZ_ASSERT_IF(metadata().debugEnabled, unlinkedCodeForDebugging_);
168 0 : }
169 0 : ~Module() override { /* Note: can be called on any thread */ }
170 :
171 0 : const Code& code() const { return *code_; }
172 0 : const Metadata& metadata() const { return code_->metadata(); }
173 0 : const MetadataTier& metadata(Tier t) const { return code_->metadata(t); }
174 0 : const ImportVector& imports() const { return imports_; }
175 0 : const ExportVector& exports() const { return exports_; }
176 0 : const Bytes& bytecode() const { return bytecode_->bytes; }
177 0 : uint32_t codeLength(Tier t) const { return code_->segment(t).length(); }
178 :
179 : // Instantiate this module with the given imports:
180 :
181 : bool instantiate(JSContext* cx,
182 : Handle<FunctionVector> funcImports,
183 : HandleWasmTableObject tableImport,
184 : HandleWasmMemoryObject memoryImport,
185 : const ValVector& globalImports,
186 : HandleObject instanceProto,
187 : MutableHandleWasmInstanceObject instanceObj) const;
188 :
189 : // Structured clone support:
190 :
191 : void serializedSize(size_t* maybeBytecodeSize, size_t* maybeCompiledSize) const override;
192 : void serialize(uint8_t* maybeBytecodeBegin, size_t maybeBytecodeSize,
193 : uint8_t* maybeCompiledBegin, size_t maybeCompiledSize) const override;
194 : static bool assumptionsMatch(const Assumptions& current, const uint8_t* compiledBegin,
195 : size_t remain);
196 : static RefPtr<Module> deserialize(const uint8_t* bytecodeBegin, size_t bytecodeSize,
197 : const uint8_t* compiledBegin, size_t compiledSize,
198 : Metadata* maybeMetadata = nullptr);
199 : JSObject* createObject(JSContext* cx) override;
200 :
201 : // about:memory reporting:
202 :
203 : void addSizeOfMisc(MallocSizeOf mallocSizeOf,
204 : Metadata::SeenSet* seenMetadata,
205 : ShareableBytes::SeenSet* seenBytes,
206 : Code::SeenSet* seenCode,
207 : size_t* code, size_t* data) const;
208 :
209 : // Generated code analysis support:
210 :
211 : bool extractCode(JSContext* cx, MutableHandleValue vp) const;
212 : };
213 :
214 : typedef RefPtr<Module> SharedModule;
215 :
216 : // JS API implementations:
217 :
218 : bool
219 : CompiledModuleAssumptionsMatch(PRFileDesc* compiled, JS::BuildIdCharVector&& buildId);
220 :
221 : SharedModule
222 : DeserializeModule(PRFileDesc* bytecode, PRFileDesc* maybeCompiled, JS::BuildIdCharVector&& buildId,
223 : UniqueChars filename, unsigned line, unsigned column);
224 :
225 : } // namespace wasm
226 : } // namespace js
227 :
228 : #endif // wasm_module_h
|