Chromium Code Reviews| 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 |