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 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
959 | 959 |
960 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone, | 960 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone, |
961 uint32_t index) { | 961 uint32_t index) { |
962 DCHECK(IsValidFunction(index)); | 962 DCHECK(IsValidFunction(index)); |
963 // Always make a direct call to whatever is in the table at that location. | 963 // Always make a direct call to whatever is in the table at that location. |
964 // A wrapper will be generated for FFI calls. | 964 // A wrapper will be generated for FFI calls. |
965 const WasmFunction* function = &module->functions[index]; | 965 const WasmFunction* function = &module->functions[index]; |
966 return GetWasmCallDescriptor(zone, function->sig); | 966 return GetWasmCallDescriptor(zone, function->sig); |
967 } | 967 } |
968 | 968 |
969 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, | |
970 const byte* module_end, bool asm_js) { | |
971 HandleScope scope(isolate); | |
972 Zone zone(isolate->allocator()); | |
973 // Decode the module, but don't verify function bodies, since we'll | |
974 // be compiling them anyway. | |
975 ModuleResult result = | |
976 DecodeWasmModule(isolate, &zone, module_start, module_end, false, | |
977 asm_js ? kAsmJsOrigin : kWasmOrigin); | |
978 if (result.failed()) { | |
979 if (result.val) { | |
980 delete result.val; | |
981 } | |
982 // Module verification failed. throw. | |
983 std::ostringstream str; | |
984 str << "WASM.compileRun() failed: " << result; | |
985 isolate->Throw( | |
986 *isolate->factory()->NewStringFromAsciiChecked(str.str().c_str())); | |
987 return -1; | |
988 } | |
989 | |
990 int32_t retval = CompileAndRunWasmModule(isolate, result.val); | |
991 delete result.val; | |
992 return retval; | |
993 } | |
994 | |
995 int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module) { | |
996 ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); | |
997 WasmModuleInstance instance(module); | |
998 Handle<FixedArray> code_table = module->CompileFunctions(isolate); | |
999 | |
1000 if (code_table.is_null()) return -1; | |
1001 | |
1002 for (uint32_t i = 0; i < module->functions.size(); ++i) { | |
1003 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | |
1004 instance.function_code[i] = code; | |
1005 } | |
1006 | |
1007 // Allocate and initialize the linear memory. | |
1008 if (!AllocateMemory(&thrower, isolate, &instance)) { | |
1009 return -1; | |
1010 } | |
1011 LoadDataSegments(module, instance.mem_start, instance.mem_size); | |
1012 | |
1013 // Allocate the globals area if necessary. | |
1014 if (!AllocateGlobals(&thrower, isolate, &instance)) { | |
1015 return -1; | |
1016 } | |
1017 | |
1018 ModuleEnv module_env; | |
1019 module_env.module = module; | |
1020 module_env.instance = &instance; | |
1021 module_env.origin = module->origin; | |
1022 InitializePlaceholders(isolate->factory(), &module_env.placeholders, | |
1023 module->functions.size()); | |
1024 if (module->export_table.size() == 0) { | |
1025 thrower.Error("WASM.compileRun() failed: no exported functions"); | |
1026 return -2; | |
1027 } | |
1028 | |
1029 // Compile all functions. | |
1030 for (const WasmFunction& func : module->functions) { | |
1031 // Compile the function and install it in the linker. | |
1032 Handle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction( | |
1033 &thrower, isolate, &module_env, &func); | |
1034 if (!code.is_null()) instance.function_code[func.func_index] = code; | |
1035 if (thrower.error()) return -1; | |
1036 } | |
1037 | |
1038 LinkModuleFunctions(isolate, instance.function_code); | |
1039 | |
1040 // Wrap the main code so it can be called as a JS function. | |
1041 uint32_t main_index = module->export_table.back().func_index; | |
1042 Handle<Code> main_code = instance.function_code[main_index]; | |
1043 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main"); | |
1044 Handle<JSObject> module_object = Handle<JSObject>(0, isolate); | |
1045 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( | |
1046 isolate, &module_env, name, main_code, module_object, main_index); | |
1047 | |
1048 // Call the JS function. | |
1049 Handle<Object> undefined = isolate->factory()->undefined_value(); | |
1050 MaybeHandle<Object> retval = | |
1051 Execution::Call(isolate, jsfunc, undefined, 0, nullptr); | |
1052 | |
1053 // The result should be a number. | |
1054 if (retval.is_null()) { | |
1055 thrower.Error("WASM.compileRun() failed: Invocation was null"); | |
1056 return -1; | |
1057 } | |
1058 Handle<Object> result = retval.ToHandleChecked(); | |
1059 if (result->IsSmi()) { | |
1060 return Smi::cast(*result)->value(); | |
1061 } | |
1062 if (result->IsHeapNumber()) { | |
1063 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | |
1064 } | |
1065 thrower.Error("WASM.compileRun() failed: Return value should be number"); | |
1066 return -1; | |
1067 } | |
1068 | |
1069 Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm, | 969 Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm, |
1070 uint32_t func_index) { | 970 uint32_t func_index) { |
1071 if (!wasm->IsUndefined(isolate)) { | 971 if (!wasm->IsUndefined(isolate)) { |
1072 Handle<ByteArray> func_names_arr_obj( | 972 Handle<ByteArray> func_names_arr_obj( |
1073 ByteArray::cast(Handle<JSObject>::cast(wasm)->GetInternalField( | 973 ByteArray::cast(Handle<JSObject>::cast(wasm)->GetInternalField( |
1074 kWasmFunctionNamesArray)), | 974 kWasmFunctionNamesArray)), |
1075 isolate); | 975 isolate); |
1076 // TODO(clemens): Extract this from the module bytes; skip whole function | 976 // TODO(clemens): Extract this from the module bytes; skip whole function |
1077 // name table. | 977 // name table. |
1078 Handle<Object> name; | 978 Handle<Object> name; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1119 } | 1019 } |
1120 | 1020 |
1121 WasmDebugInfo* GetDebugInfo(JSObject* wasm) { | 1021 WasmDebugInfo* GetDebugInfo(JSObject* wasm) { |
1122 Object* info = wasm->GetInternalField(kWasmDebugInfo); | 1022 Object* info = wasm->GetInternalField(kWasmDebugInfo); |
1123 if (!info->IsUndefined(wasm->GetIsolate())) return WasmDebugInfo::cast(info); | 1023 if (!info->IsUndefined(wasm->GetIsolate())) return WasmDebugInfo::cast(info); |
1124 Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(handle(wasm)); | 1024 Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(handle(wasm)); |
1125 wasm->SetInternalField(kWasmDebugInfo, *new_info); | 1025 wasm->SetInternalField(kWasmDebugInfo, *new_info); |
1126 return *new_info; | 1026 return *new_info; |
1127 } | 1027 } |
1128 | 1028 |
1029 namespace testing { | |
1030 | |
1031 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, | |
1032 const byte* module_end, bool asm_js) { | |
1033 HandleScope scope(isolate); | |
1034 Zone zone(isolate->allocator()); | |
1035 ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); | |
1036 | |
1037 // Decode the module, but don't verify function bodies, since we'll | |
1038 // be compiling them anyway. | |
1039 ModuleResult decoding_result = | |
1040 DecodeWasmModule(isolate, &zone, module_start, module_end, false, | |
1041 asm_js ? kAsmJsOrigin : kWasmOrigin); | |
1042 if (decoding_result.failed()) { | |
1043 // Module verification failed. throw. | |
1044 thrower.Error("WASM.compileRun() failed: %s", | |
1045 decoding_result.error_msg.get()); | |
ahaas
2016/06/23 13:49:19
Should you not return here?
Mircea Trofin
2016/06/23 15:04:14
Good catch - yes, we should.
| |
1046 } | |
1047 std::unique_ptr<const WasmModule> module(decoding_result.val); | |
1048 | |
1049 if (module->import_table.size() > 0) { | |
1050 thrower.Error("Not supported: module has imports."); | |
1051 } | |
1052 if (module->export_table.size() == 0) { | |
1053 thrower.Error("Not supported: module has no exports."); | |
1054 } | |
1055 | |
1056 if (thrower.error()) return -1; | |
1057 | |
1058 Handle<JSObject> instance = | |
1059 module | |
1060 ->Instantiate(isolate, Handle<JSReceiver>::null(), | |
1061 Handle<JSArrayBuffer>::null()) | |
1062 .ToHandleChecked(); | |
1063 | |
1064 Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports"); | |
1065 Handle<JSObject> exports_object = Handle<JSObject>::cast( | |
1066 JSObject::GetProperty(instance, exports).ToHandleChecked()); | |
1067 Handle<Name> main_name = isolate->factory()->NewStringFromStaticChars("main"); | |
1068 PropertyDescriptor desc; | |
1069 Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor( | |
1070 isolate, exports_object, main_name, &desc); | |
1071 if (!property_found.FromMaybe(false)) return -1; | |
1072 | |
1073 Handle<JSFunction> main_export = Handle<JSFunction>::cast(desc.value()); | |
1074 | |
1075 // Call the JS function. | |
1076 Handle<Object> undefined = isolate->factory()->undefined_value(); | |
1077 MaybeHandle<Object> retval = | |
1078 Execution::Call(isolate, main_export, undefined, 0, nullptr); | |
1079 | |
1080 // The result should be a number. | |
1081 if (retval.is_null()) { | |
1082 thrower.Error("WASM.compileRun() failed: Invocation was null"); | |
1083 return -1; | |
1084 } | |
1085 Handle<Object> result = retval.ToHandleChecked(); | |
1086 if (result->IsSmi()) { | |
1087 return Smi::cast(*result)->value(); | |
1088 } | |
1089 if (result->IsHeapNumber()) { | |
1090 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | |
1091 } | |
1092 thrower.Error("WASM.compileRun() failed: Return value should be number"); | |
1093 return -1; | |
1094 } | |
1095 | |
1096 } // namespace testing | |
1129 } // namespace wasm | 1097 } // namespace wasm |
1130 } // namespace internal | 1098 } // namespace internal |
1131 } // namespace v8 | 1099 } // namespace v8 |
OLD | NEW |