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 |