| 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 |