V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
wasm-module.h
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_WASM_WASM_MODULE_H_
6 #define V8_WASM_WASM_MODULE_H_
7 
8 #include <memory>
9 
10 #include "src/globals.h"
11 #include "src/handles.h"
12 #include "src/vector.h"
13 #include "src/wasm/signature-map.h"
14 #include "src/wasm/wasm-constants.h"
15 #include "src/wasm/wasm-opcodes.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 class WasmDebugInfo;
21 class WasmModuleObject;
22 
23 namespace wasm {
24 
25 using WasmName = Vector<const char>;
26 
27 class ErrorThrower;
28 
29 // Reference to a string in the wire bytes.
30 class WireBytesRef {
31  public:
32  WireBytesRef() : WireBytesRef(0, 0) {}
33  WireBytesRef(uint32_t offset, uint32_t length)
34  : offset_(offset), length_(length) {
35  DCHECK_IMPLIES(offset_ == 0, length_ == 0);
36  DCHECK_LE(offset_, offset_ + length_); // no uint32_t overflow.
37  }
38 
39  uint32_t offset() const { return offset_; }
40  uint32_t length() const { return length_; }
41  uint32_t end_offset() const { return offset_ + length_; }
42  bool is_empty() const { return length_ == 0; }
43  bool is_set() const { return offset_ != 0; }
44 
45  private:
46  uint32_t offset_;
47  uint32_t length_;
48 };
49 
50 // Static representation of a wasm function.
51 struct WasmFunction {
52  FunctionSig* sig; // signature of the function.
53  uint32_t func_index; // index into the function table.
54  uint32_t sig_index; // index into the signature table.
55  WireBytesRef code; // code of this function.
56  bool imported;
57  bool exported;
58 };
59 
60 // Static representation of a wasm global variable.
61 struct WasmGlobal {
62  ValueType type; // type of the global.
63  bool mutability; // {true} if mutable.
64  WasmInitExpr init; // the initialization expression of the global.
65  union {
66  uint32_t index; // index of imported mutable global.
67  uint32_t offset; // offset into global memory (if not imported & mutable).
68  };
69  bool imported; // true if imported.
70  bool exported; // true if exported.
71 };
72 
73 // Note: An exception signature only uses the params portion of a
74 // function signature.
76 
77 // Static representation of a wasm exception type.
78 struct WasmException {
79  explicit WasmException(const WasmExceptionSig* sig) : sig(sig) {}
80  FunctionSig* ToFunctionSig() const { return const_cast<FunctionSig*>(sig); }
81 
82  const WasmExceptionSig* sig; // type signature of the exception.
83 };
84 
85 // Static representation of a wasm data segment.
87  // Construct an active segment.
88  explicit WasmDataSegment(WasmInitExpr dest_addr)
89  : dest_addr(dest_addr), active(true) {}
90 
91  // Construct a passive segment, which has no dest_addr.
92  WasmDataSegment() : active(false) {}
93 
94  WasmInitExpr dest_addr; // destination memory address of the data.
95  WireBytesRef source; // start offset in the module bytes.
96  bool active = true; // true if copied automatically during instantiation.
97 };
98 
99 // Static representation of a wasm indirect call table.
100 struct WasmTable {
101  MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(WasmTable);
102  ValueType type = kWasmStmt; // table type.
103  uint32_t initial_size = 0; // initial table size.
104  uint32_t maximum_size = 0; // maximum table size.
105  bool has_maximum_size = false; // true if there is a maximum size.
106  // TODO(titzer): Move this to WasmInstance. Needed by interpreter only.
107  std::vector<int32_t> values; // function table, -1 indicating invalid.
108  bool imported = false; // true if imported.
109  bool exported = false; // true if exported.
110 };
111 
112 // Static representation of how to initialize a table.
114  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmTableInit);
115 
116  // Construct an active segment.
117  WasmTableInit(uint32_t table_index, WasmInitExpr offset)
118  : table_index(table_index), offset(offset), active(true) {}
119 
120  // Construct a passive segment, which has no table index or offset.
121  WasmTableInit() : table_index(0), active(false) {}
122 
123  uint32_t table_index;
124  WasmInitExpr offset;
125  std::vector<uint32_t> entries;
126  bool active; // true if copied automatically during instantiation.
127 };
128 
129 // Static representation of a wasm import.
130 struct WasmImport {
131  WireBytesRef module_name; // module name.
132  WireBytesRef field_name; // import name.
133  ImportExportKindCode kind; // kind of the import.
134  uint32_t index; // index into the respective space.
135 };
136 
137 // Static representation of a wasm export.
138 struct WasmExport {
139  WireBytesRef name; // exported name.
140  ImportExportKindCode kind; // kind of the export.
141  uint32_t index; // index into the respective space.
142 };
143 
144 enum ModuleOrigin : uint8_t { kWasmOrigin, kAsmJsOrigin };
145 
146 #define SELECT_WASM_COUNTER(counters, origin, prefix, suffix) \
147  ((origin) == kWasmOrigin ? (counters)->prefix##_wasm_##suffix() \
148  : (counters)->prefix##_asm_##suffix())
149 
150 struct ModuleWireBytes;
151 
152 // Static representation of a module.
153 struct V8_EXPORT_PRIVATE WasmModule {
154  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmModule);
155 
156  std::unique_ptr<Zone> signature_zone;
157  uint32_t initial_pages = 0; // initial size of the memory in 64k pages
158  uint32_t maximum_pages = 0; // maximum size of the memory in 64k pages
159  bool has_shared_memory = false; // true if memory is a SharedArrayBuffer
160  bool has_maximum_pages = false; // true if there is a maximum memory size
161  bool has_memory = false; // true if the memory was defined or imported
162  bool mem_export = false; // true if the memory is exported
163  int start_function_index = -1; // start function, >= 0 if any
164 
165  std::vector<WasmGlobal> globals;
166  // Size of the buffer required for all globals that are not imported and
167  // mutable.
168  uint32_t globals_buffer_size = 0;
169  uint32_t num_imported_mutable_globals = 0;
170  uint32_t num_imported_functions = 0;
171  uint32_t num_declared_functions = 0; // excluding imported
172  uint32_t num_exported_functions = 0;
173  WireBytesRef name = {0, 0};
174  std::vector<FunctionSig*> signatures; // by signature index
175  std::vector<uint32_t> signature_ids; // by signature index
176  std::vector<WasmFunction> functions;
177  std::vector<WasmDataSegment> data_segments;
178  std::vector<WasmTable> tables;
179  std::vector<WasmImport> import_table;
180  std::vector<WasmExport> export_table;
181  std::vector<WasmException> exceptions;
182  std::vector<WasmTableInit> table_inits;
183  SignatureMap signature_map; // canonicalizing map for signature indexes.
184 
185  ModuleOrigin origin = kWasmOrigin; // origin of the module
186  mutable std::unique_ptr<std::unordered_map<uint32_t, WireBytesRef>>
187  function_names;
188  std::string source_map_url;
189 
190  explicit WasmModule(std::unique_ptr<Zone> signature_zone = nullptr);
191 
192  WireBytesRef LookupFunctionName(const ModuleWireBytes& wire_bytes,
193  uint32_t function_index) const;
194  void AddFunctionNameForTesting(int function_index, WireBytesRef name);
195 };
196 
197 size_t EstimateStoredSize(const WasmModule* module);
198 
199 // Interface to the storage (wire bytes) of a wasm module.
200 // It is illegal for anyone receiving a ModuleWireBytes to store pointers based
201 // on module_bytes, as this storage is only guaranteed to be alive as long as
202 // this struct is alive.
203 struct V8_EXPORT_PRIVATE ModuleWireBytes {
204  ModuleWireBytes(Vector<const byte> module_bytes)
205  : module_bytes_(module_bytes) {}
206  ModuleWireBytes(const byte* start, const byte* end)
207  : module_bytes_(start, static_cast<int>(end - start)) {
208  DCHECK_GE(kMaxInt, end - start);
209  }
210 
211  // Get a string stored in the module bytes representing a name.
212  WasmName GetNameOrNull(WireBytesRef ref) const;
213 
214  // Get a string stored in the module bytes representing a function name.
215  WasmName GetNameOrNull(const WasmFunction* function,
216  const WasmModule* module) const;
217 
218  // Checks the given offset range is contained within the module bytes.
219  bool BoundsCheck(uint32_t offset, uint32_t length) const {
220  uint32_t size = static_cast<uint32_t>(module_bytes_.length());
221  return offset <= size && length <= size - offset;
222  }
223 
224  Vector<const byte> GetFunctionBytes(const WasmFunction* function) const {
225  return module_bytes_.SubVector(function->code.offset(),
226  function->code.end_offset());
227  }
228 
229  Vector<const byte> module_bytes() const { return module_bytes_; }
230  const byte* start() const { return module_bytes_.start(); }
231  const byte* end() const { return module_bytes_.end(); }
232  size_t length() const { return module_bytes_.length(); }
233 
234  private:
235  Vector<const byte> module_bytes_;
236 };
237 
238 // A helper for printing out the names of functions.
240  WasmFunctionName(const WasmFunction* function, WasmName name)
241  : function_(function), name_(name) {}
242 
243  const WasmFunction* function_;
244  const WasmName name_;
245 };
246 
247 std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name);
248 
249 // Get the debug info associated with the given wasm object.
250 // If no debug info exists yet, it is created automatically.
251 Handle<WasmDebugInfo> GetDebugInfo(Handle<JSObject> wasm);
252 
253 V8_EXPORT_PRIVATE MaybeHandle<WasmModuleObject> CreateModuleObjectFromBytes(
254  Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower,
255  ModuleOrigin origin, Handle<Script> asm_js_script,
256  Vector<const byte> asm_offset_table);
257 
258 V8_EXPORT_PRIVATE bool IsWasmCodegenAllowed(Isolate* isolate,
259  Handle<Context> context);
260 
261 V8_EXPORT_PRIVATE Handle<JSArray> GetImports(Isolate* isolate,
262  Handle<WasmModuleObject> module);
263 V8_EXPORT_PRIVATE Handle<JSArray> GetExports(Isolate* isolate,
264  Handle<WasmModuleObject> module);
265 V8_EXPORT_PRIVATE Handle<JSArray> GetCustomSections(
266  Isolate* isolate, Handle<WasmModuleObject> module, Handle<String> name,
267  ErrorThrower* thrower);
268 
269 // Decode local variable names from the names section. Return FixedArray of
270 // FixedArray of <undefined|String>. The outer fixed array is indexed by the
271 // function index, the inner one by the local index.
273 
274 // TruncatedUserString makes it easy to output names up to a certain length, and
275 // output a truncation followed by '...' if they exceed a limit.
276 // Use like this:
277 // TruncatedUserString<> name (pc, len);
278 // printf("... %.*s ...", name.length(), name.start())
279 template <int kMaxLen = 50>
281  static_assert(kMaxLen >= 4, "minimum length is 4 (length of '...' plus one)");
282 
283  public:
284  template <typename T>
285  explicit TruncatedUserString(Vector<T> name)
286  : TruncatedUserString(name.start(), name.length()) {}
287 
288  TruncatedUserString(const byte* start, size_t len)
289  : TruncatedUserString(reinterpret_cast<const char*>(start), len) {}
290 
291  TruncatedUserString(const char* start, size_t len)
292  : start_(start), length_(std::min(kMaxLen, static_cast<int>(len))) {
293  if (len > static_cast<size_t>(kMaxLen)) {
294  memcpy(buffer_, start, kMaxLen - 3);
295  memset(buffer_ + kMaxLen - 3, '.', 3);
296  start_ = buffer_;
297  }
298  }
299 
300  const char* start() const { return start_; }
301 
302  int length() const { return length_; }
303 
304  private:
305  const char* start_;
306  const int length_;
307  char buffer_[kMaxLen];
308 };
309 
310 } // namespace wasm
311 } // namespace internal
312 } // namespace v8
313 
314 #endif // V8_WASM_WASM_MODULE_H_
Definition: libplatform.h:13