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 #include "src/macro-assembler.h" | 5 #include "src/macro-assembler.h" |
6 #include "src/objects.h" | 6 #include "src/objects.h" |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/simulator.h" | 9 #include "src/simulator.h" |
10 | 10 |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 module_end(nullptr), | 275 module_end(nullptr), |
276 min_mem_size_log2(0), | 276 min_mem_size_log2(0), |
277 max_mem_size_log2(0), | 277 max_mem_size_log2(0), |
278 mem_export(false), | 278 mem_export(false), |
279 mem_external(false), | 279 mem_external(false), |
280 start_function_index(-1), | 280 start_function_index(-1), |
281 globals(nullptr), | 281 globals(nullptr), |
282 signatures(nullptr), | 282 signatures(nullptr), |
283 functions(nullptr), | 283 functions(nullptr), |
284 data_segments(nullptr), | 284 data_segments(nullptr), |
285 function_table(nullptr) {} | 285 function_table(nullptr), |
| 286 import_table(nullptr) {} |
286 | 287 |
287 WasmModule::~WasmModule() { | 288 WasmModule::~WasmModule() { |
288 if (globals) delete globals; | 289 if (globals) delete globals; |
289 if (signatures) delete signatures; | 290 if (signatures) delete signatures; |
290 if (functions) delete functions; | 291 if (functions) delete functions; |
291 if (data_segments) delete data_segments; | 292 if (data_segments) delete data_segments; |
292 if (function_table) delete function_table; | 293 if (function_table) delete function_table; |
| 294 if (import_table) delete import_table; |
293 } | 295 } |
294 | 296 |
| 297 static MaybeHandle<JSFunction> LookupFunction(ErrorThrower& thrower, |
| 298 Handle<JSObject> ffi, |
| 299 uint32_t index, |
| 300 Handle<String> name, |
| 301 const char* cstr) { |
| 302 if (!ffi.is_null()) { |
| 303 MaybeHandle<Object> result = Object::GetProperty(ffi, name); |
| 304 if (!result.is_null()) { |
| 305 Handle<Object> obj = result.ToHandleChecked(); |
| 306 if (obj->IsJSFunction()) { |
| 307 return Handle<JSFunction>::cast(obj); |
| 308 } else { |
| 309 thrower.Error("FFI function #%d:%s is not a JSFunction.", index, cstr); |
| 310 return MaybeHandle<JSFunction>(); |
| 311 } |
| 312 } else { |
| 313 thrower.Error("FFI function #%d:%s not found.", index, cstr); |
| 314 return MaybeHandle<JSFunction>(); |
| 315 } |
| 316 } else { |
| 317 thrower.Error("FFI table is not an object."); |
| 318 return MaybeHandle<JSFunction>(); |
| 319 } |
| 320 } |
295 | 321 |
296 // Instantiates a wasm module as a JSObject. | 322 // Instantiates a wasm module as a JSObject. |
297 // * allocates a backing store of {mem_size} bytes. | 323 // * allocates a backing store of {mem_size} bytes. |
298 // * installs a named property "memory" for that buffer if exported | 324 // * installs a named property "memory" for that buffer if exported |
299 // * installs named properties on the object for exported functions | 325 // * installs named properties on the object for exported functions |
300 // * compiles wasm code to machine code | 326 // * compiles wasm code to machine code |
301 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, | 327 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
302 Handle<JSObject> ffi, | 328 Handle<JSObject> ffi, |
303 Handle<JSArrayBuffer> memory) { | 329 Handle<JSArrayBuffer> memory) { |
304 this->shared_isolate = isolate; // TODO(titzer): have a real shared isolate. | 330 this->shared_isolate = isolate; // TODO(titzer): have a real shared isolate. |
305 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 331 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
306 Factory* factory = isolate->factory(); | 332 Factory* factory = isolate->factory(); |
307 | 333 |
308 //------------------------------------------------------------------------- | 334 //------------------------------------------------------------------------- |
309 // Allocate the instance and its JS counterpart. | 335 // Allocate the instance and its JS counterpart. |
310 //------------------------------------------------------------------------- | 336 //------------------------------------------------------------------------- |
311 Handle<Map> map = factory->NewMap( | 337 Handle<Map> map = factory->NewMap( |
312 JS_OBJECT_TYPE, | 338 JS_OBJECT_TYPE, |
313 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 339 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
314 WasmModuleInstance instance(this); | 340 WasmModuleInstance instance(this); |
| 341 std::vector<Handle<Code>> import_code; |
315 instance.context = isolate->native_context(); | 342 instance.context = isolate->native_context(); |
316 instance.js_object = factory->NewJSObjectFromMap(map, TENURED); | 343 instance.js_object = factory->NewJSObjectFromMap(map, TENURED); |
317 Handle<FixedArray> code_table = | 344 Handle<FixedArray> code_table = |
318 factory->NewFixedArray(static_cast<int>(functions->size()), TENURED); | 345 factory->NewFixedArray(static_cast<int>(functions->size()), TENURED); |
319 instance.js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 346 instance.js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
320 | 347 |
321 //------------------------------------------------------------------------- | 348 //------------------------------------------------------------------------- |
322 // Allocate and initialize the linear memory. | 349 // Allocate and initialize the linear memory. |
323 //------------------------------------------------------------------------- | 350 //------------------------------------------------------------------------- |
324 if (memory.is_null()) { | 351 if (memory.is_null()) { |
(...skipping 19 matching lines...) Expand all Loading... |
344 //------------------------------------------------------------------------- | 371 //------------------------------------------------------------------------- |
345 if (!AllocateGlobals(&thrower, isolate, &instance)) { | 372 if (!AllocateGlobals(&thrower, isolate, &instance)) { |
346 return MaybeHandle<JSObject>(); | 373 return MaybeHandle<JSObject>(); |
347 } | 374 } |
348 if (!instance.globals_buffer.is_null()) { | 375 if (!instance.globals_buffer.is_null()) { |
349 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer, | 376 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer, |
350 *instance.globals_buffer); | 377 *instance.globals_buffer); |
351 } | 378 } |
352 | 379 |
353 //------------------------------------------------------------------------- | 380 //------------------------------------------------------------------------- |
354 // Compile all functions in the module. | 381 // Compile wrappers to imported functions. |
355 //------------------------------------------------------------------------- | 382 //------------------------------------------------------------------------- |
| 383 uint32_t index = 0; |
356 instance.function_table = BuildFunctionTable(isolate, this); | 384 instance.function_table = BuildFunctionTable(isolate, this); |
357 uint32_t index = 0; | |
358 WasmLinker linker(isolate, functions->size()); | 385 WasmLinker linker(isolate, functions->size()); |
359 ModuleEnv module_env; | 386 ModuleEnv module_env; |
360 module_env.module = this; | 387 module_env.module = this; |
361 module_env.instance = &instance; | 388 module_env.instance = &instance; |
362 module_env.linker = &linker; | 389 module_env.linker = &linker; |
363 module_env.asm_js = false; | 390 module_env.asm_js = false; |
364 | 391 |
| 392 if (import_table->size() > 0) { |
| 393 instance.import_code = &import_code; |
| 394 instance.import_code->reserve(import_table->size()); |
| 395 for (const WasmImport& import : *import_table) { |
| 396 const char* cstr = GetName(import.function_name_offset); |
| 397 Handle<String> name = factory->InternalizeUtf8String(cstr); |
| 398 MaybeHandle<JSFunction> function = |
| 399 LookupFunction(thrower, ffi, index, name, cstr); |
| 400 if (function.is_null()) return MaybeHandle<JSObject>(); |
| 401 Handle<Code> code = compiler::CompileWasmToJSWrapper( |
| 402 isolate, &module_env, function.ToHandleChecked(), import.sig, cstr); |
| 403 instance.import_code->push_back(code); |
| 404 index++; |
| 405 } |
| 406 } |
| 407 |
| 408 //------------------------------------------------------------------------- |
| 409 // Compile all functions in the module. |
| 410 //------------------------------------------------------------------------- |
| 411 |
365 // First pass: compile each function and initialize the code table. | 412 // First pass: compile each function and initialize the code table. |
| 413 index = 0; |
366 for (const WasmFunction& func : *functions) { | 414 for (const WasmFunction& func : *functions) { |
367 if (thrower.error()) break; | 415 if (thrower.error()) break; |
368 DCHECK_EQ(index, func.func_index); | 416 DCHECK_EQ(index, func.func_index); |
369 | 417 |
370 const char* cstr = GetName(func.name_offset); | 418 const char* cstr = GetName(func.name_offset); |
371 Handle<String> name = factory->InternalizeUtf8String(cstr); | 419 Handle<String> name = factory->InternalizeUtf8String(cstr); |
372 Handle<Code> code = Handle<Code>::null(); | 420 Handle<Code> code = Handle<Code>::null(); |
373 Handle<JSFunction> function = Handle<JSFunction>::null(); | 421 Handle<JSFunction> function = Handle<JSFunction>::null(); |
374 if (func.external) { | 422 if (func.external) { |
375 // Lookup external function in FFI object. | 423 // Lookup external function in FFI object. |
376 if (!ffi.is_null()) { | 424 MaybeHandle<JSFunction> function = |
377 MaybeHandle<Object> result = Object::GetProperty(ffi, name); | 425 LookupFunction(thrower, ffi, index, name, cstr); |
378 if (!result.is_null()) { | 426 if (function.is_null()) return MaybeHandle<JSObject>(); |
379 Handle<Object> obj = result.ToHandleChecked(); | 427 code = compiler::CompileWasmToJSWrapper( |
380 if (obj->IsJSFunction()) { | 428 isolate, &module_env, function.ToHandleChecked(), func.sig, cstr); |
381 function = Handle<JSFunction>::cast(obj); | |
382 code = compiler::CompileWasmToJSWrapper(isolate, &module_env, | |
383 function, index); | |
384 } else { | |
385 thrower.Error("FFI function #%d:%s is not a JSFunction.", index, | |
386 cstr); | |
387 return MaybeHandle<JSObject>(); | |
388 } | |
389 } else { | |
390 thrower.Error("FFI function #%d:%s not found.", index, cstr); | |
391 return MaybeHandle<JSObject>(); | |
392 } | |
393 } else { | |
394 thrower.Error("FFI table is not an object."); | |
395 return MaybeHandle<JSObject>(); | |
396 } | |
397 } else { | 429 } else { |
398 // Compile the function. | 430 // Compile the function. |
399 code = compiler::CompileWasmFunction(thrower, isolate, &module_env, func); | 431 code = compiler::CompileWasmFunction(thrower, isolate, &module_env, func); |
400 if (code.is_null()) { | 432 if (code.is_null()) { |
401 thrower.Error("Compilation of #%d:%s failed.", index, cstr); | 433 thrower.Error("Compilation of #%d:%s failed.", index, cstr); |
402 return MaybeHandle<JSObject>(); | 434 return MaybeHandle<JSObject>(); |
403 } | 435 } |
404 if (func.exported) { | 436 if (func.exported) { |
405 function = compiler::CompileJSToWasmWrapper( | 437 function = compiler::CompileJSToWasmWrapper( |
406 isolate, &module_env, name, code, instance.js_object, index); | 438 isolate, &module_env, name, code, instance.js_object, index); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 | 479 |
448 Handle<Code> ModuleEnv::GetFunctionCode(uint32_t index) { | 480 Handle<Code> ModuleEnv::GetFunctionCode(uint32_t index) { |
449 DCHECK(IsValidFunction(index)); | 481 DCHECK(IsValidFunction(index)); |
450 if (linker) return linker->GetFunctionCode(index); | 482 if (linker) return linker->GetFunctionCode(index); |
451 if (instance && instance->function_code) { | 483 if (instance && instance->function_code) { |
452 return instance->function_code->at(index); | 484 return instance->function_code->at(index); |
453 } | 485 } |
454 return Handle<Code>::null(); | 486 return Handle<Code>::null(); |
455 } | 487 } |
456 | 488 |
| 489 Handle<Code> ModuleEnv::GetImportCode(uint32_t index) { |
| 490 DCHECK(IsValidImport(index)); |
| 491 if (instance && instance->import_code) { |
| 492 return instance->import_code->at(index); |
| 493 } |
| 494 return Handle<Code>::null(); |
| 495 } |
457 | 496 |
458 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone, | 497 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone, |
459 uint32_t index) { | 498 uint32_t index) { |
460 DCHECK(IsValidFunction(index)); | 499 DCHECK(IsValidFunction(index)); |
461 // Always make a direct call to whatever is in the table at that location. | 500 // Always make a direct call to whatever is in the table at that location. |
462 // A wrapper will be generated for FFI calls. | 501 // A wrapper will be generated for FFI calls. |
463 WasmFunction* function = &module->functions->at(index); | 502 WasmFunction* function = &module->functions->at(index); |
464 return GetWasmCallDescriptor(zone, function->sig); | 503 return GetWasmCallDescriptor(zone, function->sig); |
465 } | 504 } |
466 | 505 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 } | 604 } |
566 if (result->IsHeapNumber()) { | 605 if (result->IsHeapNumber()) { |
567 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 606 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
568 } | 607 } |
569 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 608 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
570 return -1; | 609 return -1; |
571 } | 610 } |
572 } // namespace wasm | 611 } // namespace wasm |
573 } // namespace internal | 612 } // namespace internal |
574 } // namespace v8 | 613 } // namespace v8 |
OLD | NEW |