| 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 <memory> | 5 #include <memory> |
| 6 | 6 |
| 7 #include "src/base/atomic-utils.h" | 7 #include "src/base/atomic-utils.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 | 9 |
| 10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 i < module->functions.size(); ++i) { | 558 i < module->functions.size(); ++i) { |
| 559 const WasmFunction& func = module->functions[i]; | 559 const WasmFunction& func = module->functions[i]; |
| 560 if (func.imported) continue; // Imports are compiled at instantiation time. | 560 if (func.imported) continue; // Imports are compiled at instantiation time. |
| 561 | 561 |
| 562 WasmName str = module->GetName(func.name_offset, func.name_length); | 562 WasmName str = module->GetName(func.name_offset, func.name_length); |
| 563 Handle<Code> code = Handle<Code>::null(); | 563 Handle<Code> code = Handle<Code>::null(); |
| 564 // Compile the function. | 564 // Compile the function. |
| 565 code = compiler::WasmCompilationUnit::CompileWasmFunction( | 565 code = compiler::WasmCompilationUnit::CompileWasmFunction( |
| 566 thrower, isolate, module_env, &func); | 566 thrower, isolate, module_env, &func); |
| 567 if (code.is_null()) { | 567 if (code.is_null()) { |
| 568 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(), | 568 thrower->CompileError("Compilation of #%d:%.*s failed.", i, str.length(), |
| 569 str.start()); | 569 str.start()); |
| 570 break; | 570 break; |
| 571 } | 571 } |
| 572 // Install the code into the linker table. | 572 // Install the code into the linker table. |
| 573 functions[i] = code; | 573 functions[i] = code; |
| 574 } | 574 } |
| 575 } | 575 } |
| 576 | 576 |
| 577 void PatchDirectCalls(Handle<FixedArray> old_functions, | 577 void PatchDirectCalls(Handle<FixedArray> old_functions, |
| 578 Handle<FixedArray> new_functions, int start) { | 578 Handle<FixedArray> new_functions, int start) { |
| 579 DCHECK_EQ(new_functions->length(), old_functions->length()); | 579 DCHECK_EQ(new_functions->length(), old_functions->length()); |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 // Set up the globals for the new instance. | 1261 // Set up the globals for the new instance. |
| 1262 //-------------------------------------------------------------------------- | 1262 //-------------------------------------------------------------------------- |
| 1263 MaybeHandle<JSArrayBuffer> old_globals; | 1263 MaybeHandle<JSArrayBuffer> old_globals; |
| 1264 MaybeHandle<JSArrayBuffer> globals; | 1264 MaybeHandle<JSArrayBuffer> globals; |
| 1265 uint32_t globals_size = compiled_module_->globals_size(); | 1265 uint32_t globals_size = compiled_module_->globals_size(); |
| 1266 if (globals_size > 0) { | 1266 if (globals_size > 0) { |
| 1267 Handle<JSArrayBuffer> global_buffer = | 1267 Handle<JSArrayBuffer> global_buffer = |
| 1268 NewArrayBuffer(isolate_, globals_size); | 1268 NewArrayBuffer(isolate_, globals_size); |
| 1269 globals = global_buffer; | 1269 globals = global_buffer; |
| 1270 if (globals.is_null()) { | 1270 if (globals.is_null()) { |
| 1271 thrower_->Error("Out of memory: wasm globals"); | 1271 thrower_->RangeError("Out of memory: wasm globals"); |
| 1272 return nothing; | 1272 return nothing; |
| 1273 } | 1273 } |
| 1274 Address old_address = owner.is_null() | 1274 Address old_address = owner.is_null() |
| 1275 ? nullptr | 1275 ? nullptr |
| 1276 : GetGlobalStartAddressFromCodeTemplate( | 1276 : GetGlobalStartAddressFromCodeTemplate( |
| 1277 *factory->undefined_value(), | 1277 *factory->undefined_value(), |
| 1278 JSObject::cast(*owner.ToHandleChecked())); | 1278 JSObject::cast(*owner.ToHandleChecked())); |
| 1279 RelocateGlobals(instance, old_address, | 1279 RelocateGlobals(instance, old_address, |
| 1280 static_cast<Address>(global_buffer->backing_store())); | 1280 static_cast<Address>(global_buffer->backing_store())); |
| 1281 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer); | 1281 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1418 } | 1418 } |
| 1419 module_object_->SetInternalField(0, *compiled_module_); | 1419 module_object_->SetInternalField(0, *compiled_module_); |
| 1420 instance->SetInternalField(kWasmCompiledModule, *compiled_module_); | 1420 instance->SetInternalField(kWasmCompiledModule, *compiled_module_); |
| 1421 compiled_module_->set_weak_owning_instance(link_to_owning_instance); | 1421 compiled_module_->set_weak_owning_instance(link_to_owning_instance); |
| 1422 GlobalHandles::MakeWeak(global_handle.location(), | 1422 GlobalHandles::MakeWeak(global_handle.location(), |
| 1423 global_handle.location(), &InstanceFinalizer, | 1423 global_handle.location(), &InstanceFinalizer, |
| 1424 v8::WeakCallbackType::kFinalizer); | 1424 v8::WeakCallbackType::kFinalizer); |
| 1425 } | 1425 } |
| 1426 } | 1426 } |
| 1427 | 1427 |
| 1428 DCHECK(wasm::IsWasmObject(*instance)); |
| 1429 |
| 1428 //-------------------------------------------------------------------------- | 1430 //-------------------------------------------------------------------------- |
| 1429 // Run the start function if one was specified. | 1431 // Run the start function if one was specified. |
| 1430 //-------------------------------------------------------------------------- | 1432 //-------------------------------------------------------------------------- |
| 1431 if (compiled_module_->has_startup_function()) { | 1433 if (compiled_module_->has_startup_function()) { |
| 1432 Handle<FixedArray> startup_data = compiled_module_->startup_function(); | 1434 Handle<FixedArray> startup_data = compiled_module_->startup_function(); |
| 1433 HandleScope scope(isolate_); | 1435 HandleScope scope(isolate_); |
| 1434 int32_t start_index = | 1436 int32_t start_index = |
| 1435 startup_data->GetValueChecked<Smi>(isolate_, kExportIndex)->value(); | 1437 startup_data->GetValueChecked<Smi>(isolate_, kExportIndex)->value(); |
| 1436 Handle<Code> startup_code = | 1438 Handle<Code> startup_code = |
| 1437 code_table->GetValueChecked<Code>(isolate_, start_index); | 1439 code_table->GetValueChecked<Code>(isolate_, start_index); |
| 1438 int arity = Smi::cast(startup_data->get(kExportArity))->value(); | 1440 int arity = Smi::cast(startup_data->get(kExportArity))->value(); |
| 1439 MaybeHandle<ByteArray> startup_signature = | 1441 MaybeHandle<ByteArray> startup_signature = |
| 1440 startup_data->GetValue<ByteArray>(isolate_, kExportedSignature); | 1442 startup_data->GetValue<ByteArray>(isolate_, kExportedSignature); |
| 1441 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 1443 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
| 1442 isolate_, startup_code, factory->InternalizeUtf8String("start"), | 1444 isolate_, startup_code, factory->InternalizeUtf8String("start"), |
| 1443 arity, startup_signature, instance); | 1445 arity, startup_signature, instance); |
| 1444 RecordStats(isolate_, *startup_code); | 1446 RecordStats(isolate_, *startup_code); |
| 1445 // Call the JS function. | 1447 // Call the JS function. |
| 1446 Handle<Object> undefined = factory->undefined_value(); | 1448 Handle<Object> undefined = factory->undefined_value(); |
| 1447 MaybeHandle<Object> retval = | 1449 MaybeHandle<Object> retval = |
| 1448 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); | 1450 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); |
| 1449 | 1451 |
| 1450 if (retval.is_null()) { | 1452 if (retval.is_null()) { |
| 1451 thrower_->Error("WASM.instantiateModule(): start function failed"); | 1453 DCHECK(isolate_->has_pending_exception()); |
| 1454 isolate_->OptionalRescheduleException(false); |
| 1452 // It's unfortunate that the new instance is already linked in the | 1455 // It's unfortunate that the new instance is already linked in the |
| 1453 // chain. However, we need to set up everything before executing the | 1456 // chain. However, we need to set up everything before executing the |
| 1454 // start function, such that stack trace information can be generated | 1457 // start function, such that stack trace information can be generated |
| 1455 // correctly already in the start function. | 1458 // correctly already in the start function. |
| 1456 return nothing; | 1459 return nothing; |
| 1457 } | 1460 } |
| 1458 } | 1461 } |
| 1459 | 1462 |
| 1460 DCHECK(wasm::IsWasmObject(*instance)); | 1463 DCHECK(!isolate_->has_pending_exception()); |
| 1461 | |
| 1462 TRACE("Finishing instance %d\n", compiled_module_->instance_id()); | 1464 TRACE("Finishing instance %d\n", compiled_module_->instance_id()); |
| 1463 TRACE_CHAIN(WasmCompiledModule::cast(module_object_->GetInternalField(0))); | 1465 TRACE_CHAIN(WasmCompiledModule::cast(module_object_->GetInternalField(0))); |
| 1464 return instance; | 1466 return instance; |
| 1465 } | 1467 } |
| 1466 | 1468 |
| 1467 private: | 1469 private: |
| 1468 Isolate* isolate_; | 1470 Isolate* isolate_; |
| 1469 ErrorThrower* thrower_; | 1471 ErrorThrower* thrower_; |
| 1470 Handle<JSObject> module_object_; | 1472 Handle<JSObject> module_object_; |
| 1471 Handle<JSReceiver> ffi_; | 1473 Handle<JSReceiver> ffi_; |
| 1472 Handle<JSArrayBuffer> memory_; | 1474 Handle<JSArrayBuffer> memory_; |
| 1473 Handle<WasmCompiledModule> compiled_module_; | 1475 Handle<WasmCompiledModule> compiled_module_; |
| 1474 | 1476 |
| 1475 // Helper routine to print out errors with imports (FFI). | 1477 // Helper routine to print out errors with imports (FFI). |
| 1476 MaybeHandle<JSFunction> ReportFFIError(const char* error, uint32_t index, | 1478 MaybeHandle<JSFunction> ReportFFIError(const char* error, uint32_t index, |
| 1477 Handle<String> module_name, | 1479 Handle<String> module_name, |
| 1478 MaybeHandle<String> function_name) { | 1480 MaybeHandle<String> function_name) { |
| 1479 Handle<String> function_name_handle; | 1481 Handle<String> function_name_handle; |
| 1480 if (function_name.ToHandle(&function_name_handle)) { | 1482 if (function_name.ToHandle(&function_name_handle)) { |
| 1481 thrower_->Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", | 1483 thrower_->TypeError( |
| 1482 index, module_name->length(), | 1484 "Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", index, |
| 1483 module_name->ToCString().get(), | 1485 module_name->length(), module_name->ToCString().get(), |
| 1484 function_name_handle->length(), | 1486 function_name_handle->length(), |
| 1485 function_name_handle->ToCString().get(), error); | 1487 function_name_handle->ToCString().get(), error); |
| 1486 } else { | 1488 } else { |
| 1487 thrower_->Error("Import #%d module=\"%.*s\" error: %s", index, | 1489 thrower_->TypeError("Import #%d module=\"%.*s\" error: %s", index, |
| 1488 module_name->length(), module_name->ToCString().get(), | 1490 module_name->length(), module_name->ToCString().get(), |
| 1489 error); | 1491 error); |
| 1490 } | 1492 } |
| 1491 thrower_->Error("Import "); | 1493 thrower_->TypeError("Import "); |
| 1492 return MaybeHandle<JSFunction>(); | 1494 return MaybeHandle<JSFunction>(); |
| 1493 } | 1495 } |
| 1494 | 1496 |
| 1495 // Look up an import value in the {ffi_} object. | 1497 // Look up an import value in the {ffi_} object. |
| 1496 MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name, | 1498 MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name, |
| 1497 MaybeHandle<String> import_name) { | 1499 MaybeHandle<String> import_name) { |
| 1498 if (ffi_.is_null()) { | 1500 if (ffi_.is_null()) { |
| 1499 return ReportFFIError("FFI is not an object", index, module_name, | 1501 return ReportFFIError("FFI is not an object", index, module_name, |
| 1500 import_name); | 1502 import_name); |
| 1501 } | 1503 } |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1766 if (type == kLocalI64 || type == kLocalF64) size = sizeof(double); | 1768 if (type == kLocalI64 || type == kLocalF64) size = sizeof(double); |
| 1767 memcpy(raw_buffer_ptr(globals, offset), | 1769 memcpy(raw_buffer_ptr(globals, offset), |
| 1768 raw_buffer_ptr(globals, old_offset), size); | 1770 raw_buffer_ptr(globals, old_offset), size); |
| 1769 } | 1771 } |
| 1770 } | 1772 } |
| 1771 } | 1773 } |
| 1772 | 1774 |
| 1773 // Allocate memory for a module instance as a new JSArrayBuffer. | 1775 // Allocate memory for a module instance as a new JSArrayBuffer. |
| 1774 Handle<JSArrayBuffer> AllocateMemory(uint32_t min_mem_pages) { | 1776 Handle<JSArrayBuffer> AllocateMemory(uint32_t min_mem_pages) { |
| 1775 if (min_mem_pages > WasmModule::kMaxMemPages) { | 1777 if (min_mem_pages > WasmModule::kMaxMemPages) { |
| 1776 thrower_->Error("Out of memory: wasm memory too large"); | 1778 thrower_->RangeError("Out of memory: wasm memory too large"); |
| 1777 return Handle<JSArrayBuffer>::null(); | 1779 return Handle<JSArrayBuffer>::null(); |
| 1778 } | 1780 } |
| 1779 Handle<JSArrayBuffer> mem_buffer = | 1781 Handle<JSArrayBuffer> mem_buffer = |
| 1780 NewArrayBuffer(isolate_, min_mem_pages * WasmModule::kPageSize); | 1782 NewArrayBuffer(isolate_, min_mem_pages * WasmModule::kPageSize); |
| 1781 | 1783 |
| 1782 if (mem_buffer.is_null()) { | 1784 if (mem_buffer.is_null()) { |
| 1783 thrower_->Error("Out of memory: wasm memory"); | 1785 thrower_->RangeError("Out of memory: wasm memory"); |
| 1784 } | 1786 } |
| 1785 return mem_buffer; | 1787 return mem_buffer; |
| 1786 } | 1788 } |
| 1787 | 1789 |
| 1788 // Process the exports, creating wrappers for functions, tables, memories, | 1790 // Process the exports, creating wrappers for functions, tables, memories, |
| 1789 // and globals. | 1791 // and globals. |
| 1790 void ProcessExports(MaybeHandle<JSArrayBuffer> globals, | 1792 void ProcessExports(MaybeHandle<JSArrayBuffer> globals, |
| 1791 Handle<FixedArray> code_table, | 1793 Handle<FixedArray> code_table, |
| 1792 Handle<JSObject> instance) { | 1794 Handle<JSObject> instance) { |
| 1793 if (!compiled_module_->has_exports()) return; | 1795 if (!compiled_module_->has_exports()) return; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1874 break; | 1876 break; |
| 1875 } | 1877 } |
| 1876 default: | 1878 default: |
| 1877 UNREACHABLE(); | 1879 UNREACHABLE(); |
| 1878 break; | 1880 break; |
| 1879 } | 1881 } |
| 1880 | 1882 |
| 1881 v8::Maybe<bool> status = JSReceiver::DefineOwnProperty( | 1883 v8::Maybe<bool> status = JSReceiver::DefineOwnProperty( |
| 1882 isolate_, exports_object, name, &desc, Object::THROW_ON_ERROR); | 1884 isolate_, exports_object, name, &desc, Object::THROW_ON_ERROR); |
| 1883 if (!status.IsJust()) { | 1885 if (!status.IsJust()) { |
| 1884 thrower_->Error("export of %.*s failed.", name->length(), | 1886 thrower_->TypeError("export of %.*s failed.", name->length(), |
| 1885 name->ToCString().get()); | 1887 name->ToCString().get()); |
| 1886 return; | 1888 return; |
| 1887 } | 1889 } |
| 1888 } | 1890 } |
| 1889 } | 1891 } |
| 1890 }; | 1892 }; |
| 1891 | 1893 |
| 1892 // Instantiates a WASM module, creating a WebAssembly.Instance from a | 1894 // Instantiates a WASM module, creating a WebAssembly.Instance from a |
| 1893 // WebAssembly.Module. | 1895 // WebAssembly.Module. |
| 1894 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, | 1896 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
| 1895 ErrorThrower* thrower, | 1897 ErrorThrower* thrower, |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2159 Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower, | 2161 Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower, |
| 2160 ModuleOrigin origin, Handle<Script> asm_js_script, | 2162 ModuleOrigin origin, Handle<Script> asm_js_script, |
| 2161 const byte* asm_js_offset_tables_start, | 2163 const byte* asm_js_offset_tables_start, |
| 2162 const byte* asm_js_offset_tables_end) { | 2164 const byte* asm_js_offset_tables_end) { |
| 2163 MaybeHandle<JSObject> nothing; | 2165 MaybeHandle<JSObject> nothing; |
| 2164 Zone zone(isolate->allocator()); | 2166 Zone zone(isolate->allocator()); |
| 2165 ModuleResult result = | 2167 ModuleResult result = |
| 2166 DecodeWasmModule(isolate, &zone, start, end, false, origin); | 2168 DecodeWasmModule(isolate, &zone, start, end, false, origin); |
| 2167 std::unique_ptr<const WasmModule> decoded_module(result.val); | 2169 std::unique_ptr<const WasmModule> decoded_module(result.val); |
| 2168 if (result.failed()) { | 2170 if (result.failed()) { |
| 2169 thrower->Failed("Wasm decoding failed", result); | 2171 thrower->CompileFailed("Wasm decoding failed", result); |
| 2170 return nothing; | 2172 return nothing; |
| 2171 } | 2173 } |
| 2172 MaybeHandle<WasmCompiledModule> maybe_compiled_module = | 2174 MaybeHandle<WasmCompiledModule> maybe_compiled_module = |
| 2173 decoded_module->CompileFunctions(isolate, thrower); | 2175 decoded_module->CompileFunctions(isolate, thrower); |
| 2174 if (maybe_compiled_module.is_null()) return nothing; | 2176 if (maybe_compiled_module.is_null()) return nothing; |
| 2175 Handle<WasmCompiledModule> compiled_module = | 2177 Handle<WasmCompiledModule> compiled_module = |
| 2176 maybe_compiled_module.ToHandleChecked(); | 2178 maybe_compiled_module.ToHandleChecked(); |
| 2177 | 2179 |
| 2178 DCHECK_EQ(origin == kAsmJsOrigin, !asm_js_script.is_null()); | 2180 DCHECK_EQ(origin == kAsmJsOrigin, !asm_js_script.is_null()); |
| 2179 DCHECK(!compiled_module->has_asm_js_script()); | 2181 DCHECK(!compiled_module->has_asm_js_script()); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2326 } | 2328 } |
| 2327 | 2329 |
| 2328 void testing::ValidateOrphanedInstance(Isolate* isolate, | 2330 void testing::ValidateOrphanedInstance(Isolate* isolate, |
| 2329 Handle<JSObject> instance) { | 2331 Handle<JSObject> instance) { |
| 2330 DisallowHeapAllocation no_gc; | 2332 DisallowHeapAllocation no_gc; |
| 2331 CHECK(IsWasmObject(*instance)); | 2333 CHECK(IsWasmObject(*instance)); |
| 2332 WasmCompiledModule* compiled_module = GetCompiledModule(*instance); | 2334 WasmCompiledModule* compiled_module = GetCompiledModule(*instance); |
| 2333 CHECK(compiled_module->has_weak_module_object()); | 2335 CHECK(compiled_module->has_weak_module_object()); |
| 2334 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); | 2336 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); |
| 2335 } | 2337 } |
| OLD | NEW |