Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/src/wasm/WasmJS.h
Line
Count
Source (jump to first uncovered line)
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 2016 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_js_h
20
#define wasm_js_h
21
22
#include "gc/Policy.h"
23
#include "vm/NativeObject.h"
24
#include "wasm/WasmTypes.h"
25
26
namespace js {
27
28
class GlobalObject;
29
class StructTypeDescr;
30
class TypedArrayObject;
31
class WasmFunctionScope;
32
class WasmInstanceScope;
33
class SharedArrayRawBuffer;
34
35
namespace wasm {
36
37
// Return whether WebAssembly can be compiled on this platform.
38
// This must be checked and must be true to call any of the top-level wasm
39
// eval/compile methods.
40
41
bool
42
HasCompilerSupport(JSContext* cx);
43
44
// Return whether WebAssembly is supported on this platform. This determines
45
// whether the WebAssembly object is exposed to JS and takes into account
46
// configuration options that disable various modes.
47
48
bool
49
HasSupport(JSContext* cx);
50
51
// Return whether WebAssembly streaming/caching is supported on this platform.
52
// This takes into account prefs and necessary embedding callbacks.
53
54
bool
55
HasStreamingSupport(JSContext* cx);
56
57
bool
58
HasCachingSupport(JSContext* cx);
59
60
// Compiles the given binary wasm module given the ArrayBufferObject
61
// and links the module's imports with the given import object.
62
63
MOZ_MUST_USE bool
64
Eval(JSContext* cx, Handle<TypedArrayObject*> code, HandleObject importObj,
65
     MutableHandleWasmInstanceObject instanceObj);
66
67
// These accessors can be used to probe JS values for being an exported wasm
68
// function.
69
70
extern bool
71
IsExportedFunction(JSFunction* fun);
72
73
extern bool
74
IsExportedWasmFunction(JSFunction* fun);
75
76
extern bool
77
IsExportedFunction(const Value& v, MutableHandleFunction f);
78
79
extern Instance&
80
ExportedFunctionToInstance(JSFunction* fun);
81
82
extern WasmInstanceObject*
83
ExportedFunctionToInstanceObject(JSFunction* fun);
84
85
extern uint32_t
86
ExportedFunctionToFuncIndex(JSFunction* fun);
87
88
extern bool
89
IsSharedWasmMemoryObject(JSObject* obj);
90
91
} // namespace wasm
92
93
// The class of the WebAssembly global namespace object.
94
95
extern const Class WebAssemblyClass;
96
97
JSObject*
98
InitWebAssemblyClass(JSContext* cx, Handle<GlobalObject*> global);
99
100
// The class of WebAssembly.Module. Each WasmModuleObject owns a
101
// wasm::Module. These objects are used both as content-facing JS objects and as
102
// internal implementation details of asm.js.
103
104
class WasmModuleObject : public NativeObject
105
{
106
    static const unsigned MODULE_SLOT = 0;
107
    static const ClassOps classOps_;
108
    static void finalize(FreeOp* fop, JSObject* obj);
109
    static bool imports(JSContext* cx, unsigned argc, Value* vp);
110
    static bool exports(JSContext* cx, unsigned argc, Value* vp);
111
    static bool customSections(JSContext* cx, unsigned argc, Value* vp);
112
113
  public:
114
    static const unsigned RESERVED_SLOTS = 1;
115
    static const Class class_;
116
    static const JSPropertySpec properties[];
117
    static const JSFunctionSpec methods[];
118
    static const JSFunctionSpec static_methods[];
119
    static bool construct(JSContext*, unsigned, Value*);
120
121
    static WasmModuleObject* create(JSContext* cx,
122
                                    const wasm::Module& module,
123
                                    HandleObject proto = nullptr);
124
    const wasm::Module& module() const;
125
};
126
127
// The class of WebAssembly.Global.  This wraps a storage location, and there is
128
// a per-agent one-to-one relationship between the WasmGlobalObject and the
129
// storage location (the Cell) it wraps: if a module re-exports an imported
130
// global, the imported and exported WasmGlobalObjects are the same, and if a
131
// module exports a global twice, the two exported WasmGlobalObjects are the
132
// same.
133
134
class WasmGlobalObject : public NativeObject
135
{
136
    static const unsigned TYPE_SLOT = 0;
137
    static const unsigned MUTABLE_SLOT = 1;
138
    static const unsigned CELL_SLOT = 2;
139
140
    static const ClassOps classOps_;
141
    static void finalize(FreeOp*, JSObject* obj);
142
    static void trace(JSTracer* trc, JSObject* obj);
143
144
    static bool valueGetterImpl(JSContext* cx, const CallArgs& args);
145
    static bool valueGetter(JSContext* cx, unsigned argc, Value* vp);
146
    static bool valueSetterImpl(JSContext* cx, const CallArgs& args);
147
    static bool valueSetter(JSContext* cx, unsigned argc, Value* vp);
148
149
  public:
150
    // For exposed globals the Cell holds the value of the global; the
151
    // instance's global area holds a pointer to the Cell.
152
    union Cell {
153
        int32_t   i32;
154
        int64_t   i64;
155
        float     f32;
156
        double    f64;
157
        JSObject* ptr;
158
0
        Cell() : i64(0) {}
159
0
        ~Cell() {}
160
    };
161
162
    static const unsigned RESERVED_SLOTS = 3;
163
    static const Class class_;
164
    static const JSPropertySpec properties[];
165
    static const JSFunctionSpec methods[];
166
    static const JSFunctionSpec static_methods[];
167
    static bool construct(JSContext*, unsigned, Value*);
168
169
    static WasmGlobalObject* create(JSContext* cx, wasm::HandleVal value, bool isMutable);
170
0
    bool isNewborn() { return getReservedSlot(CELL_SLOT).isUndefined(); }
171
172
    wasm::ValType type() const;
173
    void val(wasm::MutableHandleVal outval) const;
174
    bool isMutable() const;
175
    // value() will MOZ_CRASH if the type is int64
176
    Value value(JSContext* cx) const;
177
    Cell* cell() const;
178
};
179
180
// The class of WebAssembly.Instance. Each WasmInstanceObject owns a
181
// wasm::Instance. These objects are used both as content-facing JS objects and
182
// as internal implementation details of asm.js.
183
184
class WasmInstanceObject : public NativeObject
185
{
186
    static const unsigned INSTANCE_SLOT = 0;
187
    static const unsigned EXPORTS_OBJ_SLOT = 1;
188
    static const unsigned EXPORTS_SLOT = 2;
189
    static const unsigned SCOPES_SLOT = 3;
190
    static const unsigned INSTANCE_SCOPE_SLOT = 4;
191
    static const unsigned GLOBALS_SLOT = 5;
192
193
    static const ClassOps classOps_;
194
    static bool exportsGetterImpl(JSContext* cx, const CallArgs& args);
195
    static bool exportsGetter(JSContext* cx, unsigned argc, Value* vp);
196
    bool isNewborn() const;
197
    static void finalize(FreeOp* fop, JSObject* obj);
198
    static void trace(JSTracer* trc, JSObject* obj);
199
200
    // ExportMap maps from function index to exported function object.
201
    // This allows the instance to lazily create exported function
202
    // objects on demand (instead up-front for all table elements) while
203
    // correctly preserving observable function object identity.
204
    using ExportMap = GCHashMap<uint32_t,
205
                                HeapPtr<JSFunction*>,
206
                                DefaultHasher<uint32_t>,
207
                                SystemAllocPolicy>;
208
    ExportMap& exports() const;
209
210
    // WeakScopeMap maps from function index to js::Scope. This maps is weak
211
    // to avoid holding scope objects alive. The scopes are normally created
212
    // during debugging.
213
    using ScopeMap = JS::WeakCache<GCHashMap<uint32_t,
214
                                             ReadBarriered<WasmFunctionScope*>,
215
                                             DefaultHasher<uint32_t>,
216
                                             SystemAllocPolicy>>;
217
    ScopeMap& scopes() const;
218
219
  public:
220
    static const unsigned RESERVED_SLOTS = 6;
221
    static const Class class_;
222
    static const JSPropertySpec properties[];
223
    static const JSFunctionSpec methods[];
224
    static const JSFunctionSpec static_methods[];
225
    static bool construct(JSContext*, unsigned, Value*);
226
227
    static WasmInstanceObject* create(JSContext* cx,
228
                                      RefPtr<const wasm::Code> code,
229
                                      const wasm::DataSegmentVector& dataSegments,
230
                                      const wasm::ElemSegmentVector& elemSegments,
231
                                      wasm::UniqueTlsData tlsData,
232
                                      HandleWasmMemoryObject memory,
233
                                      Vector<RefPtr<wasm::Table>, 0, SystemAllocPolicy>&& tables,
234
                                      GCVector<HeapPtr<StructTypeDescr*>, 0, SystemAllocPolicy>&& structTypeDescrs,
235
                                      Handle<FunctionVector> funcImports,
236
                                      const wasm::GlobalDescVector& globals,
237
                                      wasm::HandleValVector globalImportValues,
238
                                      const WasmGlobalObjectVector& globalObjs,
239
                                      HandleObject proto,
240
                                      UniquePtr<wasm::DebugState> maybeDebug);
241
    void initExportsObj(JSObject& exportsObj);
242
243
    wasm::Instance& instance() const;
244
    JSObject& exportsObj() const;
245
246
    static bool getExportedFunction(JSContext* cx,
247
                                    HandleWasmInstanceObject instanceObj,
248
                                    uint32_t funcIndex,
249
                                    MutableHandleFunction fun);
250
251
    const wasm::CodeRange& getExportedFunctionCodeRange(JSFunction* fun, wasm::Tier tier);
252
253
    static WasmInstanceScope* getScope(JSContext* cx, HandleWasmInstanceObject instanceObj);
254
    static WasmFunctionScope* getFunctionScope(JSContext* cx,
255
                                               HandleWasmInstanceObject instanceObj,
256
                                               uint32_t funcIndex);
257
258
    WasmGlobalObjectVector& indirectGlobals() const;
259
};
260
261
// The class of WebAssembly.Memory. A WasmMemoryObject references an ArrayBuffer
262
// or SharedArrayBuffer object which owns the actual memory.
263
264
class WasmMemoryObject : public NativeObject
265
{
266
    static const unsigned BUFFER_SLOT = 0;
267
    static const unsigned OBSERVERS_SLOT = 1;
268
    static const ClassOps classOps_;
269
    static void finalize(FreeOp* fop, JSObject* obj);
270
    static bool bufferGetterImpl(JSContext* cx, const CallArgs& args);
271
    static bool bufferGetter(JSContext* cx, unsigned argc, Value* vp);
272
    static bool growImpl(JSContext* cx, const CallArgs& args);
273
    static bool grow(JSContext* cx, unsigned argc, Value* vp);
274
    static uint32_t growShared(HandleWasmMemoryObject memory, uint32_t delta);
275
276
    using InstanceSet = JS::WeakCache<GCHashSet<ReadBarrieredWasmInstanceObject,
277
                                                MovableCellHasher<ReadBarrieredWasmInstanceObject>,
278
                                                SystemAllocPolicy>>;
279
    bool hasObservers() const;
280
    InstanceSet& observers() const;
281
    InstanceSet* getOrCreateObservers(JSContext* cx);
282
283
  public:
284
    static const unsigned RESERVED_SLOTS = 2;
285
    static const Class class_;
286
    static const JSPropertySpec properties[];
287
    static const JSFunctionSpec methods[];
288
    static const JSFunctionSpec static_methods[];
289
    static bool construct(JSContext*, unsigned, Value*);
290
291
    static WasmMemoryObject* create(JSContext* cx,
292
                                    Handle<ArrayBufferObjectMaybeShared*> buffer,
293
                                    HandleObject proto);
294
295
    // `buffer()` returns the current buffer object always.  If the buffer
296
    // represents shared memory then `buffer().byteLength()` never changes, and
297
    // in particular it may be a smaller value than that returned from
298
    // `volatileMemoryLength()` below.
299
    //
300
    // Generally, you do not want to call `buffer().byteLength()`, but to call
301
    // `volatileMemoryLength()`, instead.
302
    ArrayBufferObjectMaybeShared& buffer() const;
303
304
    // The current length of the memory.  In the case of shared memory, the
305
    // length can change at any time.  Also note that this will acquire a lock
306
    // for shared memory, so do not call this from a signal handler.
307
    uint32_t volatileMemoryLength() const;
308
309
    bool isShared() const;
310
    bool movingGrowable() const;
311
312
    // If isShared() is true then obtain the underlying buffer object.
313
    SharedArrayRawBuffer* sharedArrayRawBuffer() const;
314
315
    bool addMovingGrowObserver(JSContext* cx, WasmInstanceObject* instance);
316
    static uint32_t grow(HandleWasmMemoryObject memory, uint32_t delta, JSContext* cx);
317
};
318
319
// The class of WebAssembly.Table. A WasmTableObject holds a refcount on a
320
// wasm::Table, allowing a Table to be shared between multiple Instances
321
// (eventually between multiple threads).
322
323
class WasmTableObject : public NativeObject
324
{
325
    static const unsigned TABLE_SLOT = 0;
326
    static const ClassOps classOps_;
327
    bool isNewborn() const;
328
    static void finalize(FreeOp* fop, JSObject* obj);
329
    static void trace(JSTracer* trc, JSObject* obj);
330
    static bool lengthGetterImpl(JSContext* cx, const CallArgs& args);
331
    static bool lengthGetter(JSContext* cx, unsigned argc, Value* vp);
332
    static bool getImpl(JSContext* cx, const CallArgs& args);
333
    static bool get(JSContext* cx, unsigned argc, Value* vp);
334
    static bool setImpl(JSContext* cx, const CallArgs& args);
335
    static bool set(JSContext* cx, unsigned argc, Value* vp);
336
    static bool growImpl(JSContext* cx, const CallArgs& args);
337
    static bool grow(JSContext* cx, unsigned argc, Value* vp);
338
339
  public:
340
    static const unsigned RESERVED_SLOTS = 1;
341
    static const Class class_;
342
    static const JSPropertySpec properties[];
343
    static const JSFunctionSpec methods[];
344
    static const JSFunctionSpec static_methods[];
345
    static bool construct(JSContext*, unsigned, Value*);
346
347
    // Note that, after creation, a WasmTableObject's table() is not initialized
348
    // and must be initialized before use.
349
350
    static WasmTableObject* create(JSContext* cx, const wasm::Limits& limits);
351
    wasm::Table& table() const;
352
};
353
354
} // namespace js
355
356
#endif // wasm_js_h