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/compiler/wasm-compiler.h" |
| 6 |
| 7 #include "src/isolate-inl.h" |
| 8 |
| 9 #include "src/base/platform/platform.h" |
5 | 10 |
6 #include "src/compiler/access-builder.h" | 11 #include "src/compiler/access-builder.h" |
7 #include "src/compiler/change-lowering.h" | 12 #include "src/compiler/change-lowering.h" |
8 #include "src/compiler/common-operator.h" | 13 #include "src/compiler/common-operator.h" |
9 #include "src/compiler/diamond.h" | 14 #include "src/compiler/diamond.h" |
10 #include "src/compiler/graph.h" | 15 #include "src/compiler/graph.h" |
11 #include "src/compiler/graph-visualizer.h" | 16 #include "src/compiler/graph-visualizer.h" |
12 #include "src/compiler/instruction-selector.h" | 17 #include "src/compiler/instruction-selector.h" |
13 #include "src/compiler/js-generic-lowering.h" | 18 #include "src/compiler/js-generic-lowering.h" |
14 #include "src/compiler/js-graph.h" | 19 #include "src/compiler/js-graph.h" |
15 #include "src/compiler/js-operator.h" | 20 #include "src/compiler/js-operator.h" |
16 #include "src/compiler/linkage.h" | 21 #include "src/compiler/linkage.h" |
17 #include "src/compiler/machine-operator.h" | 22 #include "src/compiler/machine-operator.h" |
18 #include "src/compiler/node-matchers.h" | 23 #include "src/compiler/node-matchers.h" |
19 #include "src/compiler/pipeline.h" | 24 #include "src/compiler/pipeline.h" |
20 #include "src/compiler/simplified-lowering.h" | 25 #include "src/compiler/simplified-lowering.h" |
21 #include "src/compiler/simplified-operator.h" | 26 #include "src/compiler/simplified-operator.h" |
22 #include "src/compiler/source-position.h" | 27 #include "src/compiler/source-position.h" |
23 #include "src/compiler/typer.h" | 28 #include "src/compiler/typer.h" |
24 #include "src/compiler/wasm-compiler.h" | |
25 | 29 |
26 #include "src/code-factory.h" | 30 #include "src/code-factory.h" |
27 #include "src/code-stubs.h" | 31 #include "src/code-stubs.h" |
28 | 32 |
29 #include "src/wasm/ast-decoder.h" | 33 #include "src/wasm/ast-decoder.h" |
30 #include "src/wasm/wasm-module.h" | 34 #include "src/wasm/wasm-module.h" |
31 #include "src/wasm/wasm-opcodes.h" | 35 #include "src/wasm/wasm-opcodes.h" |
32 | 36 |
33 // TODO(titzer): pull WASM_64 up to a common header. | 37 // TODO(titzer): pull WASM_64 up to a common header. |
34 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 | 38 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 | 337 |
334 | 338 |
335 Node* WasmGraphBuilder::Merge(unsigned count, Node** controls) { | 339 Node* WasmGraphBuilder::Merge(unsigned count, Node** controls) { |
336 return graph()->NewNode(jsgraph()->common()->Merge(count), count, controls); | 340 return graph()->NewNode(jsgraph()->common()->Merge(count), count, controls); |
337 } | 341 } |
338 | 342 |
339 | 343 |
340 Node* WasmGraphBuilder::Phi(wasm::LocalType type, unsigned count, Node** vals, | 344 Node* WasmGraphBuilder::Phi(wasm::LocalType type, unsigned count, Node** vals, |
341 Node* control) { | 345 Node* control) { |
342 DCHECK(IrOpcode::IsMergeOpcode(control->opcode())); | 346 DCHECK(IrOpcode::IsMergeOpcode(control->opcode())); |
343 Node** buf = Realloc(vals, count + 1); | 347 Node** buf = Realloc(vals, count); |
| 348 buf = Realloc(buf, count + 1); |
344 buf[count] = control; | 349 buf[count] = control; |
345 return graph()->NewNode(jsgraph()->common()->Phi(type, count), count + 1, | 350 return graph()->NewNode(jsgraph()->common()->Phi(type, count), count + 1, |
346 buf); | 351 buf); |
347 } | 352 } |
348 | 353 |
349 | 354 |
350 Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects, | 355 Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects, |
351 Node* control) { | 356 Node* control) { |
352 DCHECK(IrOpcode::IsMergeOpcode(control->opcode())); | 357 DCHECK(IrOpcode::IsMergeOpcode(control->opcode())); |
353 Node** buf = Realloc(effects, count + 1); | 358 Node** buf = Realloc(effects, count); |
| 359 buf = Realloc(buf, count + 1); |
354 buf[count] = control; | 360 buf[count] = control; |
355 return graph()->NewNode(jsgraph()->common()->EffectPhi(count), count + 1, | 361 return graph()->NewNode(jsgraph()->common()->EffectPhi(count), count + 1, |
356 buf); | 362 buf); |
357 } | 363 } |
358 | 364 |
359 | 365 |
360 Node* WasmGraphBuilder::Int32Constant(int32_t value) { | 366 Node* WasmGraphBuilder::Int32Constant(int32_t value) { |
361 return jsgraph()->Int32Constant(value); | 367 return jsgraph()->Int32Constant(value); |
362 } | 368 } |
363 | 369 |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 Node* WasmGraphBuilder::Return(unsigned count, Node** vals) { | 958 Node* WasmGraphBuilder::Return(unsigned count, Node** vals) { |
953 DCHECK_NOT_NULL(*control_); | 959 DCHECK_NOT_NULL(*control_); |
954 DCHECK_NOT_NULL(*effect_); | 960 DCHECK_NOT_NULL(*effect_); |
955 | 961 |
956 if (count == 0) { | 962 if (count == 0) { |
957 // Handle a return of void. | 963 // Handle a return of void. |
958 vals[0] = jsgraph()->Int32Constant(0); | 964 vals[0] = jsgraph()->Int32Constant(0); |
959 count = 1; | 965 count = 1; |
960 } | 966 } |
961 | 967 |
962 Node** buf = Realloc(vals, count + 2); | 968 Node** buf = Realloc(vals, count); |
| 969 buf = Realloc(buf, count + 2); |
963 buf[count] = *effect_; | 970 buf[count] = *effect_; |
964 buf[count + 1] = *control_; | 971 buf[count + 1] = *control_; |
965 Node* ret = graph()->NewNode(jsgraph()->common()->Return(), count + 2, vals); | 972 Node* ret = graph()->NewNode(jsgraph()->common()->Return(), count + 2, vals); |
966 | 973 |
967 MergeControlToEnd(jsgraph(), ret); | 974 MergeControlToEnd(jsgraph(), ret); |
968 return ret; | 975 return ret; |
969 } | 976 } |
970 | 977 |
971 | 978 |
972 Node* WasmGraphBuilder::ReturnVoid() { return Return(0, Buffer(0)); } | 979 Node* WasmGraphBuilder::ReturnVoid() { return Return(0, Buffer(0)); } |
(...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1617 } | 1624 } |
1618 | 1625 |
1619 | 1626 |
1620 void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index, | 1627 void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index, |
1621 uint32_t offset) { | 1628 uint32_t offset) { |
1622 // TODO(turbofan): fold bounds checks for constant indexes. | 1629 // TODO(turbofan): fold bounds checks for constant indexes. |
1623 CHECK_GE(module_->mem_end, module_->mem_start); | 1630 CHECK_GE(module_->mem_end, module_->mem_start); |
1624 ptrdiff_t size = module_->mem_end - module_->mem_start; | 1631 ptrdiff_t size = module_->mem_end - module_->mem_start; |
1625 byte memsize = wasm::WasmOpcodes::MemSize(memtype); | 1632 byte memsize = wasm::WasmOpcodes::MemSize(memtype); |
1626 Node* cond; | 1633 Node* cond; |
1627 if (offset >= size || (offset + memsize) > size) { | 1634 if (static_cast<ptrdiff_t>(offset) >= size || |
| 1635 static_cast<ptrdiff_t>(offset + memsize) > size) { |
1628 // The access will always throw. | 1636 // The access will always throw. |
1629 cond = jsgraph()->Int32Constant(0); | 1637 cond = jsgraph()->Int32Constant(0); |
1630 } else { | 1638 } else { |
1631 // Check against the limit. | 1639 // Check against the limit. |
1632 size_t limit = size - offset - memsize; | 1640 size_t limit = size - offset - memsize; |
1633 CHECK(limit <= kMaxUInt32); | 1641 CHECK(limit <= kMaxUInt32); |
1634 cond = graph()->NewNode( | 1642 cond = graph()->NewNode( |
1635 jsgraph()->machine()->Uint32LessThanOrEqual(), index, | 1643 jsgraph()->machine()->Uint32LessThanOrEqual(), index, |
1636 jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); | 1644 jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); |
1637 } | 1645 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1706 | 1714 |
1707 Node* WasmGraphBuilder::String(const char* string) { | 1715 Node* WasmGraphBuilder::String(const char* string) { |
1708 return jsgraph()->Constant( | 1716 return jsgraph()->Constant( |
1709 jsgraph()->isolate()->factory()->NewStringFromAsciiChecked(string)); | 1717 jsgraph()->isolate()->factory()->NewStringFromAsciiChecked(string)); |
1710 } | 1718 } |
1711 | 1719 |
1712 | 1720 |
1713 Graph* WasmGraphBuilder::graph() { return jsgraph()->graph(); } | 1721 Graph* WasmGraphBuilder::graph() { return jsgraph()->graph(); } |
1714 | 1722 |
1715 | 1723 |
1716 Handle<JSFunction> CompileJSToWasmWrapper(Isolate* isolate, | 1724 Handle<JSFunction> CompileJSToWasmWrapper( |
1717 wasm::ModuleEnv* module, | 1725 Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name, |
1718 Handle<String> name, | 1726 Handle<Code> wasm_code, Handle<JSObject> module_object, uint32_t index) { |
1719 Handle<Code> wasm_code, | |
1720 uint32_t index) { | |
1721 wasm::WasmFunction* func = &module->module->functions->at(index); | 1727 wasm::WasmFunction* func = &module->module->functions->at(index); |
1722 | 1728 |
1723 //---------------------------------------------------------------------------- | 1729 //---------------------------------------------------------------------------- |
1724 // Create the JSFunction object. | 1730 // Create the JSFunction object. |
1725 //---------------------------------------------------------------------------- | 1731 //---------------------------------------------------------------------------- |
1726 Handle<SharedFunctionInfo> shared = | 1732 Handle<SharedFunctionInfo> shared = |
1727 isolate->factory()->NewSharedFunctionInfo(name, wasm_code, false); | 1733 isolate->factory()->NewSharedFunctionInfo(name, wasm_code, false); |
1728 int params = static_cast<int>(func->sig->parameter_count()); | 1734 int params = static_cast<int>(func->sig->parameter_count()); |
1729 shared->set_length(params); | 1735 shared->set_length(params); |
1730 shared->set_internal_formal_parameter_count(1 + params); | 1736 shared->set_internal_formal_parameter_count(1 + params); |
1731 Handle<JSFunction> function = isolate->factory()->NewFunction(name); | 1737 Handle<JSFunction> function = isolate->factory()->NewFunction( |
| 1738 isolate->wasm_function_map(), name, MaybeHandle<Code>()); |
| 1739 function->SetInternalField(0, *module_object); |
1732 function->set_shared(*shared); | 1740 function->set_shared(*shared); |
1733 | 1741 |
1734 //---------------------------------------------------------------------------- | 1742 //---------------------------------------------------------------------------- |
1735 // Create the Graph | 1743 // Create the Graph |
1736 //---------------------------------------------------------------------------- | 1744 //---------------------------------------------------------------------------- |
1737 Zone zone; | 1745 Zone zone; |
1738 Graph graph(&zone); | 1746 Graph graph(&zone); |
1739 CommonOperatorBuilder common(&zone); | 1747 CommonOperatorBuilder common(&zone); |
1740 JSOperatorBuilder javascript(&zone); | 1748 JSOperatorBuilder javascript(&zone); |
1741 MachineOperatorBuilder machine(&zone); | 1749 MachineOperatorBuilder machine(&zone); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1781 &zone, false, params + 1, CallDescriptor::kNoFlags); | 1789 &zone, false, params + 1, CallDescriptor::kNoFlags); |
1782 CompilationInfo info("js-to-wasm", isolate, &zone); | 1790 CompilationInfo info("js-to-wasm", isolate, &zone); |
1783 // TODO(titzer): this is technically a WASM wrapper, not a wasm function. | 1791 // TODO(titzer): this is technically a WASM wrapper, not a wasm function. |
1784 info.set_output_code_kind(Code::WASM_FUNCTION); | 1792 info.set_output_code_kind(Code::WASM_FUNCTION); |
1785 Handle<Code> code = | 1793 Handle<Code> code = |
1786 Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr); | 1794 Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr); |
1787 | 1795 |
1788 #ifdef ENABLE_DISASSEMBLER | 1796 #ifdef ENABLE_DISASSEMBLER |
1789 // Disassemble the wrapper code for debugging. | 1797 // Disassemble the wrapper code for debugging. |
1790 if (!code.is_null() && FLAG_print_opt_code) { | 1798 if (!code.is_null() && FLAG_print_opt_code) { |
1791 static const int kBufferSize = 128; | 1799 Vector<char> buffer; |
1792 char buffer[kBufferSize]; | |
1793 const char* name = ""; | 1800 const char* name = ""; |
1794 if (func->name_offset > 0) { | 1801 if (func->name_offset > 0) { |
1795 const byte* ptr = module->module->module_start + func->name_offset; | 1802 const byte* ptr = module->module->module_start + func->name_offset; |
1796 name = reinterpret_cast<const char*>(ptr); | 1803 name = reinterpret_cast<const char*>(ptr); |
1797 } | 1804 } |
1798 snprintf(buffer, kBufferSize, "JS->WASM function wrapper #%d:%s", index, | 1805 SNPrintF(buffer, "JS->WASM function wrapper #%d:%s", index, name); |
1799 name); | |
1800 OFStream os(stdout); | 1806 OFStream os(stdout); |
1801 code->Disassemble(buffer, os); | 1807 code->Disassemble(buffer.start(), os); |
1802 } | 1808 } |
1803 #endif | 1809 #endif |
1804 // Set the JSFunction's machine code. | 1810 // Set the JSFunction's machine code. |
1805 function->set_code(*code); | 1811 function->set_code(*code); |
1806 } | 1812 } |
1807 return function; | 1813 return function; |
1808 } | 1814 } |
1809 | 1815 |
1810 | 1816 |
1811 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module, | 1817 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1857 // Schedule and compile to machine code. | 1863 // Schedule and compile to machine code. |
1858 CallDescriptor* incoming = module->GetWasmCallDescriptor(&zone, func->sig); | 1864 CallDescriptor* incoming = module->GetWasmCallDescriptor(&zone, func->sig); |
1859 CompilationInfo info("wasm-to-js", isolate, &zone); | 1865 CompilationInfo info("wasm-to-js", isolate, &zone); |
1860 // TODO(titzer): this is technically a WASM wrapper, not a wasm function. | 1866 // TODO(titzer): this is technically a WASM wrapper, not a wasm function. |
1861 info.set_output_code_kind(Code::WASM_FUNCTION); | 1867 info.set_output_code_kind(Code::WASM_FUNCTION); |
1862 code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr); | 1868 code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr); |
1863 | 1869 |
1864 #ifdef ENABLE_DISASSEMBLER | 1870 #ifdef ENABLE_DISASSEMBLER |
1865 // Disassemble the wrapper code for debugging. | 1871 // Disassemble the wrapper code for debugging. |
1866 if (!code.is_null() && FLAG_print_opt_code) { | 1872 if (!code.is_null() && FLAG_print_opt_code) { |
1867 static const int kBufferSize = 128; | 1873 Vector<char> buffer; |
1868 char buffer[kBufferSize]; | |
1869 const char* name = ""; | 1874 const char* name = ""; |
1870 if (func->name_offset > 0) { | 1875 if (func->name_offset > 0) { |
1871 const byte* ptr = module->module->module_start + func->name_offset; | 1876 const byte* ptr = module->module->module_start + func->name_offset; |
1872 name = reinterpret_cast<const char*>(ptr); | 1877 name = reinterpret_cast<const char*>(ptr); |
1873 } | 1878 } |
1874 snprintf(buffer, kBufferSize, "WASM->JS function wrapper #%d:%s", index, | 1879 SNPrintF(buffer, "WASM->JS function wrapper #%d:%s", index, name); |
1875 name); | |
1876 OFStream os(stdout); | 1880 OFStream os(stdout); |
1877 code->Disassemble(buffer, os); | 1881 code->Disassemble(buffer.start(), os); |
1878 } | 1882 } |
1879 #endif | 1883 #endif |
1880 } | 1884 } |
1881 return code; | 1885 return code; |
1882 } | 1886 } |
1883 | 1887 |
1884 | 1888 |
1885 // Helper function to compile a single function. | 1889 // Helper function to compile a single function. |
1886 Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, | 1890 Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, |
1887 wasm::ModuleEnv* module_env, | 1891 wasm::ModuleEnv* module_env, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1920 module_env->module->module_start, // -- | 1924 module_env->module->module_start, // -- |
1921 module_env->module->module_start + function.code_start_offset, // -- | 1925 module_env->module->module_start + function.code_start_offset, // -- |
1922 module_env->module->module_start + function.code_end_offset); // -- | 1926 module_env->module->module_start + function.code_end_offset); // -- |
1923 | 1927 |
1924 if (result.failed()) { | 1928 if (result.failed()) { |
1925 if (FLAG_trace_wasm_compiler) { | 1929 if (FLAG_trace_wasm_compiler) { |
1926 OFStream os(stdout); | 1930 OFStream os(stdout); |
1927 os << "Compilation failed: " << result << std::endl; | 1931 os << "Compilation failed: " << result << std::endl; |
1928 } | 1932 } |
1929 // Add the function as another context for the exception | 1933 // Add the function as another context for the exception |
1930 const int kBufSize = 256; | 1934 Vector<char> buffer; |
1931 char buffer[kBufSize]; | 1935 SNPrintF(buffer, "Compiling WASM function #%d:%s failed:", index, |
1932 snprintf(buffer, kBufSize, "Compiling WASM function #%d:%s failed:", index, | |
1933 module_env->module->GetName(function.name_offset)); | 1936 module_env->module->GetName(function.name_offset)); |
1934 thrower.Failed(buffer, result); | 1937 thrower.Failed(buffer.start(), result); |
1935 return Handle<Code>::null(); | 1938 return Handle<Code>::null(); |
1936 } | 1939 } |
1937 | 1940 |
1938 // Run the compiler pipeline to generate machine code. | 1941 // Run the compiler pipeline to generate machine code. |
1939 CallDescriptor* descriptor = const_cast<CallDescriptor*>( | 1942 CallDescriptor* descriptor = const_cast<CallDescriptor*>( |
1940 module_env->GetWasmCallDescriptor(&zone, function.sig)); | 1943 module_env->GetWasmCallDescriptor(&zone, function.sig)); |
1941 CompilationInfo info("wasm", isolate, &zone); | 1944 CompilationInfo info("wasm", isolate, &zone); |
1942 info.set_output_code_kind(Code::WASM_FUNCTION); | 1945 info.set_output_code_kind(Code::WASM_FUNCTION); |
1943 Handle<Code> code = | 1946 Handle<Code> code = |
1944 Pipeline::GenerateCodeForTesting(&info, descriptor, &graph); | 1947 Pipeline::GenerateCodeForTesting(&info, descriptor, &graph); |
1945 | 1948 |
1946 #ifdef ENABLE_DISASSEMBLER | 1949 #ifdef ENABLE_DISASSEMBLER |
1947 // Disassemble the code for debugging. | 1950 // Disassemble the code for debugging. |
1948 if (!code.is_null() && FLAG_print_opt_code) { | 1951 if (!code.is_null() && FLAG_print_opt_code) { |
1949 static const int kBufferSize = 128; | 1952 Vector<char> buffer; |
1950 char buffer[kBufferSize]; | |
1951 const char* name = ""; | 1953 const char* name = ""; |
1952 if (function.name_offset > 0) { | 1954 if (function.name_offset > 0) { |
1953 const byte* ptr = module_env->module->module_start + function.name_offset; | 1955 const byte* ptr = module_env->module->module_start + function.name_offset; |
1954 name = reinterpret_cast<const char*>(ptr); | 1956 name = reinterpret_cast<const char*>(ptr); |
1955 } | 1957 } |
1956 snprintf(buffer, kBufferSize, "WASM function #%d:%s", index, name); | 1958 SNPrintF(buffer, "WASM function #%d:%s", index, name); |
1957 OFStream os(stdout); | 1959 OFStream os(stdout); |
1958 code->Disassemble(buffer, os); | 1960 code->Disassemble(buffer.start(), os); |
1959 } | 1961 } |
1960 #endif | 1962 #endif |
1961 return code; | 1963 return code; |
1962 } | 1964 } |
1963 | 1965 |
1964 | 1966 |
1965 } // namespace compiler | 1967 } // namespace compiler |
1966 } // namespace internal | 1968 } // namespace internal |
1967 } // namespace v8 | 1969 } // namespace v8 |
OLD | NEW |