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