OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_WASM_MODULE_H_ | 5 #ifndef V8_WASM_MODULE_H_ |
6 #define V8_WASM_MODULE_H_ | 6 #define V8_WASM_MODULE_H_ |
7 | 7 |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "src/api.h" | 10 #include "src/api.h" |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 | 170 |
171 // Static representation of a WASM export. | 171 // Static representation of a WASM export. |
172 struct WasmExport { | 172 struct WasmExport { |
173 uint32_t name_length; // length in bytes of the exported name. | 173 uint32_t name_length; // length in bytes of the exported name. |
174 uint32_t name_offset; // offset in module bytes of the name to export. | 174 uint32_t name_offset; // offset in module bytes of the name to export. |
175 WasmExternalKind kind; // kind of the export. | 175 WasmExternalKind kind; // kind of the export. |
176 uint32_t index; // index into the respective space. | 176 uint32_t index; // index into the respective space. |
177 }; | 177 }; |
178 | 178 |
179 enum ModuleOrigin { kWasmOrigin, kAsmJsOrigin }; | 179 enum ModuleOrigin { kWasmOrigin, kAsmJsOrigin }; |
| 180 struct ModuleWireBytes; |
180 | 181 |
181 // Static representation of a module. | 182 // Static representation of a module. |
182 struct V8_EXPORT_PRIVATE WasmModule { | 183 struct V8_EXPORT_PRIVATE WasmModule { |
183 static const uint32_t kPageSize = 0x10000; // Page size, 64kb. | 184 static const uint32_t kPageSize = 0x10000; // Page size, 64kb. |
184 static const uint32_t kMinMemPages = 1; // Minimum memory size = 64kb | 185 static const uint32_t kMinMemPages = 1; // Minimum memory size = 64kb |
185 static const size_t kV8MaxPages = 16384; // Maximum memory size = 1gb | 186 static const size_t kV8MaxPages = 16384; // Maximum memory size = 1gb |
186 static const size_t kSpecMaxPages = 65536; // Maximum according to the spec | 187 static const size_t kSpecMaxPages = 65536; // Maximum according to the spec |
187 static const size_t kV8MaxTableSize = 16 * 1024 * 1024; | 188 static const size_t kV8MaxTableSize = 16 * 1024 * 1024; |
188 | 189 |
189 Zone* owned_zone; | 190 Zone* owned_zone; |
190 const byte* module_start = nullptr; // starting address for the module bytes | |
191 const byte* module_end = nullptr; // end address for the module bytes | |
192 uint32_t min_mem_pages = 0; // minimum size of the memory in 64k pages | 191 uint32_t min_mem_pages = 0; // minimum size of the memory in 64k pages |
193 uint32_t max_mem_pages = 0; // maximum size of the memory in 64k pages | 192 uint32_t max_mem_pages = 0; // maximum size of the memory in 64k pages |
194 bool has_memory = false; // true if the memory was defined or imported | 193 bool has_memory = false; // true if the memory was defined or imported |
195 bool mem_export = false; // true if the memory is exported | 194 bool mem_export = false; // true if the memory is exported |
196 // TODO(wasm): reconcile start function index being an int with | 195 // TODO(wasm): reconcile start function index being an int with |
197 // the fact that we index on uint32_t, so we may technically not be | 196 // the fact that we index on uint32_t, so we may technically not be |
198 // able to represent some start_function_index -es. | 197 // able to represent some start_function_index -es. |
199 int start_function_index = -1; // start function, if any | 198 int start_function_index = -1; // start function, if any |
200 ModuleOrigin origin = kWasmOrigin; // origin of the module | 199 ModuleOrigin origin = kWasmOrigin; // origin of the module |
201 | 200 |
(...skipping 11 matching lines...) Expand all Loading... |
213 std::vector<WasmTableInit> table_inits; // initializations of tables | 212 std::vector<WasmTableInit> table_inits; // initializations of tables |
214 // We store the semaphore here to extend its lifetime. In <libc-2.21, which we | 213 // We store the semaphore here to extend its lifetime. In <libc-2.21, which we |
215 // use on the try bots, semaphore::Wait() can return while some compilation | 214 // use on the try bots, semaphore::Wait() can return while some compilation |
216 // tasks are still executing semaphore::Signal(). If the semaphore is cleaned | 215 // tasks are still executing semaphore::Signal(). If the semaphore is cleaned |
217 // up right after semaphore::Wait() returns, then this can cause an | 216 // up right after semaphore::Wait() returns, then this can cause an |
218 // invalid-semaphore error in the compilation tasks. | 217 // invalid-semaphore error in the compilation tasks. |
219 // TODO(wasm): Move this semaphore back to CompileInParallel when the try bots | 218 // TODO(wasm): Move this semaphore back to CompileInParallel when the try bots |
220 // switch to libc-2.21 or higher. | 219 // switch to libc-2.21 or higher. |
221 std::unique_ptr<base::Semaphore> pending_tasks; | 220 std::unique_ptr<base::Semaphore> pending_tasks; |
222 | 221 |
223 WasmModule() : WasmModule(nullptr, nullptr) {} | 222 WasmModule() : WasmModule(nullptr) {} |
224 WasmModule(Zone* owned_zone, const byte* module_start); | 223 WasmModule(Zone* owned_zone); |
225 ~WasmModule() { | 224 ~WasmModule() { |
226 if (owned_zone) delete owned_zone; | 225 if (owned_zone) delete owned_zone; |
227 } | 226 } |
228 | 227 |
229 // Get a string stored in the module bytes representing a name. | |
230 WasmName GetName(uint32_t offset, uint32_t length) const { | |
231 if (length == 0) return {"<?>", 3}; // no name. | |
232 CHECK(BoundsCheck(offset, offset + length)); | |
233 DCHECK_GE(static_cast<int>(length), 0); | |
234 return {reinterpret_cast<const char*>(module_start + offset), | |
235 static_cast<int>(length)}; | |
236 } | |
237 | |
238 // Get a string stored in the module bytes representing a function name. | |
239 WasmName GetName(WasmFunction* function) const { | |
240 return GetName(function->name_offset, function->name_length); | |
241 } | |
242 | |
243 // Get a string stored in the module bytes representing a name. | |
244 WasmName GetNameOrNull(uint32_t offset, uint32_t length) const { | |
245 if (offset == 0 && length == 0) return {NULL, 0}; // no name. | |
246 CHECK(BoundsCheck(offset, offset + length)); | |
247 DCHECK_GE(static_cast<int>(length), 0); | |
248 return {reinterpret_cast<const char*>(module_start + offset), | |
249 static_cast<int>(length)}; | |
250 } | |
251 | |
252 // Get a string stored in the module bytes representing a function name. | |
253 WasmName GetNameOrNull(const WasmFunction* function) const { | |
254 return GetNameOrNull(function->name_offset, function->name_length); | |
255 } | |
256 | |
257 // Checks the given offset range is contained within the module bytes. | |
258 bool BoundsCheck(uint32_t start, uint32_t end) const { | |
259 size_t size = module_end - module_start; | |
260 return start <= size && end <= size; | |
261 } | |
262 | |
263 // Creates a new instantiation of the module in the given isolate. | 228 // Creates a new instantiation of the module in the given isolate. |
264 static MaybeHandle<WasmInstanceObject> Instantiate( | 229 static MaybeHandle<WasmInstanceObject> Instantiate( |
265 Isolate* isolate, ErrorThrower* thrower, Handle<JSObject> wasm_module, | 230 Isolate* isolate, ErrorThrower* thrower, Handle<JSObject> wasm_module, |
266 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory); | 231 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory); |
267 | 232 |
268 MaybeHandle<WasmCompiledModule> CompileFunctions( | 233 MaybeHandle<WasmCompiledModule> CompileFunctions( |
269 Isolate* isolate, Handle<Managed<WasmModule>> module_wrapper, | 234 Isolate* isolate, Handle<Managed<WasmModule>> module_wrapper, |
270 ErrorThrower* thrower) const; | 235 ErrorThrower* thrower, const ModuleWireBytes& wire_bytes) const; |
271 }; | 236 }; |
272 | 237 |
273 typedef Managed<WasmModule> WasmModuleWrapper; | 238 typedef Managed<WasmModule> WasmModuleWrapper; |
274 | 239 |
275 // An instantiated WASM module, including memory, function table, etc. | 240 // An instantiated WASM module, including memory, function table, etc. |
276 struct WasmInstance { | 241 struct WasmInstance { |
277 const WasmModule* module; // static representation of the module. | 242 const WasmModule* module; // static representation of the module. |
278 // -- Heap allocated -------------------------------------------------------- | 243 // -- Heap allocated -------------------------------------------------------- |
279 Handle<JSObject> js_object; // JavaScript module object. | 244 Handle<JSObject> js_object; // JavaScript module object. |
280 Handle<Context> context; // JavaScript native context. | 245 Handle<Context> context; // JavaScript native context. |
281 Handle<JSArrayBuffer> mem_buffer; // Handle to array buffer of memory. | 246 Handle<JSArrayBuffer> mem_buffer; // Handle to array buffer of memory. |
282 Handle<JSArrayBuffer> globals_buffer; // Handle to array buffer of globals. | 247 Handle<JSArrayBuffer> globals_buffer; // Handle to array buffer of globals. |
283 std::vector<Handle<FixedArray>> function_tables; // indirect function tables. | 248 std::vector<Handle<FixedArray>> function_tables; // indirect function tables. |
284 std::vector<Handle<Code>> function_code; // code objects for each function. | 249 std::vector<Handle<Code>> function_code; // code objects for each function. |
285 // -- raw memory ------------------------------------------------------------ | 250 // -- raw memory ------------------------------------------------------------ |
286 byte* mem_start = nullptr; // start of linear memory. | 251 byte* mem_start = nullptr; // start of linear memory. |
287 uint32_t mem_size = 0; // size of the linear memory. | 252 uint32_t mem_size = 0; // size of the linear memory. |
288 // -- raw globals ----------------------------------------------------------- | 253 // -- raw globals ----------------------------------------------------------- |
289 byte* globals_start = nullptr; // start of the globals area. | 254 byte* globals_start = nullptr; // start of the globals area. |
290 | 255 |
291 explicit WasmInstance(const WasmModule* m) | 256 explicit WasmInstance(const WasmModule* m) |
292 : module(m), | 257 : module(m), |
293 function_tables(m->function_tables.size()), | 258 function_tables(m->function_tables.size()), |
294 function_code(m->functions.size()) {} | 259 function_code(m->functions.size()) {} |
295 }; | 260 }; |
296 | 261 |
| 262 // Interface to the storage (wire bytes) of a wasm module. |
| 263 // It is illegal for anyone receiving a ModuleWireBytes to store pointers based |
| 264 // on module_bytes, as this storage is only guaranteed to be alive as long as |
| 265 // this struct is alive. |
| 266 struct V8_EXPORT_PRIVATE ModuleWireBytes { |
| 267 ModuleWireBytes(Vector<const byte> module_bytes) |
| 268 : module_bytes(module_bytes) {} |
| 269 ModuleWireBytes(const byte* start, const byte* end) |
| 270 : module_bytes(start, static_cast<int>(end - start)) { |
| 271 DCHECK_GE(kMaxInt, end - start); |
| 272 } |
| 273 |
| 274 const Vector<const byte> module_bytes; |
| 275 |
| 276 // Get a string stored in the module bytes representing a name. |
| 277 WasmName GetName(uint32_t offset, uint32_t length) const { |
| 278 if (length == 0) return {"<?>", 3}; // no name. |
| 279 CHECK(BoundsCheck(offset, length)); |
| 280 DCHECK_GE(static_cast<int>(length), 0); |
| 281 return Vector<const char>::cast( |
| 282 module_bytes.SubVector(offset, offset + length)); |
| 283 } |
| 284 |
| 285 // Get a string stored in the module bytes representing a function name. |
| 286 WasmName GetName(const WasmFunction* function) const { |
| 287 return GetName(function->name_offset, function->name_length); |
| 288 } |
| 289 |
| 290 // Get a string stored in the module bytes representing a name. |
| 291 WasmName GetNameOrNull(uint32_t offset, uint32_t length) const { |
| 292 if (offset == 0 && length == 0) return {NULL, 0}; // no name. |
| 293 CHECK(BoundsCheck(offset, length)); |
| 294 DCHECK_GE(static_cast<int>(length), 0); |
| 295 return Vector<const char>::cast( |
| 296 module_bytes.SubVector(offset, offset + length)); |
| 297 } |
| 298 |
| 299 // Get a string stored in the module bytes representing a function name. |
| 300 WasmName GetNameOrNull(const WasmFunction* function) const { |
| 301 return GetNameOrNull(function->name_offset, function->name_length); |
| 302 } |
| 303 |
| 304 // Checks the given offset range is contained within the module bytes. |
| 305 bool BoundsCheck(uint32_t offset, uint32_t length) const { |
| 306 uint32_t size = static_cast<uint32_t>(module_bytes.length()); |
| 307 return offset <= size && length <= size - offset; |
| 308 } |
| 309 }; |
| 310 |
297 // Interface provided to the decoder/graph builder which contains only | 311 // Interface provided to the decoder/graph builder which contains only |
298 // minimal information about the globals, functions, and function tables. | 312 // minimal information about the globals, functions, and function tables. |
299 struct V8_EXPORT_PRIVATE ModuleEnv { | 313 struct V8_EXPORT_PRIVATE ModuleEnv { |
| 314 ModuleEnv(const WasmModule* module, WasmInstance* instance) |
| 315 : module(module), instance(instance) {} |
| 316 |
300 const WasmModule* module; | 317 const WasmModule* module; |
301 WasmInstance* instance; | 318 WasmInstance* instance; |
302 ModuleOrigin origin; | |
303 | 319 |
304 bool IsValidGlobal(uint32_t index) const { | 320 bool IsValidGlobal(uint32_t index) const { |
305 return module && index < module->globals.size(); | 321 return module && index < module->globals.size(); |
306 } | 322 } |
307 bool IsValidFunction(uint32_t index) const { | 323 bool IsValidFunction(uint32_t index) const { |
308 return module && index < module->functions.size(); | 324 return module && index < module->functions.size(); |
309 } | 325 } |
310 bool IsValidSignature(uint32_t index) const { | 326 bool IsValidSignature(uint32_t index) const { |
311 return module && index < module->signatures.size(); | 327 return module && index < module->signatures.size(); |
312 } | 328 } |
(...skipping 10 matching lines...) Expand all Loading... |
323 } | 339 } |
324 FunctionSig* GetSignature(uint32_t index) { | 340 FunctionSig* GetSignature(uint32_t index) { |
325 DCHECK(IsValidSignature(index)); | 341 DCHECK(IsValidSignature(index)); |
326 return module->signatures[index]; | 342 return module->signatures[index]; |
327 } | 343 } |
328 const WasmIndirectFunctionTable* GetTable(uint32_t index) const { | 344 const WasmIndirectFunctionTable* GetTable(uint32_t index) const { |
329 DCHECK(IsValidTable(index)); | 345 DCHECK(IsValidTable(index)); |
330 return &module->function_tables[index]; | 346 return &module->function_tables[index]; |
331 } | 347 } |
332 | 348 |
333 bool asm_js() { return origin == kAsmJsOrigin; } | 349 bool asm_js() { return module->origin == kAsmJsOrigin; } |
334 | 350 |
335 Handle<Code> GetFunctionCode(uint32_t index) { | 351 Handle<Code> GetFunctionCode(uint32_t index) { |
336 DCHECK_NOT_NULL(instance); | 352 DCHECK_NOT_NULL(instance); |
337 return instance->function_code[index]; | 353 return instance->function_code[index]; |
338 } | 354 } |
339 | 355 |
340 static compiler::CallDescriptor* GetWasmCallDescriptor(Zone* zone, | 356 static compiler::CallDescriptor* GetWasmCallDescriptor(Zone* zone, |
341 FunctionSig* sig); | 357 FunctionSig* sig); |
342 static compiler::CallDescriptor* GetI32WasmCallDescriptor( | 358 static compiler::CallDescriptor* GetI32WasmCallDescriptor( |
343 Zone* zone, compiler::CallDescriptor* descriptor); | 359 Zone* zone, compiler::CallDescriptor* descriptor); |
344 static compiler::CallDescriptor* GetI32WasmCallDescriptorForSimd( | 360 static compiler::CallDescriptor* GetI32WasmCallDescriptorForSimd( |
345 Zone* zone, compiler::CallDescriptor* descriptor); | 361 Zone* zone, compiler::CallDescriptor* descriptor); |
346 }; | 362 }; |
347 | 363 |
| 364 // A ModuleEnv together with ModuleWireBytes. |
| 365 struct ModuleBytesEnv : public ModuleEnv, public ModuleWireBytes { |
| 366 ModuleBytesEnv(const WasmModule* module, WasmInstance* instance, |
| 367 Vector<const byte> module_bytes) |
| 368 : ModuleEnv(module, instance), ModuleWireBytes(module_bytes) {} |
| 369 ModuleBytesEnv(const WasmModule* module, WasmInstance* instance, |
| 370 const ModuleWireBytes& wire_bytes) |
| 371 : ModuleEnv(module, instance), ModuleWireBytes(wire_bytes) {} |
| 372 }; |
| 373 |
348 // A helper for printing out the names of functions. | 374 // A helper for printing out the names of functions. |
349 struct WasmFunctionName { | 375 struct WasmFunctionName { |
| 376 WasmFunctionName(const WasmFunction* function, ModuleBytesEnv* module_env) |
| 377 : function_(function), name_(module_env->GetNameOrNull(function)) {} |
| 378 |
350 const WasmFunction* function_; | 379 const WasmFunction* function_; |
351 const WasmModule* module_; | 380 WasmName name_; |
352 WasmFunctionName(const WasmFunction* function, const ModuleEnv* menv) | |
353 : function_(function), module_(menv ? menv->module : nullptr) {} | |
354 }; | 381 }; |
355 | 382 |
356 std::ostream& operator<<(std::ostream& os, const WasmModule& module); | 383 std::ostream& operator<<(std::ostream& os, const WasmModule& module); |
357 std::ostream& operator<<(std::ostream& os, const WasmFunction& function); | 384 std::ostream& operator<<(std::ostream& os, const WasmFunction& function); |
358 std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name); | 385 std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name); |
359 | 386 |
360 // Extract a function name from the given wasm instance. | 387 // Extract a function name from the given wasm instance. |
361 // Returns "<WASM UNNAMED>" if no instance is passed, the function is unnamed or | 388 // Returns "<WASM UNNAMED>" if no instance is passed, the function is unnamed or |
362 // the name is not a valid UTF-8 string. | 389 // the name is not a valid UTF-8 string. |
363 // TODO(5620): Refactor once we always get a wasm instance. | 390 // TODO(5620): Refactor once we always get a wasm instance. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 void ValidateModuleState(Isolate* isolate, Handle<WasmModuleObject> module_obj); | 466 void ValidateModuleState(Isolate* isolate, Handle<WasmModuleObject> module_obj); |
440 void ValidateOrphanedInstance(Isolate* isolate, | 467 void ValidateOrphanedInstance(Isolate* isolate, |
441 Handle<WasmInstanceObject> instance); | 468 Handle<WasmInstanceObject> instance); |
442 | 469 |
443 } // namespace testing | 470 } // namespace testing |
444 } // namespace wasm | 471 } // namespace wasm |
445 } // namespace internal | 472 } // namespace internal |
446 } // namespace v8 | 473 } // namespace v8 |
447 | 474 |
448 #endif // V8_WASM_MODULE_H_ | 475 #endif // V8_WASM_MODULE_H_ |
OLD | NEW |