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 <memory> | 5 #include <memory> |
| 6 | 6 |
| 7 #include "src/base/atomic-utils.h" | 7 #include "src/base/atomic-utils.h" |
| 8 #include "src/macro-assembler.h" | 8 #include "src/macro-assembler.h" |
| 9 #include "src/objects.h" | 9 #include "src/objects.h" |
| 10 #include "src/property-descriptor.h" | 10 #include "src/property-descriptor.h" |
| 11 #include "src/v8.h" | 11 #include "src/v8.h" |
| 12 | 12 |
| 13 #include "src/simulator.h" | 13 #include "src/simulator.h" |
| 14 | 14 |
| 15 #include "src/wasm/ast-decoder.h" | 15 #include "src/wasm/ast-decoder.h" |
| 16 #include "src/wasm/module-decoder.h" | 16 #include "src/wasm/module-decoder.h" |
| 17 #include "src/wasm/wasm-debug.h" | 17 #include "src/wasm/wasm-debug.h" |
| 18 #include "src/wasm/wasm-function-name-table.h" | 18 #include "src/wasm/wasm-function-name-table.h" |
| 19 #include "src/wasm/wasm-module.h" | 19 #include "src/wasm/wasm-module.h" |
| 20 #include "src/wasm/wasm-result.h" | 20 #include "src/wasm/wasm-result.h" |
| 21 | 21 |
| 22 #include "src/compiler/wasm-compiler.h" | 22 #include "src/compiler/wasm-compiler.h" |
| 23 | 23 |
| 24 namespace v8 { | 24 namespace v8 { |
| 25 namespace internal { | 25 namespace internal { |
| 26 namespace wasm { | 26 namespace wasm { |
| 27 | 27 |
| 28 enum JSFunctionExportInternalField { | |
|
Mircea Trofin
2016/08/03 22:52:16
You could move this in the anonymous namespace bel
| |
| 29 kInternalModuleInstance, | |
| 30 kInternalArity, | |
| 31 kInternalSignature | |
| 32 }; | |
| 33 | |
| 28 static const int kPlaceholderMarker = 1000000000; | 34 static const int kPlaceholderMarker = 1000000000; |
| 29 | 35 |
| 30 static const char* wasmSections[] = { | 36 static const char* wasmSections[] = { |
| 31 #define F(enumerator, order, string) string, | 37 #define F(enumerator, order, string) string, |
| 32 FOR_EACH_WASM_SECTION_TYPE(F) | 38 FOR_EACH_WASM_SECTION_TYPE(F) |
| 33 #undef F | 39 #undef F |
| 34 "<unknown>" // entry for "Max" | 40 "<unknown>" // entry for "Max" |
| 35 }; | 41 }; |
| 36 | 42 |
| 37 static uint8_t wasmSectionsLengths[]{ | 43 static uint8_t wasmSectionsLengths[]{ |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 os << "+" << pair.function_->func_index; | 115 os << "+" << pair.function_->func_index; |
| 110 } | 116 } |
| 111 } else { | 117 } else { |
| 112 os << "?"; | 118 os << "?"; |
| 113 } | 119 } |
| 114 return os; | 120 return os; |
| 115 } | 121 } |
| 116 | 122 |
| 117 Handle<JSFunction> WrapExportCodeAsJSFunction( | 123 Handle<JSFunction> WrapExportCodeAsJSFunction( |
| 118 Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, | 124 Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, |
| 119 Handle<JSObject> module_instance) { | 125 MaybeHandle<ByteArray> maybe_signature, Handle<JSObject> module_instance) { |
| 120 Handle<SharedFunctionInfo> shared = | 126 Handle<SharedFunctionInfo> shared = |
| 121 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); | 127 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); |
| 122 shared->set_length(arity); | 128 shared->set_length(arity); |
| 123 shared->set_internal_formal_parameter_count(arity); | 129 shared->set_internal_formal_parameter_count(arity); |
| 124 Handle<JSFunction> function = isolate->factory()->NewFunction( | 130 Handle<JSFunction> function = isolate->factory()->NewFunction( |
| 125 isolate->wasm_function_map(), name, export_code); | 131 isolate->wasm_function_map(), name, export_code); |
| 126 function->set_shared(*shared); | 132 function->set_shared(*shared); |
| 127 | 133 |
| 128 function->SetInternalField(0, *module_instance); | 134 function->SetInternalField(kInternalModuleInstance, *module_instance); |
| 135 // add another Internal Field as the function arity | |
| 136 function->SetInternalField(kInternalArity, Smi::FromInt(arity)); | |
| 137 // add another Internal Field as the signature of the foreign function | |
| 138 Handle<ByteArray> signature; | |
| 139 if (maybe_signature.ToHandle(&signature)) { | |
| 140 function->SetInternalField(kInternalSignature, *signature); | |
| 141 } | |
| 129 return function; | 142 return function; |
| 130 } | 143 } |
| 131 | 144 |
| 132 namespace { | 145 namespace { |
| 133 // Internal constants for the layout of the module object. | 146 // Internal constants for the layout of the module object. |
| 134 const int kWasmModuleFunctionTable = 0; | 147 const int kWasmModuleFunctionTable = 0; |
| 135 const int kWasmModuleCodeTable = 1; | 148 const int kWasmModuleCodeTable = 1; |
| 136 const int kWasmMemArrayBuffer = 2; | 149 const int kWasmMemArrayBuffer = 2; |
| 137 const int kWasmGlobalsArrayBuffer = 3; | 150 const int kWasmGlobalsArrayBuffer = 3; |
| 138 // TODO(clemensh): Remove function name array, extract names from module bytes. | 151 // TODO(clemensh): Remove function name array, extract names from module bytes. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 kOutputCount, // Smi. an uint32_t | 189 kOutputCount, // Smi. an uint32_t |
| 177 kSignature, // ByteArray. A copy of the data in FunctionSig | 190 kSignature, // ByteArray. A copy of the data in FunctionSig |
| 178 kWasmImportDataTableSize // Sentinel value. | 191 kWasmImportDataTableSize // Sentinel value. |
| 179 }; | 192 }; |
| 180 | 193 |
| 181 enum WasmExportMetadata { | 194 enum WasmExportMetadata { |
| 182 kExportCode, // Code | 195 kExportCode, // Code |
| 183 kExportName, // String | 196 kExportName, // String |
| 184 kExportArity, // Smi, an int | 197 kExportArity, // Smi, an int |
| 185 kExportedFunctionIndex, // Smi, an uint32_t | 198 kExportedFunctionIndex, // Smi, an uint32_t |
| 199 kExportedSignature, // ByteArray. A copy of the data in FunctionSig | |
| 186 kWasmExportMetadataTableSize // Sentinel value. | 200 kWasmExportMetadataTableSize // Sentinel value. |
| 187 }; | 201 }; |
| 188 | 202 |
| 189 enum WasmSegmentInfo { | 203 enum WasmSegmentInfo { |
| 190 kDestAddr, // Smi. an uint32_t | 204 kDestAddr, // Smi. an uint32_t |
| 191 kSourceSize, // Smi. an uint32_t | 205 kSourceSize, // Smi. an uint32_t |
| 192 kWasmSegmentInfoSize // Sentinel value. | 206 kWasmSegmentInfoSize // Sentinel value. |
| 193 }; | 207 }; |
| 194 | 208 |
| 195 enum WasmIndirectFunctionTableMetadata { | 209 enum WasmIndirectFunctionTableMetadata { |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 641 CHECK(ret_count >= 0); | 655 CHECK(ret_count >= 0); |
| 642 Handle<ByteArray> sig_data = | 656 Handle<ByteArray> sig_data = |
| 643 data->GetValueChecked<ByteArray>(isolate, kSignature); | 657 data->GetValueChecked<ByteArray>(isolate, kSignature); |
| 644 int sig_data_size = sig_data->length(); | 658 int sig_data_size = sig_data->length(); |
| 645 int param_count = sig_data_size - ret_count; | 659 int param_count = sig_data_size - ret_count; |
| 646 CHECK(param_count >= 0); | 660 CHECK(param_count >= 0); |
| 647 | 661 |
| 648 MaybeHandle<JSFunction> function = LookupFunction( | 662 MaybeHandle<JSFunction> function = LookupFunction( |
| 649 *thrower, isolate->factory(), ffi, index, module_name, function_name); | 663 *thrower, isolate->factory(), ffi, index, module_name, function_name); |
| 650 if (function.is_null()) return false; | 664 if (function.is_null()) return false; |
| 651 | 665 Handle<Code> code; |
| 652 { | 666 Handle<JSFunction> func = function.ToHandleChecked(); |
| 667 Handle<Code> export_wrapper_code = handle(func->code()); | |
| 668 bool isMatch = false; | |
| 669 if (export_wrapper_code->kind() == Code::JS_TO_WASM_FUNCTION) { | |
| 670 int exported_param_count = | |
| 671 Smi::cast(func->GetInternalField(kInternalArity))->value(); | |
| 672 Handle<ByteArray> exportedSig = Handle<ByteArray>( | |
| 673 ByteArray::cast(func->GetInternalField(kInternalSignature))); | |
| 674 if (exported_param_count == param_count && | |
| 675 exportedSig->length() == sig_data->length() && | |
| 676 memcmp(exportedSig->data(), sig_data->data(), | |
| 677 exportedSig->length()) == 0) { | |
| 678 isMatch = true; | |
| 679 } | |
| 680 } | |
| 681 if (isMatch) { | |
| 682 int wasm_count = 0; | |
| 683 int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | |
| 684 for (RelocIterator it(*export_wrapper_code, mask); !it.done(); | |
| 685 it.next()) { | |
| 686 RelocInfo* rinfo = it.rinfo(); | |
| 687 Address target_address = rinfo->target_address(); | |
| 688 Code* target = Code::GetCodeFromTargetAddress(target_address); | |
| 689 if (target->kind() == Code::WASM_FUNCTION) { | |
| 690 ++wasm_count; | |
| 691 code = handle(target); | |
| 692 } | |
| 693 } | |
| 694 DCHECK(wasm_count == 1); | |
| 695 } else { | |
| 653 // Copy the signature to avoid a raw pointer into a heap object when | 696 // Copy the signature to avoid a raw pointer into a heap object when |
| 654 // GC can happen. | 697 // GC can happen. |
| 655 Zone zone(isolate->allocator()); | 698 Zone zone(isolate->allocator()); |
| 656 MachineRepresentation* reps = | 699 MachineRepresentation* reps = |
| 657 zone.NewArray<MachineRepresentation>(sig_data_size); | 700 zone.NewArray<MachineRepresentation>(sig_data_size); |
| 658 memcpy(reps, sig_data->data(), | 701 memcpy(reps, sig_data->data(), |
| 659 sizeof(MachineRepresentation) * sig_data_size); | 702 sizeof(MachineRepresentation) * sig_data_size); |
| 660 FunctionSig sig(ret_count, param_count, reps); | 703 FunctionSig sig(ret_count, param_count, reps); |
| 661 | 704 |
| 662 Handle<Code> code = compiler::CompileWasmToJSWrapper( | 705 code = compiler::CompileWasmToJSWrapper(isolate, func, &sig, index, |
| 663 isolate, function.ToHandleChecked(), &sig, index, module_name, | 706 module_name, function_name); |
| 664 function_name); | |
| 665 | |
| 666 imports.push_back(code); | |
| 667 } | 707 } |
| 708 imports.push_back(code); | |
| 668 } | 709 } |
| 669 } | 710 } |
| 670 return true; | 711 return true; |
| 671 } | 712 } |
| 672 | 713 |
| 673 void InitializeParallelCompilation( | 714 void InitializeParallelCompilation( |
| 674 Isolate* isolate, const std::vector<WasmFunction>& functions, | 715 Isolate* isolate, const std::vector<WasmFunction>& functions, |
| 675 std::vector<compiler::WasmCompilationUnit*>& compilation_units, | 716 std::vector<compiler::WasmCompilationUnit*>& compilation_units, |
| 676 ModuleEnv& module_env, ErrorThrower& thrower) { | 717 ModuleEnv& module_env, ErrorThrower& thrower) { |
| 677 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { | 718 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 962 for (int i = 0; i < exports_size; ++i) { | 1003 for (int i = 0; i < exports_size; ++i) { |
| 963 if (thrower->error()) return false; | 1004 if (thrower->error()) return false; |
| 964 Handle<FixedArray> export_metadata = | 1005 Handle<FixedArray> export_metadata = |
| 965 exports->GetValueChecked<FixedArray>(isolate, i); | 1006 exports->GetValueChecked<FixedArray>(isolate, i); |
| 966 Handle<Code> export_code = | 1007 Handle<Code> export_code = |
| 967 export_metadata->GetValueChecked<Code>(isolate, kExportCode); | 1008 export_metadata->GetValueChecked<Code>(isolate, kExportCode); |
| 968 RecordStats(isolate, *export_code); | 1009 RecordStats(isolate, *export_code); |
| 969 Handle<String> name = | 1010 Handle<String> name = |
| 970 export_metadata->GetValueChecked<String>(isolate, kExportName); | 1011 export_metadata->GetValueChecked<String>(isolate, kExportName); |
| 971 int arity = Smi::cast(export_metadata->get(kExportArity))->value(); | 1012 int arity = Smi::cast(export_metadata->get(kExportArity))->value(); |
| 1013 MaybeHandle<ByteArray> signature = | |
| 1014 export_metadata->GetValue<ByteArray>(isolate, kExportedSignature); | |
| 972 Handle<JSFunction> function = WrapExportCodeAsJSFunction( | 1015 Handle<JSFunction> function = WrapExportCodeAsJSFunction( |
| 973 isolate, export_code, name, arity, instance); | 1016 isolate, export_code, name, arity, signature, instance); |
| 974 desc.set_value(function); | 1017 desc.set_value(function); |
| 975 Maybe<bool> status = JSReceiver::DefineOwnProperty( | 1018 Maybe<bool> status = JSReceiver::DefineOwnProperty( |
| 976 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); | 1019 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); |
| 977 if (!status.IsJust()) { | 1020 if (!status.IsJust()) { |
| 978 thrower->Error("export of %.*s failed.", name->length(), | 1021 thrower->Error("export of %.*s failed.", name->length(), |
| 979 name->ToCString().get()); | 1022 name->ToCString().get()); |
| 980 return false; | 1023 return false; |
| 981 } | 1024 } |
| 982 } | 1025 } |
| 983 } | 1026 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1073 | 1116 |
| 1074 // Compile export functions. | 1117 // Compile export functions. |
| 1075 int export_size = static_cast<int>(export_table.size()); | 1118 int export_size = static_cast<int>(export_table.size()); |
| 1076 Handle<Code> startup_fct; | 1119 Handle<Code> startup_fct; |
| 1077 if (export_size > 0) { | 1120 if (export_size > 0) { |
| 1078 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); | 1121 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); |
| 1079 for (int i = 0; i < export_size; ++i) { | 1122 for (int i = 0; i < export_size; ++i) { |
| 1080 Handle<FixedArray> export_metadata = | 1123 Handle<FixedArray> export_metadata = |
| 1081 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); | 1124 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); |
| 1082 const WasmExport& exp = export_table[i]; | 1125 const WasmExport& exp = export_table[i]; |
| 1126 FunctionSig* funcSig = functions[exp.func_index].sig; | |
| 1127 Handle<ByteArray> exportedSig = | |
| 1128 factory->NewByteArray(static_cast<int>(funcSig->parameter_count() + | |
| 1129 funcSig->return_count()), | |
| 1130 TENURED); | |
| 1131 exportedSig->copy_in(0, | |
| 1132 reinterpret_cast<const byte*>(funcSig->raw_data()), | |
| 1133 exportedSig->length()); | |
| 1134 export_metadata->set(kExportedSignature, *exportedSig); | |
| 1083 WasmName str = GetName(exp.name_offset, exp.name_length); | 1135 WasmName str = GetName(exp.name_offset, exp.name_length); |
| 1084 Handle<String> name = factory->InternalizeUtf8String(str); | 1136 Handle<String> name = factory->InternalizeUtf8String(str); |
| 1085 Handle<Code> code = | 1137 Handle<Code> code = |
| 1086 temp_instance_for_compilation.function_code[exp.func_index]; | 1138 temp_instance_for_compilation.function_code[exp.func_index]; |
| 1087 Handle<Code> export_code = compiler::CompileJSToWasmWrapper( | 1139 Handle<Code> export_code = compiler::CompileJSToWasmWrapper( |
| 1088 isolate, &module_env, code, exp.func_index); | 1140 isolate, &module_env, code, exp.func_index); |
| 1089 if (thrower->error()) return nothing; | 1141 if (thrower->error()) return nothing; |
| 1090 export_metadata->set(kExportCode, *export_code); | 1142 export_metadata->set(kExportCode, *export_code); |
| 1091 export_metadata->set(kExportName, *name); | 1143 export_metadata->set(kExportName, *name); |
| 1092 export_metadata->set( | 1144 export_metadata->set( |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1336 | 1388 |
| 1337 // Run the start function if one was specified. | 1389 // Run the start function if one was specified. |
| 1338 MaybeHandle<FixedArray> maybe_startup_fct = | 1390 MaybeHandle<FixedArray> maybe_startup_fct = |
| 1339 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); | 1391 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); |
| 1340 Handle<FixedArray> metadata; | 1392 Handle<FixedArray> metadata; |
| 1341 if (maybe_startup_fct.ToHandle(&metadata)) { | 1393 if (maybe_startup_fct.ToHandle(&metadata)) { |
| 1342 HandleScope scope(isolate); | 1394 HandleScope scope(isolate); |
| 1343 Handle<Code> startup_code = | 1395 Handle<Code> startup_code = |
| 1344 metadata->GetValueChecked<Code>(isolate, kExportCode); | 1396 metadata->GetValueChecked<Code>(isolate, kExportCode); |
| 1345 int arity = Smi::cast(metadata->get(kExportArity))->value(); | 1397 int arity = Smi::cast(metadata->get(kExportArity))->value(); |
| 1398 MaybeHandle<ByteArray> startup_signature = | |
| 1399 metadata->GetValue<ByteArray>(isolate, kExportedSignature); | |
| 1346 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 1400 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
| 1347 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, | 1401 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, |
| 1348 js_object); | 1402 startup_signature, js_object); |
| 1349 RecordStats(isolate, *startup_code); | 1403 RecordStats(isolate, *startup_code); |
| 1350 // Call the JS function. | 1404 // Call the JS function. |
| 1351 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1405 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 1352 MaybeHandle<Object> retval = | 1406 MaybeHandle<Object> retval = |
| 1353 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); | 1407 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); |
| 1354 | 1408 |
| 1355 if (retval.is_null()) { | 1409 if (retval.is_null()) { |
| 1356 thrower.Error("WASM.instantiateModule(): start function failed"); | 1410 thrower.Error("WASM.instantiateModule(): start function failed"); |
| 1357 return nothing; | 1411 return nothing; |
| 1358 } | 1412 } |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1596 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 1650 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
| 1597 } | 1651 } |
| 1598 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 1652 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
| 1599 return -1; | 1653 return -1; |
| 1600 } | 1654 } |
| 1601 | 1655 |
| 1602 } // namespace testing | 1656 } // namespace testing |
| 1603 } // namespace wasm | 1657 } // namespace wasm |
| 1604 } // namespace internal | 1658 } // namespace internal |
| 1605 } // namespace v8 | 1659 } // namespace v8 |
| OLD | NEW |