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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 | 44 |
45 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { | 45 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { |
46 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; | 46 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; |
47 } | 47 } |
48 | 48 |
49 MaybeHandle<String> ExtractStringFromModuleBytes( | 49 MaybeHandle<String> ExtractStringFromModuleBytes( |
50 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, | 50 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, |
51 uint32_t offset, uint32_t size) { | 51 uint32_t offset, uint32_t size) { |
52 // TODO(wasm): cache strings from modules if it's a performance win. | 52 // TODO(wasm): cache strings from modules if it's a performance win. |
53 Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); | 53 Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); |
| 54 DCHECK_GE(static_cast<size_t>(module_bytes->length()), offset); |
| 55 DCHECK_GE(static_cast<size_t>(module_bytes->length() - offset), size); |
54 Address raw = module_bytes->GetCharsAddress() + offset; | 56 Address raw = module_bytes->GetCharsAddress() + offset; |
55 if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size)) | 57 if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size)) |
56 return {}; // UTF8 decoding error for name. | 58 return {}; // UTF8 decoding error for name. |
57 return isolate->factory()->NewStringFromUtf8SubString( | 59 return isolate->factory()->NewStringFromUtf8SubString( |
58 module_bytes, static_cast<int>(offset), static_cast<int>(size)); | 60 module_bytes, static_cast<int>(offset), static_cast<int>(size)); |
59 } | 61 } |
60 | 62 |
61 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, | 63 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, |
62 Handle<Object> new_ref) { | 64 Handle<Object> new_ref) { |
63 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 65 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 } | 578 } |
577 TRACE("chain after {\n"); | 579 TRACE("chain after {\n"); |
578 TRACE_CHAIN(WasmCompiledModule::cast(wasm_module->GetInternalField(0))); | 580 TRACE_CHAIN(WasmCompiledModule::cast(wasm_module->GetInternalField(0))); |
579 TRACE("}\n"); | 581 TRACE("}\n"); |
580 } | 582 } |
581 compiled_module->reset_weak_owning_instance(); | 583 compiled_module->reset_weak_owning_instance(); |
582 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | 584 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); |
583 TRACE("}\n"); | 585 TRACE("}\n"); |
584 } | 586 } |
585 | 587 |
| 588 std::pair<int, int> GetFunctionOffsetAndLength( |
| 589 Handle<WasmCompiledModule> compiled_module, int func_index) { |
| 590 WasmModule* module = compiled_module->module(); |
| 591 if (func_index < 0 || |
| 592 static_cast<size_t>(func_index) > module->functions.size()) { |
| 593 return {0, 0}; |
| 594 } |
| 595 WasmFunction& func = module->functions[func_index]; |
| 596 return {static_cast<int>(func.code_start_offset), |
| 597 static_cast<int>(func.code_end_offset - func.code_start_offset)}; |
| 598 } |
| 599 |
586 } // namespace | 600 } // namespace |
587 | 601 |
588 const char* wasm::SectionName(WasmSectionCode code) { | 602 const char* wasm::SectionName(WasmSectionCode code) { |
589 switch (code) { | 603 switch (code) { |
590 case kUnknownSectionCode: | 604 case kUnknownSectionCode: |
591 return "Unknown"; | 605 return "Unknown"; |
592 case kTypeSectionCode: | 606 case kTypeSectionCode: |
593 return "Type"; | 607 return "Type"; |
594 case kImportSectionCode: | 608 case kImportSectionCode: |
595 return "Import"; | 609 return "Import"; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 DisallowHeapAllocation no_gc; | 671 DisallowHeapAllocation no_gc; |
658 FixedArray* deopt_data = code->deoptimization_data(); | 672 FixedArray* deopt_data = code->deoptimization_data(); |
659 DCHECK_NOT_NULL(deopt_data); | 673 DCHECK_NOT_NULL(deopt_data); |
660 DCHECK(deopt_data->length() == 2); | 674 DCHECK(deopt_data->length() == 2); |
661 Object* weak_link = deopt_data->get(0); | 675 Object* weak_link = deopt_data->get(0); |
662 if (!weak_link->IsWeakCell()) return nullptr; | 676 if (!weak_link->IsWeakCell()) return nullptr; |
663 WeakCell* cell = WeakCell::cast(weak_link); | 677 WeakCell* cell = WeakCell::cast(weak_link); |
664 return cell->value(); | 678 return cell->value(); |
665 } | 679 } |
666 | 680 |
667 int wasm::GetNumImportedFunctions(Handle<JSObject> object) { | 681 int wasm::GetFunctionCodeOffset(Handle<WasmCompiledModule> compiled_module, |
668 return static_cast<int>(Handle<WasmInstanceObject>::cast(object) | 682 int func_index) { |
669 ->module() | 683 return GetFunctionOffsetAndLength(compiled_module, func_index).first; |
670 ->num_imported_functions); | 684 } |
| 685 |
| 686 bool wasm::GetPositionInfo(Handle<WasmCompiledModule> compiled_module, |
| 687 uint32_t position, Script::PositionInfo* info) { |
| 688 std::vector<WasmFunction>& functions = compiled_module->module()->functions; |
| 689 |
| 690 // Binary search for a function containing the given position. |
| 691 int left = 0; // inclusive |
| 692 int right = static_cast<int>(functions.size()); // exclusive |
| 693 if (right == 0) return false; |
| 694 while (right - left > 1) { |
| 695 int mid = left + (right - left) / 2; |
| 696 if (functions[mid].code_start_offset <= position) { |
| 697 left = mid; |
| 698 } else { |
| 699 right = mid; |
| 700 } |
| 701 } |
| 702 // If the found entry does not contains the given position, return false. |
| 703 WasmFunction& func = functions[left]; |
| 704 if (position < func.code_start_offset || position >= func.code_end_offset) { |
| 705 return false; |
| 706 } |
| 707 |
| 708 info->line = left; |
| 709 info->column = position - func.code_start_offset; |
| 710 info->line_start = func.code_start_offset; |
| 711 info->line_end = func.code_end_offset; |
| 712 return true; |
671 } | 713 } |
672 | 714 |
673 WasmModule::WasmModule(Zone* owned, const byte* module_start) | 715 WasmModule::WasmModule(Zone* owned, const byte* module_start) |
674 : owned_zone(owned), | 716 : owned_zone(owned), |
675 module_start(module_start), | 717 module_start(module_start), |
676 pending_tasks(new base::Semaphore(0)) {} | 718 pending_tasks(new base::Semaphore(0)) {} |
677 | 719 |
678 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( | 720 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
679 Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper, | 721 Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper, |
680 ErrorThrower* thrower) const { | 722 ErrorThrower* thrower) const { |
(...skipping 1112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1793 // WebAssembly.Module. | 1835 // WebAssembly.Module. |
1794 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, | 1836 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
1795 ErrorThrower* thrower, | 1837 ErrorThrower* thrower, |
1796 Handle<JSObject> wasm_module, | 1838 Handle<JSObject> wasm_module, |
1797 Handle<JSReceiver> ffi, | 1839 Handle<JSReceiver> ffi, |
1798 Handle<JSArrayBuffer> memory) { | 1840 Handle<JSArrayBuffer> memory) { |
1799 WasmInstanceBuilder builder(isolate, thrower, wasm_module, ffi, memory); | 1841 WasmInstanceBuilder builder(isolate, thrower, wasm_module, ffi, memory); |
1800 return builder.Build(); | 1842 return builder.Build(); |
1801 } | 1843 } |
1802 | 1844 |
1803 Handle<Object> wasm::GetWasmFunctionNameOrNull(Isolate* isolate, | |
1804 Handle<Object> object, | |
1805 uint32_t func_index) { | |
1806 if (!object->IsUndefined(isolate)) { | |
1807 auto instance = Handle<WasmInstanceObject>::cast(object); | |
1808 WasmModule* module = instance->module(); | |
1809 WasmFunction& function = module->functions[func_index]; | |
1810 Handle<WasmCompiledModule> compiled_module(instance->get_compiled_module(), | |
1811 isolate); | |
1812 MaybeHandle<String> string = ExtractStringFromModuleBytes( | |
1813 isolate, compiled_module, function.name_offset, function.name_length); | |
1814 if (!string.is_null()) return string.ToHandleChecked(); | |
1815 } | |
1816 return isolate->factory()->null_value(); | |
1817 } | |
1818 | |
1819 Handle<String> wasm::GetWasmFunctionName(Isolate* isolate, | 1845 Handle<String> wasm::GetWasmFunctionName(Isolate* isolate, |
1820 Handle<Object> instance, | 1846 Handle<Object> instance_or_undef, |
1821 uint32_t func_index) { | 1847 uint32_t func_index) { |
1822 Handle<Object> name_or_null = | 1848 if (!instance_or_undef->IsUndefined(isolate)) { |
1823 GetWasmFunctionNameOrNull(isolate, instance, func_index); | 1849 Handle<WasmCompiledModule> compiled_module( |
1824 if (!name_or_null->IsNull(isolate)) { | 1850 Handle<WasmInstanceObject>::cast(instance_or_undef) |
1825 return Handle<String>::cast(name_or_null); | 1851 ->get_compiled_module()); |
| 1852 MaybeHandle<String> maybe_name = |
| 1853 WasmCompiledModule::GetFunctionName(compiled_module, func_index); |
| 1854 if (!maybe_name.is_null()) return maybe_name.ToHandleChecked(); |
1826 } | 1855 } |
1827 return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>"); | 1856 return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>"); |
1828 } | 1857 } |
1829 | 1858 |
1830 bool wasm::IsWasmInstance(Object* object) { | 1859 bool wasm::IsWasmInstance(Object* object) { |
1831 return WasmInstanceObject::IsWasmInstanceObject(object); | 1860 return WasmInstanceObject::IsWasmInstanceObject(object); |
1832 } | 1861 } |
1833 | 1862 |
1834 WasmCompiledModule* wasm::GetCompiledModule(Object* object) { | 1863 WasmCompiledModule* wasm::GetCompiledModule(Object* object) { |
1835 return WasmInstanceObject::cast(object)->get_compiled_module(); | 1864 return WasmInstanceObject::cast(object)->get_compiled_module(); |
1836 } | 1865 } |
1837 | 1866 |
1838 bool wasm::WasmIsAsmJs(Object* object, Isolate* isolate) { | 1867 bool wasm::WasmIsAsmJs(Object* instance, Isolate* isolate) { |
1839 return IsWasmInstance(object) && | 1868 if (instance->IsUndefined(isolate)) return false; |
1840 WasmInstanceObject::cast(object) | 1869 DCHECK(IsWasmInstance(instance)); |
1841 ->get_compiled_module() | 1870 WasmCompiledModule* compiled_module = |
1842 ->has_asm_js_script(); | 1871 GetCompiledModule(JSObject::cast(instance)); |
| 1872 DCHECK_EQ(compiled_module->has_asm_js_offset_tables(), |
| 1873 compiled_module->script()->type() == Script::TYPE_NORMAL); |
| 1874 return compiled_module->has_asm_js_offset_tables(); |
1843 } | 1875 } |
1844 | 1876 |
1845 Handle<Script> wasm::GetAsmWasmScript(Handle<JSObject> object) { | 1877 Handle<Script> wasm::GetScript(Handle<JSObject> instance) { |
1846 return Handle<WasmInstanceObject>::cast(object) | 1878 DCHECK(IsWasmInstance(*instance)); |
1847 ->get_compiled_module() | 1879 WasmCompiledModule* compiled_module = GetCompiledModule(*instance); |
1848 ->asm_js_script(); | 1880 DCHECK(compiled_module->has_script()); |
| 1881 return compiled_module->script(); |
1849 } | 1882 } |
1850 | 1883 |
1851 int wasm::GetAsmWasmSourcePosition(Handle<JSObject> instance, int func_index, | 1884 int wasm::GetAsmWasmSourcePosition(Handle<JSObject> instance, int func_index, |
1852 int byte_offset) { | 1885 int byte_offset) { |
1853 return WasmDebugInfo::GetAsmJsSourcePosition(GetDebugInfo(instance), | 1886 return WasmDebugInfo::GetAsmJsSourcePosition(GetDebugInfo(instance), |
1854 func_index, byte_offset); | 1887 func_index, byte_offset); |
1855 } | 1888 } |
1856 | 1889 |
1857 Handle<SeqOneByteString> wasm::GetWasmBytes(Handle<JSObject> object) { | 1890 Handle<SeqOneByteString> wasm::GetWasmBytes(Handle<JSObject> object) { |
1858 return Handle<WasmInstanceObject>::cast(object) | 1891 return Handle<WasmInstanceObject>::cast(object) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1898 // Compile the functions of the module, producing a compiled module. | 1931 // Compile the functions of the module, producing a compiled module. |
1899 MaybeHandle<WasmCompiledModule> maybe_compiled_module = | 1932 MaybeHandle<WasmCompiledModule> maybe_compiled_module = |
1900 result.val->CompileFunctions(isolate, module_wrapper, thrower); | 1933 result.val->CompileFunctions(isolate, module_wrapper, thrower); |
1901 | 1934 |
1902 if (maybe_compiled_module.is_null()) return nothing; | 1935 if (maybe_compiled_module.is_null()) return nothing; |
1903 | 1936 |
1904 Handle<WasmCompiledModule> compiled_module = | 1937 Handle<WasmCompiledModule> compiled_module = |
1905 maybe_compiled_module.ToHandleChecked(); | 1938 maybe_compiled_module.ToHandleChecked(); |
1906 | 1939 |
1907 DCHECK_EQ(origin == kAsmJsOrigin, !asm_js_script.is_null()); | 1940 DCHECK_EQ(origin == kAsmJsOrigin, !asm_js_script.is_null()); |
1908 DCHECK(!compiled_module->has_asm_js_script()); | 1941 DCHECK(!compiled_module->has_script()); |
1909 DCHECK(!compiled_module->has_asm_js_offset_tables()); | 1942 DCHECK(!compiled_module->has_asm_js_offset_tables()); |
1910 if (origin == kAsmJsOrigin) { | 1943 if (origin == kAsmJsOrigin) { |
1911 compiled_module->set_asm_js_script(asm_js_script); | 1944 // Set script for the asm.js source, and the offset table mapping wasm byte |
| 1945 // offsets to source positions. |
| 1946 compiled_module->set_script(asm_js_script); |
1912 size_t offset_tables_len = | 1947 size_t offset_tables_len = |
1913 asm_js_offset_tables_end - asm_js_offset_tables_start; | 1948 asm_js_offset_tables_end - asm_js_offset_tables_start; |
1914 DCHECK_GE(static_cast<size_t>(kMaxInt), offset_tables_len); | 1949 DCHECK_GE(static_cast<size_t>(kMaxInt), offset_tables_len); |
1915 Handle<ByteArray> offset_tables = | 1950 Handle<ByteArray> offset_tables = |
1916 isolate->factory()->NewByteArray(static_cast<int>(offset_tables_len)); | 1951 isolate->factory()->NewByteArray(static_cast<int>(offset_tables_len)); |
1917 memcpy(offset_tables->GetDataStartAddress(), asm_js_offset_tables_start, | 1952 memcpy(offset_tables->GetDataStartAddress(), asm_js_offset_tables_start, |
1918 offset_tables_len); | 1953 offset_tables_len); |
1919 compiled_module->set_asm_js_offset_tables(offset_tables); | 1954 compiled_module->set_asm_js_offset_tables(offset_tables); |
| 1955 } else { |
| 1956 // Create a new Script object representing this wasm module, store it in the |
| 1957 // compiled wasm module, and register it at the debugger. |
| 1958 Handle<Script> script = |
| 1959 isolate->factory()->NewScript(isolate->factory()->empty_string()); |
| 1960 script->set_type(Script::TYPE_WASM); |
| 1961 |
| 1962 DCHECK_GE(kMaxInt, end - start); |
| 1963 int hash = StringHasher::HashSequentialString( |
| 1964 reinterpret_cast<const char*>(start), static_cast<int>(end - start), |
| 1965 kZeroHashSeed); |
| 1966 |
| 1967 const int kBufferSize = 50; |
| 1968 char buffer[kBufferSize]; |
| 1969 int url_chars = SNPrintF(ArrayVector(buffer), "wasm://wasm/%08x", hash); |
| 1970 DCHECK(url_chars >= 0 && url_chars < kBufferSize); |
| 1971 MaybeHandle<String> url_str = isolate->factory()->NewStringFromOneByte( |
| 1972 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), url_chars), |
| 1973 TENURED); |
| 1974 script->set_source_url(*url_str.ToHandleChecked()); |
| 1975 |
| 1976 int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash); |
| 1977 DCHECK(name_chars >= 0 && name_chars < kBufferSize); |
| 1978 MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte( |
| 1979 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars), |
| 1980 TENURED); |
| 1981 script->set_name(*name_str.ToHandleChecked()); |
| 1982 |
| 1983 script->set_wasm_compiled_module(*compiled_module); |
| 1984 compiled_module->set_script(script); |
| 1985 isolate->debug()->OnAfterCompile(script); |
1920 } | 1986 } |
1921 | 1987 |
1922 return WasmModuleObject::New(isolate, compiled_module); | 1988 return WasmModuleObject::New(isolate, compiled_module); |
1923 } | 1989 } |
1924 | 1990 |
1925 bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start, | 1991 bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start, |
1926 const byte* end, ErrorThrower* thrower, | 1992 const byte* end, ErrorThrower* thrower, |
1927 ModuleOrigin origin) { | 1993 ModuleOrigin origin) { |
1928 ModuleResult result = DecodeWasmModule(isolate, start, end, true, origin); | 1994 ModuleResult result = DecodeWasmModule(isolate, start, end, true, origin); |
1929 if (result.val) { | 1995 if (result.val) { |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2102 CHECK_NOT_NULL(result.val); | 2168 CHECK_NOT_NULL(result.val); |
2103 module = const_cast<WasmModule*>(result.val); | 2169 module = const_cast<WasmModule*>(result.val); |
2104 } | 2170 } |
2105 | 2171 |
2106 Handle<WasmModuleWrapper> module_wrapper = | 2172 Handle<WasmModuleWrapper> module_wrapper = |
2107 WasmModuleWrapper::New(isolate, module); | 2173 WasmModuleWrapper::New(isolate, module); |
2108 | 2174 |
2109 compiled_module->set_module_wrapper(module_wrapper); | 2175 compiled_module->set_module_wrapper(module_wrapper); |
2110 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); | 2176 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); |
2111 } | 2177 } |
| 2178 |
| 2179 MaybeHandle<String> WasmCompiledModule::GetFunctionName( |
| 2180 Handle<WasmCompiledModule> compiled_module, uint32_t func_index) { |
| 2181 DCHECK_LT(func_index, compiled_module->module()->functions.size()); |
| 2182 WasmFunction& function = compiled_module->module()->functions[func_index]; |
| 2183 Isolate* isolate = compiled_module->GetIsolate(); |
| 2184 MaybeHandle<String> string = ExtractStringFromModuleBytes( |
| 2185 isolate, compiled_module, function.name_offset, function.name_length); |
| 2186 if (!string.is_null()) return string.ToHandleChecked(); |
| 2187 return {}; |
| 2188 } |
OLD | NEW |