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 |