| 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 30 matching lines...) Expand all Loading... |
| 41 | 41 |
| 42 os << " code bytes: " | 42 os << " code bytes: " |
| 43 << (function.code_end_offset - function.code_start_offset); | 43 << (function.code_end_offset - function.code_start_offset); |
| 44 return os; | 44 return os; |
| 45 } | 45 } |
| 46 | 46 |
| 47 std::ostream& operator<<(std::ostream& os, const WasmFunctionName& pair) { | 47 std::ostream& operator<<(std::ostream& os, const WasmFunctionName& pair) { |
| 48 os << "#" << pair.function_->func_index << ":"; | 48 os << "#" << pair.function_->func_index << ":"; |
| 49 if (pair.function_->name_offset > 0) { | 49 if (pair.function_->name_offset > 0) { |
| 50 if (pair.module_) { | 50 if (pair.module_) { |
| 51 os << pair.module_->GetName(pair.function_->name_offset); | 51 WasmName name = pair.module_->GetName(pair.function_->name_offset, |
| 52 pair.function_->name_length); |
| 53 os.write(name.name, name.length); |
| 52 } else { | 54 } else { |
| 53 os << "+" << pair.function_->func_index; | 55 os << "+" << pair.function_->func_index; |
| 54 } | 56 } |
| 55 } else { | 57 } else { |
| 56 os << "?"; | 58 os << "?"; |
| 57 } | 59 } |
| 58 return os; | 60 return os; |
| 59 } | 61 } |
| 60 | 62 |
| 61 // A helper class for compiling multiple wasm functions that offers | 63 // A helper class for compiling multiple wasm functions that offers |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 module_end(nullptr), | 275 module_end(nullptr), |
| 274 min_mem_pages(0), | 276 min_mem_pages(0), |
| 275 max_mem_pages(0), | 277 max_mem_pages(0), |
| 276 mem_export(false), | 278 mem_export(false), |
| 277 mem_external(false), | 279 mem_external(false), |
| 278 start_function_index(-1), | 280 start_function_index(-1), |
| 279 origin(kWasmOrigin) {} | 281 origin(kWasmOrigin) {} |
| 280 | 282 |
| 281 static MaybeHandle<JSFunction> ReportFFIError(ErrorThrower& thrower, | 283 static MaybeHandle<JSFunction> ReportFFIError(ErrorThrower& thrower, |
| 282 const char* error, uint32_t index, | 284 const char* error, uint32_t index, |
| 283 const char* module_cstr, | 285 wasm::WasmName module_name, |
| 284 const char* function_cstr) { | 286 wasm::WasmName function_name) { |
| 285 if (function_cstr) { | 287 if (function_name.name) { |
| 286 thrower.Error("Import #%d module=\"%s\" function=\"%s\" error: %s", index, | 288 thrower.Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", |
| 287 module_cstr, function_cstr, error); | 289 index, module_name.length, module_name.name, |
| 290 function_name.length, function_name.name, error); |
| 288 } else { | 291 } else { |
| 289 thrower.Error("Import #%d module=\"%s\" error: %s", index, module_cstr, | 292 thrower.Error("Import #%d module=\"%.*s\" error: %s", index, |
| 290 error); | 293 module_name.length, module_name.name, error); |
| 291 } | 294 } |
| 292 thrower.Error("Import "); | 295 thrower.Error("Import "); |
| 293 return MaybeHandle<JSFunction>(); | 296 return MaybeHandle<JSFunction>(); |
| 294 } | 297 } |
| 295 | 298 |
| 296 static MaybeHandle<JSFunction> LookupFunction( | 299 static MaybeHandle<JSFunction> LookupFunction( |
| 297 ErrorThrower& thrower, Factory* factory, Handle<JSObject> ffi, | 300 ErrorThrower& thrower, Factory* factory, Handle<JSObject> ffi, |
| 298 uint32_t index, const char* module_cstr, const char* function_cstr) { | 301 uint32_t index, wasm::WasmName module_name, wasm::WasmName function_name) { |
| 299 if (ffi.is_null()) { | 302 if (ffi.is_null()) { |
| 300 return ReportFFIError(thrower, "FFI is not an object", index, module_cstr, | 303 return ReportFFIError(thrower, "FFI is not an object", index, module_name, |
| 301 function_cstr); | 304 function_name); |
| 302 } | 305 } |
| 303 | 306 |
| 304 // Look up the module first. | 307 // Look up the module first. |
| 305 Handle<String> name = factory->InternalizeUtf8String(module_cstr); | 308 Handle<String> name = factory->InternalizeUtf8String( |
| 309 Vector<const char>(module_name.name, module_name.length)); |
| 306 MaybeHandle<Object> result = Object::GetProperty(ffi, name); | 310 MaybeHandle<Object> result = Object::GetProperty(ffi, name); |
| 307 if (result.is_null()) { | 311 if (result.is_null()) { |
| 308 return ReportFFIError(thrower, "module not found", index, module_cstr, | 312 return ReportFFIError(thrower, "module not found", index, module_name, |
| 309 function_cstr); | 313 function_name); |
| 310 } | 314 } |
| 311 | 315 |
| 312 Handle<Object> module = result.ToHandleChecked(); | 316 Handle<Object> module = result.ToHandleChecked(); |
| 313 | 317 |
| 314 if (!module->IsJSReceiver()) { | 318 if (!module->IsJSReceiver()) { |
| 315 return ReportFFIError(thrower, "module is not an object or function", index, | 319 return ReportFFIError(thrower, "module is not an object or function", index, |
| 316 module_cstr, function_cstr); | 320 module_name, function_name); |
| 317 } | 321 } |
| 318 | 322 |
| 319 Handle<Object> function; | 323 Handle<Object> function; |
| 320 if (function_cstr) { | 324 if (function_name.name) { |
| 321 // Look up the function in the module. | 325 // Look up the function in the module. |
| 322 Handle<String> name = factory->InternalizeUtf8String(function_cstr); | 326 Handle<String> name = factory->InternalizeUtf8String( |
| 327 Vector<const char>(function_name.name, function_name.length)); |
| 323 MaybeHandle<Object> result = Object::GetProperty(module, name); | 328 MaybeHandle<Object> result = Object::GetProperty(module, name); |
| 324 if (result.is_null()) { | 329 if (result.is_null()) { |
| 325 return ReportFFIError(thrower, "function not found", index, module_cstr, | 330 return ReportFFIError(thrower, "function not found", index, module_name, |
| 326 function_cstr); | 331 function_name); |
| 327 } | 332 } |
| 328 function = result.ToHandleChecked(); | 333 function = result.ToHandleChecked(); |
| 329 } else { | 334 } else { |
| 330 // No function specified. Use the "default export". | 335 // No function specified. Use the "default export". |
| 331 function = module; | 336 function = module; |
| 332 } | 337 } |
| 333 | 338 |
| 334 if (!function->IsJSFunction()) { | 339 if (!function->IsJSFunction()) { |
| 335 return ReportFFIError(thrower, "not a function", index, module_cstr, | 340 return ReportFFIError(thrower, "not a function", index, module_name, |
| 336 function_cstr); | 341 function_name); |
| 337 } | 342 } |
| 338 | 343 |
| 339 return Handle<JSFunction>::cast(function); | 344 return Handle<JSFunction>::cast(function); |
| 340 } | 345 } |
| 341 | 346 |
| 342 // Instantiates a wasm module as a JSObject. | 347 // Instantiates a wasm module as a JSObject. |
| 343 // * allocates a backing store of {mem_size} bytes. | 348 // * allocates a backing store of {mem_size} bytes. |
| 344 // * installs a named property "memory" for that buffer if exported | 349 // * installs a named property "memory" for that buffer if exported |
| 345 // * installs named properties on the object for exported functions | 350 // * installs named properties on the object for exported functions |
| 346 // * compiles wasm code to machine code | 351 // * compiles wasm code to machine code |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 WasmLinker linker(isolate, functions.size()); | 402 WasmLinker linker(isolate, functions.size()); |
| 398 ModuleEnv module_env; | 403 ModuleEnv module_env; |
| 399 module_env.module = this; | 404 module_env.module = this; |
| 400 module_env.instance = &instance; | 405 module_env.instance = &instance; |
| 401 module_env.linker = &linker; | 406 module_env.linker = &linker; |
| 402 module_env.origin = origin; | 407 module_env.origin = origin; |
| 403 | 408 |
| 404 if (import_table.size() > 0) { | 409 if (import_table.size() > 0) { |
| 405 instance.import_code.reserve(import_table.size()); | 410 instance.import_code.reserve(import_table.size()); |
| 406 for (const WasmImport& import : import_table) { | 411 for (const WasmImport& import : import_table) { |
| 407 const char* module_cstr = GetNameOrNull(import.module_name_offset); | 412 WasmName module_name = |
| 408 const char* function_cstr = GetNameOrNull(import.function_name_offset); | 413 GetNameOrNull(import.module_name_offset, import.module_name_length); |
| 414 WasmName function_name = GetNameOrNull(import.function_name_offset, |
| 415 import.function_name_length); |
| 409 MaybeHandle<JSFunction> function = LookupFunction( | 416 MaybeHandle<JSFunction> function = LookupFunction( |
| 410 thrower, factory, ffi, index, module_cstr, function_cstr); | 417 thrower, factory, ffi, index, module_name, function_name); |
| 411 if (function.is_null()) return MaybeHandle<JSObject>(); | 418 if (function.is_null()) return MaybeHandle<JSObject>(); |
| 412 Handle<Code> code = compiler::CompileWasmToJSWrapper( | 419 Handle<Code> code = compiler::CompileWasmToJSWrapper( |
| 413 isolate, &module_env, function.ToHandleChecked(), import.sig, | 420 isolate, &module_env, function.ToHandleChecked(), import.sig, |
| 414 module_cstr, function_cstr); | 421 module_name, function_name); |
| 415 instance.import_code.push_back(code); | 422 instance.import_code.push_back(code); |
| 416 index++; | 423 index++; |
| 417 } | 424 } |
| 418 } | 425 } |
| 419 | 426 |
| 420 //------------------------------------------------------------------------- | 427 //------------------------------------------------------------------------- |
| 421 // Compile all functions in the module. | 428 // Compile all functions in the module. |
| 422 //------------------------------------------------------------------------- | 429 //------------------------------------------------------------------------- |
| 423 | 430 |
| 424 // First pass: compile each function and initialize the code table. | 431 // First pass: compile each function and initialize the code table. |
| 425 index = 0; | 432 index = 0; |
| 426 for (const WasmFunction& func : functions) { | 433 for (const WasmFunction& func : functions) { |
| 427 if (thrower.error()) break; | 434 if (thrower.error()) break; |
| 428 DCHECK_EQ(index, func.func_index); | 435 DCHECK_EQ(index, func.func_index); |
| 429 | 436 |
| 430 const char* cstr = GetName(func.name_offset); | 437 WasmName str = GetName(func.name_offset, func.name_length); |
| 431 Handle<String> name = factory->InternalizeUtf8String(cstr); | 438 WasmName str_null = {nullptr, 0}; |
| 439 Handle<String> name = factory->InternalizeUtf8String( |
| 440 Vector<const char>(str.name, str.length)); |
| 432 Handle<Code> code = Handle<Code>::null(); | 441 Handle<Code> code = Handle<Code>::null(); |
| 433 Handle<JSFunction> function = Handle<JSFunction>::null(); | 442 Handle<JSFunction> function = Handle<JSFunction>::null(); |
| 434 if (func.external) { | 443 if (func.external) { |
| 435 // Lookup external function in FFI object. | 444 // Lookup external function in FFI object. |
| 436 MaybeHandle<JSFunction> function = | 445 MaybeHandle<JSFunction> function = |
| 437 LookupFunction(thrower, factory, ffi, index, cstr, nullptr); | 446 LookupFunction(thrower, factory, ffi, index, str, str_null); |
| 438 if (function.is_null()) return MaybeHandle<JSObject>(); | 447 if (function.is_null()) return MaybeHandle<JSObject>(); |
| 439 code = compiler::CompileWasmToJSWrapper(isolate, &module_env, | 448 code = compiler::CompileWasmToJSWrapper(isolate, &module_env, |
| 440 function.ToHandleChecked(), | 449 function.ToHandleChecked(), |
| 441 func.sig, cstr, nullptr); | 450 func.sig, str, str_null); |
| 442 } else { | 451 } else { |
| 443 // Compile the function. | 452 // Compile the function. |
| 444 code = compiler::CompileWasmFunction(thrower, isolate, &module_env, func); | 453 code = compiler::CompileWasmFunction(thrower, isolate, &module_env, func); |
| 445 if (code.is_null()) { | 454 if (code.is_null()) { |
| 446 thrower.Error("Compilation of #%d:%s failed.", index, cstr); | 455 thrower.Error("Compilation of #%d:%.*s failed.", index, str.length, |
| 456 str.name); |
| 447 return MaybeHandle<JSObject>(); | 457 return MaybeHandle<JSObject>(); |
| 448 } | 458 } |
| 449 if (func.exported) { | 459 if (func.exported) { |
| 450 function = compiler::CompileJSToWasmWrapper( | 460 function = compiler::CompileJSToWasmWrapper( |
| 451 isolate, &module_env, name, code, instance.js_object, index); | 461 isolate, &module_env, name, code, instance.js_object, index); |
| 452 } | 462 } |
| 453 } | 463 } |
| 454 if (!code.is_null()) { | 464 if (!code.is_null()) { |
| 455 // Install the code into the linker table. | 465 // Install the code into the linker table. |
| 456 linker.Finish(index, code); | 466 linker.Finish(index, code); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 478 isolate->native_context()->object_function(), isolate); | 488 isolate->native_context()->object_function(), isolate); |
| 479 Handle<JSObject> exports_object = | 489 Handle<JSObject> exports_object = |
| 480 factory->NewJSObject(object_function, TENURED); | 490 factory->NewJSObject(object_function, TENURED); |
| 481 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); | 491 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); |
| 482 JSObject::AddProperty(instance.js_object, exports_name, exports_object, | 492 JSObject::AddProperty(instance.js_object, exports_name, exports_object, |
| 483 READ_ONLY); | 493 READ_ONLY); |
| 484 | 494 |
| 485 // Compile wrappers and add them to the exports object. | 495 // Compile wrappers and add them to the exports object. |
| 486 for (const WasmExport& exp : export_table) { | 496 for (const WasmExport& exp : export_table) { |
| 487 if (thrower.error()) break; | 497 if (thrower.error()) break; |
| 488 const char* cstr = GetName(exp.name_offset); | 498 WasmName str = GetName(exp.name_offset, exp.name_length); |
| 489 Handle<String> name = factory->InternalizeUtf8String(cstr); | 499 Handle<String> name = factory->InternalizeUtf8String( |
| 500 Vector<const char>(str.name, str.length)); |
| 490 Handle<Code> code = linker.GetFunctionCode(exp.func_index); | 501 Handle<Code> code = linker.GetFunctionCode(exp.func_index); |
| 491 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( | 502 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( |
| 492 isolate, &module_env, name, code, instance.js_object, exp.func_index); | 503 isolate, &module_env, name, code, instance.js_object, exp.func_index); |
| 493 JSObject::AddProperty(exports_object, name, function, READ_ONLY); | 504 JSObject::AddProperty(exports_object, name, function, READ_ONLY); |
| 494 } | 505 } |
| 495 | 506 |
| 496 if (mem_export) { | 507 if (mem_export) { |
| 497 // Export the memory as a named property. | 508 // Export the memory as a named property. |
| 498 Handle<String> name = factory->InternalizeUtf8String("memory"); | 509 Handle<String> name = factory->InternalizeUtf8String("memory"); |
| 499 JSObject::AddProperty(exports_object, name, instance.mem_buffer, | 510 JSObject::AddProperty(exports_object, name, instance.mem_buffer, |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 } | 658 } |
| 648 if (result->IsHeapNumber()) { | 659 if (result->IsHeapNumber()) { |
| 649 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 660 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
| 650 } | 661 } |
| 651 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 662 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
| 652 return -1; | 663 return -1; |
| 653 } | 664 } |
| 654 } // namespace wasm | 665 } // namespace wasm |
| 655 } // namespace internal | 666 } // namespace internal |
| 656 } // namespace v8 | 667 } // namespace v8 |
| OLD | NEW |