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" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 os << "+" << pair.function_->func_index; | 109 os << "+" << pair.function_->func_index; |
| 110 } | 110 } |
| 111 } else { | 111 } else { |
| 112 os << "?"; | 112 os << "?"; |
| 113 } | 113 } |
| 114 return os; | 114 return os; |
| 115 } | 115 } |
| 116 | 116 |
| 117 Handle<JSFunction> WrapExportCodeAsJSFunction( | 117 Handle<JSFunction> WrapExportCodeAsJSFunction( |
| 118 Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, | 118 Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, |
| 119 Handle<JSObject> module_instance) { | 119 Handle<ByteArray> signature, Handle<JSObject> module_instance) { |
| 120 Handle<SharedFunctionInfo> shared = | 120 Handle<SharedFunctionInfo> shared = |
| 121 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); | 121 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); |
| 122 shared->set_length(arity); | 122 shared->set_length(arity); |
| 123 shared->set_internal_formal_parameter_count(arity); | 123 shared->set_internal_formal_parameter_count(arity); |
| 124 Handle<JSFunction> function = isolate->factory()->NewFunction( | 124 Handle<JSFunction> function = isolate->factory()->NewFunction( |
| 125 isolate->wasm_function_map(), name, export_code); | 125 isolate->wasm_function_map(), name, export_code); |
| 126 function->set_shared(*shared); | 126 function->set_shared(*shared); |
| 127 | 127 |
| 128 function->SetInternalField(0, *module_instance); | 128 function->SetInternalField(0, *module_instance); |
| 129 // add another Internal Field as the shared function | |
| 130 function->SetInternalField(1, *shared); | |
| 131 // add another Internal Field as the signature of the foreign function | |
| 132 function->SetInternalField(2, *signature); | |
|
Mircea Trofin
2016/08/01 23:38:32
This might fail, because we only specified a grand
| |
| 129 return function; | 133 return function; |
| 130 } | 134 } |
| 131 | 135 |
| 132 namespace { | 136 namespace { |
| 133 // Internal constants for the layout of the module object. | 137 // Internal constants for the layout of the module object. |
| 134 const int kWasmModuleFunctionTable = 0; | 138 const int kWasmModuleFunctionTable = 0; |
| 135 const int kWasmModuleCodeTable = 1; | 139 const int kWasmModuleCodeTable = 1; |
| 136 const int kWasmMemArrayBuffer = 2; | 140 const int kWasmMemArrayBuffer = 2; |
| 137 const int kWasmGlobalsArrayBuffer = 3; | 141 const int kWasmGlobalsArrayBuffer = 3; |
| 138 // TODO(clemensh): Remove function name array, extract names from module bytes. | 142 // 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 | 180 kOutputCount, // Smi. an uint32_t |
| 177 kSignature, // ByteArray. A copy of the data in FunctionSig | 181 kSignature, // ByteArray. A copy of the data in FunctionSig |
| 178 kWasmImportDataTableSize // Sentinel value. | 182 kWasmImportDataTableSize // Sentinel value. |
| 179 }; | 183 }; |
| 180 | 184 |
| 181 enum WasmExportMetadata { | 185 enum WasmExportMetadata { |
| 182 kExportCode, // Code | 186 kExportCode, // Code |
| 183 kExportName, // String | 187 kExportName, // String |
| 184 kExportArity, // Smi, an int | 188 kExportArity, // Smi, an int |
| 185 kExportedFunctionIndex, // Smi, an uint32_t | 189 kExportedFunctionIndex, // Smi, an uint32_t |
| 190 kExportedSignature, // ByteArray. A copy of the data in FunctionSig | |
| 186 kWasmExportMetadataTableSize // Sentinel value. | 191 kWasmExportMetadataTableSize // Sentinel value. |
| 187 }; | 192 }; |
| 188 | 193 |
| 189 enum WasmSegmentInfo { | 194 enum WasmSegmentInfo { |
| 190 kDestAddr, // Smi. an uint32_t | 195 kDestAddr, // Smi. an uint32_t |
| 191 kSourceSize, // Smi. an uint32_t | 196 kSourceSize, // Smi. an uint32_t |
| 192 kWasmSegmentInfoSize // Sentinel value. | 197 kWasmSegmentInfoSize // Sentinel value. |
| 193 }; | 198 }; |
| 194 | 199 |
| 195 uint32_t GetMinModuleMemSize(const WasmModule* module) { | 200 uint32_t GetMinModuleMemSize(const WasmModule* module) { |
| (...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 664 CHECK(ret_count >= 0); | 669 CHECK(ret_count >= 0); |
| 665 Handle<ByteArray> sig_data = data->GetValueChecked<ByteArray>(kSignature); | 670 Handle<ByteArray> sig_data = data->GetValueChecked<ByteArray>(kSignature); |
| 666 int sig_data_size = sig_data->length(); | 671 int sig_data_size = sig_data->length(); |
| 667 int param_count = sig_data_size - ret_count; | 672 int param_count = sig_data_size - ret_count; |
| 668 CHECK(param_count >= 0); | 673 CHECK(param_count >= 0); |
| 669 | 674 |
| 670 MaybeHandle<JSFunction> function = LookupFunction( | 675 MaybeHandle<JSFunction> function = LookupFunction( |
| 671 *thrower, isolate->factory(), ffi, index, module_name, function_name); | 676 *thrower, isolate->factory(), ffi, index, module_name, function_name); |
| 672 if (function.is_null()) return false; | 677 if (function.is_null()) return false; |
| 673 | 678 |
| 674 { | 679 Handle<Code> code; |
| 680 Handle<JSFunction> func = function.ToHandleChecked(); | |
| 681 Handle<Code> export_wrapper_code = handle(func->code()); | |
| 682 bool isMatch = true; | |
| 683 if (export_wrapper_code->kind() == Code::JS_TO_WASM_FUNCTION) { | |
| 684 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>( | |
| 685 SharedFunctionInfo::cast(func->GetInternalField(1))); | |
| 686 int exported_param_count = shared->length(); | |
| 687 // check whether two functions have same param count | |
|
Mircea Trofin
2016/08/01 23:38:32
You should get the parameter count from the wasm f
| |
| 688 if (exported_param_count != param_count) isMatch = false; | |
| 689 Handle<ByteArray> exportedSig = | |
| 690 Handle<ByteArray>(ByteArray::cast(func->GetInternalField(2))); | |
|
Mircea Trofin
2016/08/01 23:38:32
why continue computing exportedSig if isMatch=fals
| |
| 691 // check whether two functions have same signature | |
| 692 if (exportedSig->length() == sig_data->length()) { | |
| 693 for (int i = 0; i < exportedSig->length(); i++) { | |
| 694 if (exportedSig->get(i) != sig_data->get(i)) { | |
| 695 isMatch = false; | |
| 696 break; | |
| 697 } | |
| 698 } | |
| 699 } else { | |
| 700 isMatch = false; | |
| 701 } | |
| 702 if (isMatch) { | |
| 703 int wasm_count = 0; | |
| 704 int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | |
| 705 for (RelocIterator it(*export_wrapper_code, mask); !it.done(); | |
| 706 it.next()) { | |
| 707 RelocInfo* rinfo = it.rinfo(); | |
| 708 Address target_address = rinfo->target_address(); | |
| 709 Code* target = Code::GetCodeFromTargetAddress(target_address); | |
| 710 if (target->kind() == Code::WASM_FUNCTION) { | |
| 711 wasm_count++; | |
|
Mircea Trofin
2016/08/01 23:38:32
++wasm_count
| |
| 712 code = handle(target); | |
| 713 } | |
| 714 } | |
| 715 CHECK(wasm_count == 1); | |
|
Mircea Trofin
2016/08/01 23:38:32
DCHECK
| |
| 716 } | |
| 717 } | |
| 718 if (export_wrapper_code->kind() != Code::JS_TO_WASM_FUNCTION || | |
| 719 !isMatch) { | |
| 675 // Copy the signature to avoid a raw pointer into a heap object when | 720 // Copy the signature to avoid a raw pointer into a heap object when |
| 676 // GC can happen. | 721 // GC can happen. |
| 677 Zone zone(isolate->allocator()); | 722 Zone zone(isolate->allocator()); |
| 678 MachineRepresentation* reps = | 723 MachineRepresentation* reps = |
| 679 zone.NewArray<MachineRepresentation>(sig_data_size); | 724 zone.NewArray<MachineRepresentation>(sig_data_size); |
| 680 memcpy(reps, sig_data->data(), | 725 memcpy(reps, sig_data->data(), |
| 681 sizeof(MachineRepresentation) * sig_data_size); | 726 sizeof(MachineRepresentation) * sig_data_size); |
| 682 FunctionSig sig(ret_count, param_count, reps); | 727 FunctionSig sig(ret_count, param_count, reps); |
| 683 | 728 |
| 684 Handle<Code> code = compiler::CompileWasmToJSWrapper( | 729 code = compiler::CompileWasmToJSWrapper(isolate, func, &sig, index, |
| 685 isolate, function.ToHandleChecked(), &sig, index, module_name, | 730 module_name, function_name); |
| 686 function_name); | |
| 687 | |
| 688 imports.push_back(code); | |
| 689 } | 731 } |
| 732 imports.push_back(code); | |
| 690 } | 733 } |
| 691 } | 734 } |
| 692 return true; | 735 return true; |
| 693 } | 736 } |
| 694 | 737 |
| 695 void InitializeParallelCompilation( | 738 void InitializeParallelCompilation( |
| 696 Isolate* isolate, const std::vector<WasmFunction>& functions, | 739 Isolate* isolate, const std::vector<WasmFunction>& functions, |
| 697 std::vector<compiler::WasmCompilationUnit*>& compilation_units, | 740 std::vector<compiler::WasmCompilationUnit*>& compilation_units, |
| 698 ModuleEnv& module_env, ErrorThrower& thrower) { | 741 ModuleEnv& module_env, ErrorThrower& thrower) { |
| 699 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { | 742 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 983 for (int i = 0; i < exports_size; ++i) { | 1026 for (int i = 0; i < exports_size; ++i) { |
| 984 if (thrower->error()) return false; | 1027 if (thrower->error()) return false; |
| 985 Handle<FixedArray> export_metadata = | 1028 Handle<FixedArray> export_metadata = |
| 986 exports->GetValueChecked<FixedArray>(i); | 1029 exports->GetValueChecked<FixedArray>(i); |
| 987 Handle<Code> export_code = | 1030 Handle<Code> export_code = |
| 988 export_metadata->GetValueChecked<Code>(kExportCode); | 1031 export_metadata->GetValueChecked<Code>(kExportCode); |
| 989 RecordStats(isolate, *export_code); | 1032 RecordStats(isolate, *export_code); |
| 990 Handle<String> name = | 1033 Handle<String> name = |
| 991 export_metadata->GetValueChecked<String>(kExportName); | 1034 export_metadata->GetValueChecked<String>(kExportName); |
| 992 int arity = Smi::cast(export_metadata->get(kExportArity))->value(); | 1035 int arity = Smi::cast(export_metadata->get(kExportArity))->value(); |
| 1036 Handle<ByteArray> signature = | |
| 1037 export_metadata->GetValueChecked<ByteArray>(kExportedSignature); | |
| 993 Handle<JSFunction> function = WrapExportCodeAsJSFunction( | 1038 Handle<JSFunction> function = WrapExportCodeAsJSFunction( |
| 994 isolate, export_code, name, arity, instance); | 1039 isolate, export_code, name, arity, signature, instance); |
| 995 desc.set_value(function); | 1040 desc.set_value(function); |
| 996 Maybe<bool> status = JSReceiver::DefineOwnProperty( | 1041 Maybe<bool> status = JSReceiver::DefineOwnProperty( |
| 997 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); | 1042 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); |
| 998 if (!status.IsJust()) { | 1043 if (!status.IsJust()) { |
| 999 thrower->Error("export of %.*s failed.", name->length(), | 1044 thrower->Error("export of %.*s failed.", name->length(), |
| 1000 name->ToCString().get()); | 1045 name->ToCString().get()); |
| 1001 return false; | 1046 return false; |
| 1002 } | 1047 } |
| 1003 } | 1048 } |
| 1004 } | 1049 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1088 | 1133 |
| 1089 // Compile export functions. | 1134 // Compile export functions. |
| 1090 int export_size = static_cast<int>(export_table.size()); | 1135 int export_size = static_cast<int>(export_table.size()); |
| 1091 Handle<Code> startup_fct; | 1136 Handle<Code> startup_fct; |
| 1092 if (export_size > 0) { | 1137 if (export_size > 0) { |
| 1093 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); | 1138 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); |
| 1094 for (int i = 0; i < export_size; ++i) { | 1139 for (int i = 0; i < export_size; ++i) { |
| 1095 Handle<FixedArray> export_metadata = | 1140 Handle<FixedArray> export_metadata = |
| 1096 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); | 1141 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); |
| 1097 const WasmExport& exp = export_table[i]; | 1142 const WasmExport& exp = export_table[i]; |
| 1143 FunctionSig* funcSig = functions[exp.func_index].sig; | |
| 1144 Handle<ByteArray> exportedSig = | |
| 1145 factory->NewByteArray(static_cast<int>(funcSig->parameter_count() + | |
| 1146 funcSig->return_count()), | |
| 1147 TENURED); | |
| 1148 exportedSig->copy_in(0, | |
| 1149 reinterpret_cast<const byte*>(funcSig->raw_data()), | |
| 1150 exportedSig->length()); | |
| 1151 export_metadata->set(kExportedSignature, *exportedSig); | |
| 1098 WasmName str = GetName(exp.name_offset, exp.name_length); | 1152 WasmName str = GetName(exp.name_offset, exp.name_length); |
| 1099 Handle<String> name = factory->InternalizeUtf8String(str); | 1153 Handle<String> name = factory->InternalizeUtf8String(str); |
| 1100 Handle<Code> code = | 1154 Handle<Code> code = |
| 1101 temp_instance_for_compilation.function_code[exp.func_index]; | 1155 temp_instance_for_compilation.function_code[exp.func_index]; |
| 1102 Handle<Code> export_code = compiler::CompileJSToWasmWrapper( | 1156 Handle<Code> export_code = compiler::CompileJSToWasmWrapper( |
| 1103 isolate, &module_env, code, exp.func_index); | 1157 isolate, &module_env, code, exp.func_index); |
| 1104 if (thrower->error()) return nothing; | 1158 if (thrower->error()) return nothing; |
| 1105 export_metadata->set(kExportCode, *export_code); | 1159 export_metadata->set(kExportCode, *export_code); |
| 1106 export_metadata->set(kExportName, *name); | 1160 export_metadata->set(kExportName, *name); |
| 1107 export_metadata->set( | 1161 export_metadata->set( |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1324 } | 1378 } |
| 1325 | 1379 |
| 1326 // Run the start function if one was specified. | 1380 // Run the start function if one was specified. |
| 1327 MaybeHandle<FixedArray> maybe_startup_fct = | 1381 MaybeHandle<FixedArray> maybe_startup_fct = |
| 1328 compiled_module->GetValue<FixedArray>(kStartupFunction); | 1382 compiled_module->GetValue<FixedArray>(kStartupFunction); |
| 1329 Handle<FixedArray> metadata; | 1383 Handle<FixedArray> metadata; |
| 1330 if (maybe_startup_fct.ToHandle(&metadata)) { | 1384 if (maybe_startup_fct.ToHandle(&metadata)) { |
| 1331 HandleScope scope(isolate); | 1385 HandleScope scope(isolate); |
| 1332 Handle<Code> startup_code = metadata->GetValueChecked<Code>(kExportCode); | 1386 Handle<Code> startup_code = metadata->GetValueChecked<Code>(kExportCode); |
| 1333 int arity = Smi::cast(metadata->get(kExportArity))->value(); | 1387 int arity = Smi::cast(metadata->get(kExportArity))->value(); |
| 1388 Handle<ByteArray> startup_signature = | |
| 1389 metadata->GetValueChecked<ByteArray>(kExportedSignature); | |
| 1334 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 1390 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
| 1335 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, | 1391 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, |
| 1336 js_object); | 1392 startup_signature, js_object); |
| 1337 RecordStats(isolate, *startup_code); | 1393 RecordStats(isolate, *startup_code); |
| 1338 // Call the JS function. | 1394 // Call the JS function. |
| 1339 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1395 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 1340 MaybeHandle<Object> retval = | 1396 MaybeHandle<Object> retval = |
| 1341 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); | 1397 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); |
| 1342 | 1398 |
| 1343 if (retval.is_null()) { | 1399 if (retval.is_null()) { |
| 1344 thrower.Error("WASM.instantiateModule(): start function failed"); | 1400 thrower.Error("WASM.instantiateModule(): start function failed"); |
| 1345 return nothing; | 1401 return nothing; |
| 1346 } | 1402 } |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1550 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 1606 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
| 1551 } | 1607 } |
| 1552 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 1608 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
| 1553 return -1; | 1609 return -1; |
| 1554 } | 1610 } |
| 1555 | 1611 |
| 1556 } // namespace testing | 1612 } // namespace testing |
| 1557 } // namespace wasm | 1613 } // namespace wasm |
| 1558 } // namespace internal | 1614 } // namespace internal |
| 1559 } // namespace v8 | 1615 } // namespace v8 |
| OLD | NEW |