| 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/base/atomic-utils.h" | 5 #include "src/base/atomic-utils.h" |
| 6 #include "src/macro-assembler.h" | 6 #include "src/macro-assembler.h" |
| 7 #include "src/objects.h" | 7 #include "src/objects.h" |
| 8 #include "src/property-descriptor.h" | 8 #include "src/property-descriptor.h" |
| 9 #include "src/v8.h" | 9 #include "src/v8.h" |
| 10 | 10 |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 ModuleEnv& module_env, CodeStats& code_stats, | 570 ModuleEnv& module_env, CodeStats& code_stats, |
| 571 PropertyDescriptor& desc) { | 571 PropertyDescriptor& desc) { |
| 572 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; | 572 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; |
| 573 i < module->functions.size(); i++) { | 573 i < module->functions.size(); i++) { |
| 574 const WasmFunction& func = module->functions[i]; | 574 const WasmFunction& func = module->functions[i]; |
| 575 if (thrower.error()) break; | 575 if (thrower.error()) break; |
| 576 | 576 |
| 577 DCHECK_EQ(i, func.func_index); | 577 DCHECK_EQ(i, func.func_index); |
| 578 WasmName str = module->GetName(func.name_offset, func.name_length); | 578 WasmName str = module->GetName(func.name_offset, func.name_length); |
| 579 Handle<Code> code = Handle<Code>::null(); | 579 Handle<Code> code = Handle<Code>::null(); |
| 580 Handle<JSFunction> function = Handle<JSFunction>::null(); | |
| 581 Handle<String> function_name = Handle<String>::null(); | |
| 582 if (FLAG_wasm_num_compilation_tasks != 0) { | 580 if (FLAG_wasm_num_compilation_tasks != 0) { |
| 583 code = results[i]; | 581 code = results[i]; |
| 584 } else { | 582 } else { |
| 585 // Compile the function. | 583 // Compile the function. |
| 586 code = compiler::WasmCompilationUnit::CompileWasmFunction( | 584 code = compiler::WasmCompilationUnit::CompileWasmFunction( |
| 587 &thrower, isolate, &module_env, &func); | 585 &thrower, isolate, &module_env, &func); |
| 588 } | 586 } |
| 589 if (code.is_null()) { | 587 if (code.is_null()) { |
| 590 thrower.Error("Compilation of #%d:%.*s failed.", i, str.length(), | 588 thrower.Error("Compilation of #%d:%.*s failed.", i, str.length(), |
| 591 str.start()); | 589 str.start()); |
| 592 return false; | 590 return false; |
| 593 } | 591 } |
| 594 if (func.exported) { | |
| 595 function_name = factory->InternalizeUtf8String(str); | |
| 596 function = compiler::CompileJSToWasmWrapper( | |
| 597 isolate, &module_env, function_name, code, instance.js_object, i); | |
| 598 code_stats.Record(function->code()); | |
| 599 } | |
| 600 if (!code.is_null()) { | 592 if (!code.is_null()) { |
| 601 // Install the code into the linker table. | 593 // Install the code into the linker table. |
| 602 module_env.linker->Finish(i, code); | 594 module_env.linker->Finish(i, code); |
| 603 code_table->set(i, *code); | 595 code_table->set(i, *code); |
| 604 code_stats.Record(*code); | 596 code_stats.Record(*code); |
| 605 } | 597 } |
| 606 if (func.exported) { | |
| 607 // Exported functions are installed as read-only properties on the | |
| 608 // module. | |
| 609 desc.set_value(function); | |
| 610 Maybe<bool> status = JSReceiver::DefineOwnProperty( | |
| 611 isolate, instance.js_object, function_name, &desc, | |
| 612 Object::THROW_ON_ERROR); | |
| 613 if (!status.IsJust()) | |
| 614 thrower.Error("export of %.*s failed.", str.length(), str.start()); | |
| 615 } | |
| 616 } | 598 } |
| 617 return true; | 599 return true; |
| 618 } | 600 } |
| 619 } // namespace | 601 } // namespace |
| 620 | 602 |
| 621 // Instantiates a wasm module as a JSObject. | 603 // Instantiates a wasm module as a JSObject. |
| 622 // * allocates a backing store of {mem_size} bytes. | 604 // * allocates a backing store of {mem_size} bytes. |
| 623 // * installs a named property "memory" for that buffer if exported | 605 // * installs a named property "memory" for that buffer if exported |
| 624 // * installs named properties on the object for exported functions | 606 // * installs named properties on the object for exported functions |
| 625 // * compiles wasm code to machine code | 607 // * compiles wasm code to machine code |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 | 760 |
| 779 // Patch all direct call sites. | 761 // Patch all direct call sites. |
| 780 linker.Link(instance.function_table, this->function_table); | 762 linker.Link(instance.function_table, this->function_table); |
| 781 instance.js_object->SetInternalField(kWasmModuleFunctionTable, | 763 instance.js_object->SetInternalField(kWasmModuleFunctionTable, |
| 782 Smi::FromInt(0)); | 764 Smi::FromInt(0)); |
| 783 | 765 |
| 784 //------------------------------------------------------------------------- | 766 //------------------------------------------------------------------------- |
| 785 // Create and populate the exports object. | 767 // Create and populate the exports object. |
| 786 //------------------------------------------------------------------------- | 768 //------------------------------------------------------------------------- |
| 787 if (export_table.size() > 0 || mem_export) { | 769 if (export_table.size() > 0 || mem_export) { |
| 788 // Create the "exports" object. | 770 Handle<JSObject> exports_object; |
| 789 Handle<JSFunction> object_function = Handle<JSFunction>( | 771 if (origin == kWasmOrigin) { |
| 790 isolate->native_context()->object_function(), isolate); | 772 // Create the "exports" object. |
| 791 Handle<JSObject> exports_object = | 773 Handle<JSFunction> object_function = Handle<JSFunction>( |
| 792 factory->NewJSObject(object_function, TENURED); | 774 isolate->native_context()->object_function(), isolate); |
| 793 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); | 775 exports_object = factory->NewJSObject(object_function, TENURED); |
| 794 JSObject::AddProperty(instance.js_object, exports_name, exports_object, | 776 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); |
| 795 READ_ONLY); | 777 JSObject::AddProperty(instance.js_object, exports_name, exports_object, |
| 778 READ_ONLY); |
| 779 } else { |
| 780 // Just export the functions directly on the object returned. |
| 781 exports_object = instance.js_object; |
| 782 } |
| 796 | 783 |
| 797 // Compile wrappers and add them to the exports object. | 784 // Compile wrappers and add them to the exports object. |
| 798 for (const WasmExport& exp : export_table) { | 785 for (const WasmExport& exp : export_table) { |
| 799 if (thrower.error()) break; | 786 if (thrower.error()) break; |
| 800 WasmName str = GetName(exp.name_offset, exp.name_length); | 787 WasmName str = GetName(exp.name_offset, exp.name_length); |
| 801 Handle<String> name = factory->InternalizeUtf8String(str); | 788 Handle<String> name = factory->InternalizeUtf8String(str); |
| 802 Handle<Code> code = linker.GetFunctionCode(exp.func_index); | 789 Handle<Code> code = linker.GetFunctionCode(exp.func_index); |
| 803 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( | 790 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( |
| 804 isolate, &module_env, name, code, instance.js_object, | 791 isolate, &module_env, name, code, instance.js_object, |
| 805 exp.func_index); | 792 exp.func_index); |
| 806 code_stats.Record(function->code()); | 793 code_stats.Record(function->code()); |
| 807 desc.set_value(function); | 794 desc.set_value(function); |
| 808 Maybe<bool> status = JSReceiver::DefineOwnProperty( | 795 Maybe<bool> status = JSReceiver::DefineOwnProperty( |
| 809 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); | 796 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); |
| 810 if (!status.IsJust()) | 797 if (!status.IsJust()) { |
| 811 thrower.Error("export of %.*s failed.", str.length(), str.start()); | 798 thrower.Error("export of %.*s failed.", str.length(), str.start()); |
| 799 break; |
| 800 } |
| 812 } | 801 } |
| 813 | 802 |
| 814 if (mem_export) { | 803 if (mem_export) { |
| 815 // Export the memory as a named property. | 804 // Export the memory as a named property. |
| 816 Handle<String> name = factory->InternalizeUtf8String("memory"); | 805 Handle<String> name = factory->InternalizeUtf8String("memory"); |
| 817 JSObject::AddProperty(exports_object, name, instance.mem_buffer, | 806 JSObject::AddProperty(exports_object, name, instance.mem_buffer, |
| 818 READ_ONLY); | 807 READ_ONLY); |
| 819 } | 808 } |
| 820 } | 809 } |
| 821 } | 810 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 const WasmFunction* function = &module->functions[index]; | 860 const WasmFunction* function = &module->functions[index]; |
| 872 return GetWasmCallDescriptor(zone, function->sig); | 861 return GetWasmCallDescriptor(zone, function->sig); |
| 873 } | 862 } |
| 874 | 863 |
| 875 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, | 864 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, |
| 876 const byte* module_end, bool asm_js) { | 865 const byte* module_end, bool asm_js) { |
| 877 HandleScope scope(isolate); | 866 HandleScope scope(isolate); |
| 878 Zone zone(isolate->allocator()); | 867 Zone zone(isolate->allocator()); |
| 879 // Decode the module, but don't verify function bodies, since we'll | 868 // Decode the module, but don't verify function bodies, since we'll |
| 880 // be compiling them anyway. | 869 // be compiling them anyway. |
| 881 ModuleResult result = DecodeWasmModule(isolate, &zone, module_start, | 870 ModuleResult result = |
| 882 module_end, false, kWasmOrigin); | 871 DecodeWasmModule(isolate, &zone, module_start, module_end, false, |
| 872 asm_js ? kAsmJsOrigin : kWasmOrigin); |
| 883 if (result.failed()) { | 873 if (result.failed()) { |
| 884 if (result.val) { | 874 if (result.val) { |
| 885 delete result.val; | 875 delete result.val; |
| 886 } | 876 } |
| 887 // Module verification failed. throw. | 877 // Module verification failed. throw. |
| 888 std::ostringstream str; | 878 std::ostringstream str; |
| 889 str << "WASM.compileRun() failed: " << result; | 879 str << "WASM.compileRun() failed: " << result; |
| 890 isolate->Throw( | 880 isolate->Throw( |
| 891 *isolate->factory()->NewStringFromAsciiChecked(str.str().c_str())); | 881 *isolate->factory()->NewStringFromAsciiChecked(str.str().c_str())); |
| 892 return -1; | 882 return -1; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 916 instance.function_table = BuildFunctionTable(isolate, module); | 906 instance.function_table = BuildFunctionTable(isolate, module); |
| 917 | 907 |
| 918 // Create module environment. | 908 // Create module environment. |
| 919 WasmLinker linker(isolate, module->functions.size()); | 909 WasmLinker linker(isolate, module->functions.size()); |
| 920 ModuleEnv module_env; | 910 ModuleEnv module_env; |
| 921 module_env.module = module; | 911 module_env.module = module; |
| 922 module_env.instance = &instance; | 912 module_env.instance = &instance; |
| 923 module_env.linker = &linker; | 913 module_env.linker = &linker; |
| 924 module_env.origin = module->origin; | 914 module_env.origin = module->origin; |
| 925 | 915 |
| 916 if (module->export_table.size() == 0) { |
| 917 thrower.Error("WASM.compileRun() failed: no exported functions"); |
| 918 return -2; |
| 919 } |
| 920 |
| 926 // Compile all functions. | 921 // Compile all functions. |
| 927 Handle<Code> main_code = Handle<Code>::null(); // record last code. | |
| 928 uint32_t index = 0; | |
| 929 int main_index = 0; | |
| 930 for (const WasmFunction& func : module->functions) { | 922 for (const WasmFunction& func : module->functions) { |
| 931 DCHECK_EQ(index, func.func_index); | 923 // Compile the function and install it in the linker. |
| 932 // Compile the function and install it in the code table. | |
| 933 Handle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction( | 924 Handle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction( |
| 934 &thrower, isolate, &module_env, &func); | 925 &thrower, isolate, &module_env, &func); |
| 935 if (!code.is_null()) { | 926 if (!code.is_null()) linker.Finish(func.func_index, code); |
| 936 if (func.exported) { | |
| 937 main_code = code; | |
| 938 main_index = index; | |
| 939 } | |
| 940 linker.Finish(index, code); | |
| 941 } | |
| 942 if (thrower.error()) return -1; | 927 if (thrower.error()) return -1; |
| 943 index++; | |
| 944 } | |
| 945 | |
| 946 if (main_code.is_null()) { | |
| 947 thrower.Error("WASM.compileRun() failed: no main code found"); | |
| 948 return -1; | |
| 949 } | 928 } |
| 950 | 929 |
| 951 linker.Link(instance.function_table, instance.module->function_table); | 930 linker.Link(instance.function_table, instance.module->function_table); |
| 952 | 931 |
| 953 // Wrap the main code so it can be called as a JS function. | 932 // Wrap the main code so it can be called as a JS function. |
| 933 uint32_t main_index = module->export_table.back().func_index; |
| 934 Handle<Code> main_code = linker.GetFunctionCode(main_index); |
| 954 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main"); | 935 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main"); |
| 955 Handle<JSObject> module_object = Handle<JSObject>(0, isolate); | 936 Handle<JSObject> module_object = Handle<JSObject>(0, isolate); |
| 956 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( | 937 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( |
| 957 isolate, &module_env, name, main_code, module_object, main_index); | 938 isolate, &module_env, name, main_code, module_object, main_index); |
| 958 | 939 |
| 959 // Call the JS function. | 940 // Call the JS function. |
| 960 Handle<Object> undefined(isolate->heap()->undefined_value(), isolate); | 941 Handle<Object> undefined(isolate->heap()->undefined_value(), isolate); |
| 961 MaybeHandle<Object> retval = | 942 MaybeHandle<Object> retval = |
| 962 Execution::Call(isolate, jsfunc, undefined, 0, nullptr); | 943 Execution::Call(isolate, jsfunc, undefined, 0, nullptr); |
| 963 | 944 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 981 uint32_t func_index) { | 962 uint32_t func_index) { |
| 982 Object* func_names_arr_obj = wasm->GetInternalField(kWasmFunctionNamesArray); | 963 Object* func_names_arr_obj = wasm->GetInternalField(kWasmFunctionNamesArray); |
| 983 if (func_names_arr_obj->IsUndefined()) return Handle<String>::null(); | 964 if (func_names_arr_obj->IsUndefined()) return Handle<String>::null(); |
| 984 return GetWasmFunctionNameFromTable( | 965 return GetWasmFunctionNameFromTable( |
| 985 handle(ByteArray::cast(func_names_arr_obj)), func_index); | 966 handle(ByteArray::cast(func_names_arr_obj)), func_index); |
| 986 } | 967 } |
| 987 | 968 |
| 988 } // namespace wasm | 969 } // namespace wasm |
| 989 } // namespace internal | 970 } // namespace internal |
| 990 } // namespace v8 | 971 } // namespace v8 |
| OLD | NEW |