| 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/adapters.h" | 7 #include "src/base/adapters.h" |
| 8 #include "src/base/atomic-utils.h" | 8 #include "src/base/atomic-utils.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compiler/wasm-compiler.h" | 10 #include "src/compiler/wasm-compiler.h" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 | 40 |
| 41 namespace { | 41 namespace { |
| 42 | 42 |
| 43 static const int kInvalidSigIndex = -1; | 43 static const int kInvalidSigIndex = -1; |
| 44 static const int kPlaceholderMarker = 1000000000; | 44 static const int kPlaceholderMarker = 1000000000; |
| 45 | 45 |
| 46 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { | 46 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { |
| 47 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; | 47 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; |
| 48 } | 48 } |
| 49 | 49 |
| 50 MaybeHandle<String> ExtractStringFromModuleBytes( | |
| 51 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, | |
| 52 uint32_t offset, uint32_t size) { | |
| 53 // TODO(wasm): cache strings from modules if it's a performance win. | |
| 54 Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); | |
| 55 DCHECK_GE(module_bytes->length(), offset); | |
| 56 DCHECK_GE(module_bytes->length() - offset, size); | |
| 57 Address raw = module_bytes->GetCharsAddress() + offset; | |
| 58 if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size)) | |
| 59 return {}; // UTF8 decoding error for name. | |
| 60 return isolate->factory()->NewStringFromUtf8SubString( | |
| 61 module_bytes, static_cast<int>(offset), static_cast<int>(size)); | |
| 62 } | |
| 63 | |
| 64 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, | 50 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, |
| 65 Handle<Object> new_ref) { | 51 Handle<Object> new_ref) { |
| 66 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 52 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); |
| 67 it.next()) { | 53 it.next()) { |
| 68 if (it.rinfo()->target_object() == *old_ref) { | 54 if (it.rinfo()->target_object() == *old_ref) { |
| 69 it.rinfo()->set_target_object(*new_ref); | 55 it.rinfo()->set_target_object(*new_ref); |
| 70 } | 56 } |
| 71 } | 57 } |
| 72 } | 58 } |
| 73 | 59 |
| (...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 return os; | 781 return os; |
| 796 } | 782 } |
| 797 | 783 |
| 798 WasmInstanceObject* wasm::GetOwningWasmInstance(Code* code) { | 784 WasmInstanceObject* wasm::GetOwningWasmInstance(Code* code) { |
| 799 DCHECK(code->kind() == Code::WASM_FUNCTION); | 785 DCHECK(code->kind() == Code::WASM_FUNCTION); |
| 800 DisallowHeapAllocation no_gc; | 786 DisallowHeapAllocation no_gc; |
| 801 FixedArray* deopt_data = code->deoptimization_data(); | 787 FixedArray* deopt_data = code->deoptimization_data(); |
| 802 DCHECK_NOT_NULL(deopt_data); | 788 DCHECK_NOT_NULL(deopt_data); |
| 803 DCHECK(deopt_data->length() == 2); | 789 DCHECK(deopt_data->length() == 2); |
| 804 Object* weak_link = deopt_data->get(0); | 790 Object* weak_link = deopt_data->get(0); |
| 805 if (!weak_link->IsWeakCell()) return nullptr; | 791 DCHECK(weak_link->IsWeakCell()); |
| 806 WeakCell* cell = WeakCell::cast(weak_link); | 792 WeakCell* cell = WeakCell::cast(weak_link); |
| 807 if (!cell->value()) return nullptr; | 793 if (!cell->value()) return nullptr; |
| 808 return WasmInstanceObject::cast(cell->value()); | 794 return WasmInstanceObject::cast(cell->value()); |
| 809 } | 795 } |
| 810 | 796 |
| 811 int wasm::GetFunctionCodeOffset(Handle<WasmCompiledModule> compiled_module, | 797 int wasm::GetFunctionCodeOffset(Handle<WasmCompiledModule> compiled_module, |
| 812 int func_index) { | 798 int func_index) { |
| 813 return GetFunctionOffsetAndLength(compiled_module, func_index).first; | 799 return GetFunctionOffsetAndLength(compiled_module, func_index).first; |
| 814 } | 800 } |
| 815 | 801 |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1514 // functions. | 1500 // functions. |
| 1515 int ProcessImports(Handle<FixedArray> code_table, | 1501 int ProcessImports(Handle<FixedArray> code_table, |
| 1516 Handle<WasmInstanceObject> instance) { | 1502 Handle<WasmInstanceObject> instance) { |
| 1517 int num_imported_functions = 0; | 1503 int num_imported_functions = 0; |
| 1518 int num_imported_tables = 0; | 1504 int num_imported_tables = 0; |
| 1519 for (int index = 0; index < static_cast<int>(module_->import_table.size()); | 1505 for (int index = 0; index < static_cast<int>(module_->import_table.size()); |
| 1520 ++index) { | 1506 ++index) { |
| 1521 WasmImport& import = module_->import_table[index]; | 1507 WasmImport& import = module_->import_table[index]; |
| 1522 | 1508 |
| 1523 Handle<String> module_name; | 1509 Handle<String> module_name; |
| 1524 MaybeHandle<String> maybe_module_name = ExtractStringFromModuleBytes( | 1510 MaybeHandle<String> maybe_module_name = |
| 1525 isolate_, compiled_module_, import.module_name_offset, | 1511 WasmCompiledModule::ExtractUtf8StringFromModuleBytes( |
| 1526 import.module_name_length); | 1512 isolate_, compiled_module_, import.module_name_offset, |
| 1513 import.module_name_length); |
| 1527 if (!maybe_module_name.ToHandle(&module_name)) return -1; | 1514 if (!maybe_module_name.ToHandle(&module_name)) return -1; |
| 1528 | 1515 |
| 1529 Handle<String> import_name; | 1516 Handle<String> import_name; |
| 1530 MaybeHandle<String> maybe_import_name = ExtractStringFromModuleBytes( | 1517 MaybeHandle<String> maybe_import_name = |
| 1531 isolate_, compiled_module_, import.field_name_offset, | 1518 WasmCompiledModule::ExtractUtf8StringFromModuleBytes( |
| 1532 import.field_name_length); | 1519 isolate_, compiled_module_, import.field_name_offset, |
| 1520 import.field_name_length); |
| 1533 if (!maybe_import_name.ToHandle(&import_name)) return -1; | 1521 if (!maybe_import_name.ToHandle(&import_name)) return -1; |
| 1534 | 1522 |
| 1535 MaybeHandle<Object> result = | 1523 MaybeHandle<Object> result = |
| 1536 LookupImport(index, module_name, import_name); | 1524 LookupImport(index, module_name, import_name); |
| 1537 if (thrower_->error()) return -1; | 1525 if (thrower_->error()) return -1; |
| 1538 Handle<Object> value = result.ToHandleChecked(); | 1526 Handle<Object> value = result.ToHandleChecked(); |
| 1539 | 1527 |
| 1540 switch (import.kind) { | 1528 switch (import.kind) { |
| 1541 case kExternalFunction: { | 1529 case kExternalFunction: { |
| 1542 // Function imports must be callable. | 1530 // Function imports must be callable. |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1745 int export_index = 0; | 1733 int export_index = 0; |
| 1746 for (auto exp : module_->export_table) { | 1734 for (auto exp : module_->export_table) { |
| 1747 if (exp.kind == kExternalFunction) { | 1735 if (exp.kind == kExternalFunction) { |
| 1748 ++export_index; | 1736 ++export_index; |
| 1749 } | 1737 } |
| 1750 } | 1738 } |
| 1751 // Process each export in the export table (go in reverse so asm.js | 1739 // Process each export in the export table (go in reverse so asm.js |
| 1752 // can skip duplicates). | 1740 // can skip duplicates). |
| 1753 for (auto exp : base::Reversed(module_->export_table)) { | 1741 for (auto exp : base::Reversed(module_->export_table)) { |
| 1754 Handle<String> name = | 1742 Handle<String> name = |
| 1755 ExtractStringFromModuleBytes(isolate_, compiled_module_, | 1743 WasmCompiledModule::ExtractUtf8StringFromModuleBytes( |
| 1756 exp.name_offset, exp.name_length) | 1744 isolate_, compiled_module_, exp.name_offset, exp.name_length) |
| 1757 .ToHandleChecked(); | 1745 .ToHandleChecked(); |
| 1758 switch (exp.kind) { | 1746 switch (exp.kind) { |
| 1759 case kExternalFunction: { | 1747 case kExternalFunction: { |
| 1760 // Wrap and export the code as a JSFunction. | 1748 // Wrap and export the code as a JSFunction. |
| 1761 WasmFunction& function = module_->functions[exp.index]; | 1749 WasmFunction& function = module_->functions[exp.index]; |
| 1762 int func_index = | 1750 int func_index = |
| 1763 static_cast<int>(module_->functions.size() + --export_index); | 1751 static_cast<int>(module_->functions.size() + --export_index); |
| 1764 Handle<JSFunction> js_function = js_wrappers_[exp.index]; | 1752 Handle<JSFunction> js_function = js_wrappers_[exp.index]; |
| 1765 if (js_function.is_null()) { | 1753 if (js_function.is_null()) { |
| 1766 // Wrap the exported code as a JSFunction. | 1754 // Wrap the exported code as a JSFunction. |
| 1767 Handle<Code> export_code = | 1755 Handle<Code> export_code = |
| 1768 code_table->GetValueChecked<Code>(isolate_, func_index); | 1756 code_table->GetValueChecked<Code>(isolate_, func_index); |
| 1769 MaybeHandle<String> func_name; | 1757 MaybeHandle<String> func_name; |
| 1770 if (module_->origin == kAsmJsOrigin) { | 1758 if (module_->origin == kAsmJsOrigin) { |
| 1771 // For modules arising from asm.js, honor the names section. | 1759 // For modules arising from asm.js, honor the names section. |
| 1772 func_name = ExtractStringFromModuleBytes( | 1760 func_name = WasmCompiledModule::ExtractUtf8StringFromModuleBytes( |
| 1773 isolate_, compiled_module_, function.name_offset, | 1761 isolate_, compiled_module_, function.name_offset, |
| 1774 function.name_length) | 1762 function.name_length) |
| 1775 .ToHandleChecked(); | 1763 .ToHandleChecked(); |
| 1776 } | 1764 } |
| 1777 js_function = WasmExportedFunction::New( | 1765 js_function = WasmExportedFunction::New( |
| 1778 isolate_, instance, func_name, function.func_index, | 1766 isolate_, instance, func_name, function.func_index, |
| 1779 static_cast<int>(function.sig->parameter_count()), export_code); | 1767 static_cast<int>(function.sig->parameter_count()), export_code); |
| 1780 js_wrappers_[exp.index] = js_function; | 1768 js_wrappers_[exp.index] = js_function; |
| 1781 } | 1769 } |
| 1782 desc.set_value(js_function); | 1770 desc.set_value(js_function); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1929 temp_instance.context = isolate_->native_context(); | 1917 temp_instance.context = isolate_->native_context(); |
| 1930 temp_instance.mem_size = 0; | 1918 temp_instance.mem_size = 0; |
| 1931 temp_instance.mem_start = nullptr; | 1919 temp_instance.mem_start = nullptr; |
| 1932 temp_instance.globals_start = nullptr; | 1920 temp_instance.globals_start = nullptr; |
| 1933 | 1921 |
| 1934 Handle<Code> wrapper_code = compiler::CompileJSToWasmWrapper( | 1922 Handle<Code> wrapper_code = compiler::CompileJSToWasmWrapper( |
| 1935 isolate_, module_, wasm_code, func_index); | 1923 isolate_, module_, wasm_code, func_index); |
| 1936 MaybeHandle<String> func_name; | 1924 MaybeHandle<String> func_name; |
| 1937 if (module_->origin == kAsmJsOrigin) { | 1925 if (module_->origin == kAsmJsOrigin) { |
| 1938 // For modules arising from asm.js, honor the names section. | 1926 // For modules arising from asm.js, honor the names section. |
| 1939 func_name = ExtractStringFromModuleBytes( | 1927 func_name = |
| 1940 isolate_, compiled_module_, | 1928 WasmCompiledModule::ExtractUtf8StringFromModuleBytes( |
| 1941 function->name_offset, function->name_length) | 1929 isolate_, compiled_module_, function->name_offset, |
| 1942 .ToHandleChecked(); | 1930 function->name_length) |
| 1931 .ToHandleChecked(); |
| 1943 } | 1932 } |
| 1944 Handle<WasmExportedFunction> js_function = | 1933 Handle<WasmExportedFunction> js_function = |
| 1945 WasmExportedFunction::New( | 1934 WasmExportedFunction::New( |
| 1946 isolate_, instance, func_name, func_index, | 1935 isolate_, instance, func_name, func_index, |
| 1947 static_cast<int>(function->sig->parameter_count()), | 1936 static_cast<int>(function->sig->parameter_count()), |
| 1948 wrapper_code); | 1937 wrapper_code); |
| 1949 js_wrappers_[func_index] = js_function; | 1938 js_wrappers_[func_index] = js_function; |
| 1950 } | 1939 } |
| 1951 table_instance.js_wrappers->set(table_index, | 1940 table_instance.js_wrappers->set(table_index, |
| 1952 *js_wrappers_[func_index]); | 1941 *js_wrappers_[func_index]); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1983 | 1972 |
| 1984 // Instantiates a WASM module, creating a WebAssembly.Instance from a | 1973 // Instantiates a WASM module, creating a WebAssembly.Instance from a |
| 1985 // WebAssembly.Module. | 1974 // WebAssembly.Module. |
| 1986 MaybeHandle<WasmInstanceObject> WasmModule::Instantiate( | 1975 MaybeHandle<WasmInstanceObject> WasmModule::Instantiate( |
| 1987 Isolate* isolate, ErrorThrower* thrower, Handle<JSObject> wasm_module, | 1976 Isolate* isolate, ErrorThrower* thrower, Handle<JSObject> wasm_module, |
| 1988 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { | 1977 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { |
| 1989 WasmInstanceBuilder builder(isolate, thrower, wasm_module, ffi, memory); | 1978 WasmInstanceBuilder builder(isolate, thrower, wasm_module, ffi, memory); |
| 1990 return builder.Build(); | 1979 return builder.Build(); |
| 1991 } | 1980 } |
| 1992 | 1981 |
| 1993 Handle<String> wasm::GetWasmFunctionName(Isolate* isolate, | |
| 1994 Handle<Object> instance_or_undef, | |
| 1995 uint32_t func_index) { | |
| 1996 if (!instance_or_undef->IsUndefined(isolate)) { | |
| 1997 Handle<WasmCompiledModule> compiled_module( | |
| 1998 Handle<WasmInstanceObject>::cast(instance_or_undef) | |
| 1999 ->get_compiled_module()); | |
| 2000 MaybeHandle<String> maybe_name = | |
| 2001 WasmCompiledModule::GetFunctionName(compiled_module, func_index); | |
| 2002 if (!maybe_name.is_null()) return maybe_name.ToHandleChecked(); | |
| 2003 } | |
| 2004 return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>"); | |
| 2005 } | |
| 2006 | |
| 2007 bool wasm::IsWasmInstance(Object* object) { | 1982 bool wasm::IsWasmInstance(Object* object) { |
| 2008 return WasmInstanceObject::IsWasmInstanceObject(object); | 1983 return WasmInstanceObject::IsWasmInstanceObject(object); |
| 2009 } | 1984 } |
| 2010 | 1985 |
| 2011 bool wasm::WasmIsAsmJs(Object* instance, Isolate* isolate) { | |
| 2012 if (instance->IsUndefined(isolate)) return false; | |
| 2013 DCHECK(IsWasmInstance(instance)); | |
| 2014 WasmCompiledModule* compiled_module = | |
| 2015 WasmInstanceObject::cast(instance)->get_compiled_module(); | |
| 2016 DCHECK_EQ(compiled_module->has_asm_js_offset_table(), | |
| 2017 compiled_module->script()->type() == Script::TYPE_NORMAL); | |
| 2018 return compiled_module->has_asm_js_offset_table(); | |
| 2019 } | |
| 2020 | |
| 2021 Handle<Script> wasm::GetScript(Handle<JSObject> instance) { | 1986 Handle<Script> wasm::GetScript(Handle<JSObject> instance) { |
| 2022 WasmCompiledModule* compiled_module = | 1987 WasmCompiledModule* compiled_module = |
| 2023 WasmInstanceObject::cast(*instance)->get_compiled_module(); | 1988 WasmInstanceObject::cast(*instance)->get_compiled_module(); |
| 2024 DCHECK(compiled_module->has_script()); | 1989 DCHECK(compiled_module->has_script()); |
| 2025 return compiled_module->script(); | 1990 return compiled_module->script(); |
| 2026 } | 1991 } |
| 2027 | 1992 |
| 2028 Handle<WasmDebugInfo> wasm::GetDebugInfo(Handle<JSObject> object) { | 1993 Handle<WasmDebugInfo> wasm::GetDebugInfo(Handle<JSObject> object) { |
| 2029 auto instance = Handle<WasmInstanceObject>::cast(object); | 1994 auto instance = Handle<WasmInstanceObject>::cast(object); |
| 2030 if (instance->has_debug_info()) { | 1995 if (instance->has_debug_info()) { |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2343 CHECK(!compiled_module->has_weak_owning_instance()); | 2308 CHECK(!compiled_module->has_weak_owning_instance()); |
| 2344 } | 2309 } |
| 2345 | 2310 |
| 2346 void testing::ValidateOrphanedInstance(Isolate* isolate, | 2311 void testing::ValidateOrphanedInstance(Isolate* isolate, |
| 2347 Handle<WasmInstanceObject> instance) { | 2312 Handle<WasmInstanceObject> instance) { |
| 2348 DisallowHeapAllocation no_gc; | 2313 DisallowHeapAllocation no_gc; |
| 2349 WasmCompiledModule* compiled_module = instance->get_compiled_module(); | 2314 WasmCompiledModule* compiled_module = instance->get_compiled_module(); |
| 2350 CHECK(compiled_module->has_weak_wasm_module()); | 2315 CHECK(compiled_module->has_weak_wasm_module()); |
| 2351 CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared()); | 2316 CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared()); |
| 2352 } | 2317 } |
| 2353 | |
| 2354 void WasmCompiledModule::RecreateModuleWrapper(Isolate* isolate, | |
| 2355 Handle<FixedArray> array) { | |
| 2356 Handle<WasmCompiledModule> compiled_module( | |
| 2357 reinterpret_cast<WasmCompiledModule*>(*array), isolate); | |
| 2358 | |
| 2359 WasmModule* module = nullptr; | |
| 2360 { | |
| 2361 Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); | |
| 2362 // We parse the module again directly from the module bytes, so | |
| 2363 // the underlying storage must not be moved meanwhile. | |
| 2364 DisallowHeapAllocation no_allocation; | |
| 2365 const byte* start = | |
| 2366 reinterpret_cast<const byte*>(module_bytes->GetCharsAddress()); | |
| 2367 const byte* end = start + module_bytes->length(); | |
| 2368 // TODO(titzer): remember the module origin in the compiled_module | |
| 2369 // For now, we assume serialized modules did not originate from asm.js. | |
| 2370 ModuleResult result = | |
| 2371 DecodeWasmModule(isolate, start, end, false, kWasmOrigin); | |
| 2372 CHECK(result.ok()); | |
| 2373 CHECK_NOT_NULL(result.val); | |
| 2374 module = const_cast<WasmModule*>(result.val); | |
| 2375 } | |
| 2376 | |
| 2377 Handle<WasmModuleWrapper> module_wrapper = | |
| 2378 WasmModuleWrapper::New(isolate, module); | |
| 2379 | |
| 2380 compiled_module->set_module_wrapper(module_wrapper); | |
| 2381 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); | |
| 2382 } | |
| 2383 | |
| 2384 MaybeHandle<String> WasmCompiledModule::GetFunctionName( | |
| 2385 Handle<WasmCompiledModule> compiled_module, uint32_t func_index) { | |
| 2386 DCHECK_LT(func_index, compiled_module->module()->functions.size()); | |
| 2387 WasmFunction& function = compiled_module->module()->functions[func_index]; | |
| 2388 Isolate* isolate = compiled_module->GetIsolate(); | |
| 2389 MaybeHandle<String> string = ExtractStringFromModuleBytes( | |
| 2390 isolate, compiled_module, function.name_offset, function.name_length); | |
| 2391 if (!string.is_null()) return string.ToHandleChecked(); | |
| 2392 return {}; | |
| 2393 } | |
| OLD | NEW |