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 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
*
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_instance_h
20
#define wasm_instance_h
21
22
#include "builtin/TypedObject.h"
23
#include "gc/Barrier.h"
24
#include "gc/Zone.h"
25
#include "vm/SharedMem.h"
26
#include "wasm/WasmCode.h"
27
#include "wasm/WasmDebug.h"
28
#include "wasm/WasmFrameIter.h" // js::wasm::WasmFrameIter
29
#include "wasm/WasmProcess.h"
30
#include "wasm/WasmTable.h"
31
32
namespace js {
33
namespace wasm {
34
35
// Instance represents a wasm instance and provides all the support for runtime
36
// execution of code in the instance. Instances share various immutable data
37
// structures with the Module from which they were instantiated and other
38
// instances instantiated from the same Module. However, an Instance has no
39
// direct reference to its source Module which allows a Module to be destroyed
40
// while it still has live Instances.
41
//
42
// The instance's code may be shared among multiple instances provided none of
43
// those instances are being debugged. Instances that are being debugged own
44
// their code.
45
46
class Instance {
47
JS::Realm* const realm_;
48
WeakHeapPtrWasmInstanceObject object_;
49
void* jsJitArgsRectifier_;
50
void* jsJitExceptionHandler_;
51
void* preBarrierCode_;
52
const SharedCode code_;
53
const UniqueTlsData tlsData_;
54
const GCPtrWasmMemoryObject memory_;
55
const SharedTableVector tables_;
56
DataSegmentVector passiveDataSegments_;
57
ElemSegmentVector passiveElemSegments_;
58
const UniqueDebugState maybeDebug_;
59
StructTypeDescrVector structTypeDescrs_;
60
61
// Internal helpers:
62
const void** addressOfFuncTypeId(const FuncTypeIdDesc& funcTypeId) const;
63
FuncImportTls& funcImportTls(const FuncImport& fi);
64
TableTls& tableTls(const TableDesc& td) const;
65
66
// Only WasmInstanceObject can call the private trace function.
67
friend class js::WasmInstanceObject;
68
void tracePrivate(JSTracer* trc);
69
70
bool callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc,
71
const uint64_t* argv, MutableHandleValue rval);
72
73
public:
74
Instance(JSContext* cx, HandleWasmInstanceObject object, SharedCode code,
75
UniqueTlsData tlsData, HandleWasmMemoryObject memory,
76
SharedTableVector&& tables, StructTypeDescrVector&& structTypeDescrs,
77
const JSFunctionVector& funcImports,
78
const ValVector& globalImportValues,
79
const WasmGlobalObjectVector& globalObjs,
80
UniqueDebugState maybeDebug);
81
~Instance();
82
bool init(JSContext* cx, const DataSegmentVector& dataSegments,
83
const ElemSegmentVector& elemSegments);
84
void trace(JSTracer* trc);
85
86
// Trace any GC roots on the stack, for the frame associated with |wfi|,
87
// whose next instruction to execute is |nextPC|.
88
//
89
// For consistency checking of StackMap sizes in debug builds, this also
90
// takes |highestByteVisitedInPrevFrame|, which is the address of the
91
// highest byte scanned in the frame below this one on the stack, and in
92
// turn it returns the address of the highest byte scanned in this frame.
93
uintptr_t traceFrame(JSTracer* trc, const wasm::WasmFrameIter& wfi,
94
uint8_t* nextPC,
95
uintptr_t highestByteVisitedInPrevFrame);
96
97
JS::Realm* realm() const { return realm_; }
98
const Code& code() const { return *code_; }
99
const CodeTier& code(Tier t) const { return code_->codeTier(t); }
100
bool debugEnabled() const { return !!maybeDebug_; }
101
DebugState& debug() { return *maybeDebug_; }
102
const ModuleSegment& moduleSegment(Tier t) const { return code_->segment(t); }
103
TlsData* tlsData() const { return tlsData_.get(); }
104
uint8_t* globalData() const { return (uint8_t*)&tlsData_->globalArea; }
105
uint8_t* codeBase(Tier t) const { return code_->segment(t).base(); }
106
const MetadataTier& metadata(Tier t) const { return code_->metadata(t); }
107
const Metadata& metadata() const { return code_->metadata(); }
108
bool isAsmJS() const { return metadata().isAsmJS(); }
109
const SharedTableVector& tables() const { return tables_; }
110
SharedMem<uint8_t*> memoryBase() const;
111
WasmMemoryObject* memory() const;
112
size_t memoryMappedSize() const;
113
SharedArrayRawBuffer* sharedMemoryBuffer() const; // never null
114
bool memoryAccessInGuardRegion(uint8_t* addr, unsigned numBytes) const;
115
bool memoryAccessInBounds(uint8_t* addr, unsigned numBytes) const;
116
const StructTypeVector& structTypes() const { return code_->structTypes(); }
117
118
static constexpr size_t offsetOfJSJitArgsRectifier() {
119
return offsetof(Instance, jsJitArgsRectifier_);
120
}
121
static constexpr size_t offsetOfJSJitExceptionHandler() {
122
return offsetof(Instance, jsJitExceptionHandler_);
123
}
124
static constexpr size_t offsetOfPreBarrierCode() {
125
return offsetof(Instance, preBarrierCode_);
126
}
127
128
// This method returns a pointer to the GC object that owns this Instance.
129
// Instances may be reached via weak edges (e.g., Realm::instances_)
130
// so this perform a read-barrier on the returned object unless the barrier
131
// is explicitly waived.
132
133
WasmInstanceObject* object() const;
134
WasmInstanceObject* objectUnbarriered() const;
135
136
// Execute the given export given the JS call arguments, storing the return
137
// value in args.rval.
138
139
MOZ_MUST_USE bool callExport(JSContext* cx, uint32_t funcIndex,
140
CallArgs args);
141
142
// Return the name associated with a given function index, or generate one
143
// if none was given by the module.
144
145
JSAtom* getFuncDisplayAtom(JSContext* cx, uint32_t funcIndex) const;
146
void ensureProfilingLabels(bool profilingEnabled) const;
147
148
// Initially, calls to imports in wasm code call out through the generic
149
// callImport method. If the imported callee gets JIT compiled and the types
150
// match up, callImport will patch the code to instead call through a thunk
151
// directly into the JIT code. If the JIT code is released, the Instance must
152
// be notified so it can go back to the generic callImport.
153
154
void deoptimizeImportExit(uint32_t funcImportIndex);
155
156
// Called by Wasm(Memory|Table)Object when a moving resize occurs:
157
158
void onMovingGrowMemory();
159
void onMovingGrowTable(const Table* theTable);
160
161
// Called to apply a single ElemSegment at a given offset, assuming
162
// that all bounds validation has already been performed.
163
164
MOZ_MUST_USE bool initElems(uint32_t tableIndex, const ElemSegment& seg,
165
uint32_t dstOffset, uint32_t srcOffset,
166
uint32_t len);
167
168
// Debugger support:
169
170
JSString* createDisplayURL(JSContext* cx);
171
WasmBreakpointSite* getOrCreateBreakpointSite(JSContext* cx, uint32_t offset);
172
void destroyBreakpointSite(JSFreeOp* fop, uint32_t offset);
173
174
// about:memory reporting:
175
176
void addSizeOfMisc(MallocSizeOf mallocSizeOf, Metadata::SeenSet* seenMetadata,
177
Code::SeenSet* seenCode, Table::SeenSet* seenTables,
178
size_t* code, size_t* data) const;
179
180
// Wasm disassembly support
181
182
void disassembleExport(JSContext* cx, uint32_t funcIndex, Tier tier,
183
PrintCallback callback) const;
184
185
public:
186
// Functions to be called directly from wasm code.
187
static int32_t callImport_void(Instance*, int32_t, int32_t, uint64_t*);
188
static int32_t callImport_i32(Instance*, int32_t, int32_t, uint64_t*);
189
static int32_t callImport_i64(Instance*, int32_t, int32_t, uint64_t*);
190
static int32_t callImport_f64(Instance*, int32_t, int32_t, uint64_t*);
191
static int32_t callImport_anyref(Instance*, int32_t, int32_t, uint64_t*);
192
static int32_t callImport_funcref(Instance*, int32_t, int32_t, uint64_t*);
193
static uint32_t memoryGrow_i32(Instance* instance, uint32_t delta);
194
static uint32_t memorySize_i32(Instance* instance);
195
static int32_t wait_i32(Instance* instance, uint32_t byteOffset,
196
int32_t value, int64_t timeout);
197
static int32_t wait_i64(Instance* instance, uint32_t byteOffset,
198
int64_t value, int64_t timeout);
199
static int32_t wake(Instance* instance, uint32_t byteOffset, int32_t count);
200
static int32_t memCopy(Instance* instance, uint32_t destByteOffset,
201
uint32_t srcByteOffset, uint32_t len,
202
uint8_t* memBase);
203
static int32_t memCopyShared(Instance* instance, uint32_t destByteOffset,
204
uint32_t srcByteOffset, uint32_t len,
205
uint8_t* memBase);
206
static int32_t dataDrop(Instance* instance, uint32_t segIndex);
207
static int32_t memFill(Instance* instance, uint32_t byteOffset,
208
uint32_t value, uint32_t len, uint8_t* memBase);
209
static int32_t memFillShared(Instance* instance, uint32_t byteOffset,
210
uint32_t value, uint32_t len, uint8_t* memBase);
211
static int32_t memInit(Instance* instance, uint32_t dstOffset,
212
uint32_t srcOffset, uint32_t len, uint32_t segIndex);
213
static int32_t tableCopy(Instance* instance, uint32_t dstOffset,
214
uint32_t srcOffset, uint32_t len,
215
uint32_t dstTableIndex, uint32_t srcTableIndex);
216
static int32_t elemDrop(Instance* instance, uint32_t segIndex);
217
static int32_t tableFill(Instance* instance, uint32_t start, void* value,
218
uint32_t len, uint32_t tableIndex);
219
static void* tableGet(Instance* instance, uint32_t index,
220
uint32_t tableIndex);
221
static uint32_t tableGrow(Instance* instance, void* initValue, uint32_t delta,
222
uint32_t tableIndex);
223
static int32_t tableSet(Instance* instance, uint32_t index, void* value,
224
uint32_t tableIndex);
225
static uint32_t tableSize(Instance* instance, uint32_t tableIndex);
226
static int32_t tableInit(Instance* instance, uint32_t dstOffset,
227
uint32_t srcOffset, uint32_t len, uint32_t segIndex,
228
uint32_t tableIndex);
229
static void* funcRef(Instance* instance, uint32_t funcIndex);
230
static void postBarrier(Instance* instance, gc::Cell** location);
231
static void postBarrierFiltering(Instance* instance, gc::Cell** location);
232
static void* structNew(Instance* instance, uint32_t typeIndex);
233
static void* structNarrow(Instance* instance, uint32_t mustUnboxAnyref,
234
uint32_t outputTypeIndex, void* maybeNullPtr);
235
};
236
237
typedef UniquePtr<Instance> UniqueInstance;
238
239
} // namespace wasm
240
} // namespace js
241
242
#endif // wasm_instance_h