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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 os.write(name.start(), name.length()); | 105 os.write(name.start(), name.length()); |
| 106 } else { | 106 } else { |
| 107 os << "+" << pair.function_->func_index; | 107 os << "+" << pair.function_->func_index; |
| 108 } | 108 } |
| 109 } else { | 109 } else { |
| 110 os << "?"; | 110 os << "?"; |
| 111 } | 111 } |
| 112 return os; | 112 return os; |
| 113 } | 113 } |
| 114 | 114 |
| 115 Handle<JSFunction> CreateExport(Isolate* isolate, Handle<Code> export_code, | |
| 116 Handle<String> name, int arity, | |
| 117 Handle<JSObject> module_instance) { | |
| 118 Handle<SharedFunctionInfo> shared = | |
| 119 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); | |
| 120 shared->set_length(arity); | |
| 121 shared->set_internal_formal_parameter_count(arity); | |
| 122 Handle<JSFunction> function = isolate->factory()->NewFunction( | |
| 123 isolate->wasm_function_map(), name, export_code); | |
| 124 function->set_shared(*shared); | |
| 125 | |
| 126 function->SetInternalField(0, *module_instance); | |
| 127 return function; | |
| 128 } | |
| 129 | |
| 130 void PatchFunctionTable(Handle<Code> code, | |
|
rossberg
2016/07/11 10:49:45
Nit: static or in namespace?
Mircea Trofin
2016/07/11 16:52:57
Done.
| |
| 131 Handle<FixedArray> old_indirect_table, | |
| 132 Handle<FixedArray> new_indirect_table) { | |
| 133 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | |
| 134 it.next()) { | |
| 135 if (it.rinfo()->target_object() == *old_indirect_table) { | |
| 136 it.rinfo()->set_target_object(*new_indirect_table); | |
| 137 } | |
| 138 } | |
| 139 } | |
| 140 | |
| 115 namespace { | 141 namespace { |
| 116 // Internal constants for the layout of the module object. | 142 // Internal constants for the layout of the module object. |
| 117 const int kWasmModuleFunctionTable = 0; | 143 const int kWasmModuleFunctionTable = 0; |
| 118 const int kWasmModuleCodeTable = 1; | 144 const int kWasmModuleCodeTable = 1; |
| 119 const int kWasmMemArrayBuffer = 2; | 145 const int kWasmMemArrayBuffer = 2; |
| 120 const int kWasmGlobalsArrayBuffer = 3; | 146 const int kWasmGlobalsArrayBuffer = 3; |
| 121 // TODO(clemensh): Remove function name array, extract names from module bytes. | 147 // TODO(clemensh): Remove function name array, extract names from module bytes. |
| 122 const int kWasmFunctionNamesArray = 4; | 148 const int kWasmFunctionNamesArray = 4; |
| 123 const int kWasmModuleBytesString = 5; | 149 const int kWasmModuleBytesString = 5; |
| 124 const int kWasmDebugInfo = 6; | 150 const int kWasmDebugInfo = 6; |
| 125 const int kWasmModuleInternalFieldCount = 7; | 151 const int kWasmModuleInternalFieldCount = 7; |
| 126 | 152 |
| 127 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. | 153 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. |
| 128 // For now, each field is expected to have the type commented by its side. | 154 // For now, each field is expected to have the type commented by its side. |
| 129 // The elements typed as "maybe" are optional. The others are mandatory. Since | 155 // The elements typed as "maybe" are optional. The others are mandatory. Since |
| 130 // the compiled module is either obtained from the current v8 instance, or from | 156 // the compiled module is either obtained from the current v8 instance, or from |
| 131 // a snapshot produced by a compatible (==identical) v8 instance, we simply | 157 // a snapshot produced by a compatible (==identical) v8 instance, we simply |
| 132 // fail at instantiation time, in the face of invalid data. | 158 // fail at instantiation time, in the face of invalid data. |
| 133 enum CompiledWasmObjectFields { | 159 enum CompiledWasmObjectFields { |
| 134 kFunctions, // FixedArray of Code | 160 kFunctions, // FixedArray of Code |
| 135 kImportData, // maybe FixedArray of FixedArray respecting the | 161 kImportData, // maybe FixedArray of FixedArray respecting the |
| 136 // WasmImportMetadata structure. | 162 // WasmImportMetadata structure. |
| 137 kExports, // maybe FixedArray of JSFunction | 163 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata |
| 138 kStartupFunction, // maybe JSFunction | 164 // structure |
| 139 kModuleBytes, // maybe String | 165 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure |
| 140 kFunctionNameTable, // maybe ByteArray | 166 kIndirectFunctionTableSize, // Smi. Size of indirect function table. |
| 141 kMinRequiredMemory, // Smi. an uint32_t | 167 kIndirectFunctionTablePrototype, // maybe FixedArray |
| 168 kModuleBytes, // maybe String | |
| 169 kFunctionNameTable, // maybe ByteArray | |
| 170 kMinRequiredMemory, // Smi. an uint32_t | |
| 142 // The following 2 are either together present or absent: | 171 // The following 2 are either together present or absent: |
| 143 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the | 172 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the |
| 144 // WasmSegmentInfo structure | 173 // WasmSegmentInfo structure |
| 145 kDataSegments, // maybe ByteArray. | 174 kDataSegments, // maybe ByteArray. |
| 146 | 175 |
| 147 kGlobalsSize, // Smi. an uint32_t | 176 kGlobalsSize, // Smi. an uint32_t |
| 148 kExportMem, // Smi. bool | 177 kExportMem, // Smi. bool |
| 149 kOrigin, // Smi. ModuleOrigin | 178 kOrigin, // Smi. ModuleOrigin |
| 150 kCompiledWasmObjectTableSize // Sentinel value. | 179 kCompiledWasmObjectTableSize // Sentinel value. |
| 151 }; | 180 }; |
| 152 | 181 |
| 153 enum WasmImportMetadata { | 182 enum WasmImportMetadata { |
| 154 kModuleName, // String | 183 kModuleName, // String |
| 155 kFunctionName, // maybe String | 184 kFunctionName, // maybe String |
| 156 kOutputCount, // Smi. an uint32_t | 185 kOutputCount, // Smi. an uint32_t |
| 157 kSignature, // ByteArray. A copy of the data in FunctionSig | 186 kSignature, // ByteArray. A copy of the data in FunctionSig |
| 158 kWasmImportDataTableSize // Sentinel value. | 187 kWasmImportDataTableSize // Sentinel value. |
| 159 }; | 188 }; |
| 160 | 189 |
| 190 enum WasmExportMetadata { | |
|
titzer
2016/07/11 08:25:35
I didn't see the prior CL where these started popp
Mircea Trofin
2016/07/11 16:52:57
My short term goal is to get an end-to-end indexed
| |
| 191 kExportCode, // Code | |
| 192 kExportName, // String | |
| 193 kExportArity, // Smi, an int | |
| 194 kExportedFunctionIndex, // Smi, an uint32_t | |
| 195 kWasmExportMetadataTableSize // Sentinel value. | |
| 196 }; | |
| 197 | |
| 161 enum WasmSegmentInfo { | 198 enum WasmSegmentInfo { |
| 162 kDestAddr, // Smi. an uint32_t | 199 kDestAddr, // Smi. an uint32_t |
| 163 kSourceSize, // Smi. an uint32_t | 200 kSourceSize, // Smi. an uint32_t |
| 164 kWasmSegmentInfoSize // Sentinel value. | 201 kWasmSegmentInfoSize // Sentinel value. |
| 165 }; | 202 }; |
| 166 | 203 |
| 167 uint32_t GetMinModuleMemSize(const WasmModule* module) { | 204 uint32_t GetMinModuleMemSize(const WasmModule* module) { |
| 168 return WasmModule::kPageSize * module->min_mem_pages; | 205 return WasmModule::kPageSize * module->min_mem_pages; |
| 169 } | 206 } |
| 170 | 207 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 segments->set(i, *js_segment); | 259 segments->set(i, *js_segment); |
| 223 data->copy_in(last_insertion_pos, | 260 data->copy_in(last_insertion_pos, |
| 224 module->module_start + segment.source_offset, | 261 module->module_start + segment.source_offset, |
| 225 segment.source_size); | 262 segment.source_size); |
| 226 last_insertion_pos += segment.source_size; | 263 last_insertion_pos += segment.source_size; |
| 227 } | 264 } |
| 228 compiled_module->set(kDataSegmentsInfo, *segments); | 265 compiled_module->set(kDataSegmentsInfo, *segments); |
| 229 compiled_module->set(kDataSegments, *data); | 266 compiled_module->set(kDataSegments, *data); |
| 230 } | 267 } |
| 231 | 268 |
| 232 Handle<FixedArray> BuildFunctionTable(Isolate* isolate, | 269 MaybeHandle<FixedArray> BuildFunctionTable(Isolate* isolate, |
| 233 const WasmModule* module) { | 270 const WasmModule* module) { |
| 234 // Compute the size of the indirect function table | 271 // Compute the size of the indirect function table |
| 235 uint32_t table_size = module->FunctionTableSize(); | 272 uint32_t table_size = module->FunctionTableSize(); |
| 236 if (table_size == 0) { | 273 if (table_size == 0) { |
| 237 return Handle<FixedArray>::null(); | 274 return MaybeHandle<FixedArray>(); |
| 238 } | 275 } |
| 239 | 276 |
| 277 DCHECK_GE(table_size, module->function_table.size()); | |
| 278 | |
| 240 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size); | 279 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size); |
| 241 for (uint32_t i = 0; | 280 for (uint32_t i = 0; i < module->function_table.size(); ++i) { |
| 242 i < static_cast<uint32_t>(module->function_table.size()); | |
| 243 ++i) { | |
| 244 const WasmFunction* function = | 281 const WasmFunction* function = |
| 245 &module->functions[module->function_table[i]]; | 282 &module->functions[module->function_table[i]]; |
| 246 fixed->set(i, Smi::FromInt(function->sig_index)); | 283 int fixed_array_index = static_cast<int>(i); |
| 284 fixed->set(fixed_array_index, Smi::FromInt(function->sig_index)); | |
| 285 fixed->set(fixed_array_index + table_size, | |
| 286 Smi::FromInt(module->function_table[fixed_array_index])); | |
| 247 } | 287 } |
| 288 | |
| 248 // Set the remaining elements to -1 (instead of "undefined"). These | 289 // Set the remaining elements to -1 (instead of "undefined"). These |
| 249 // elements are accessed directly as SMIs (without a check). On 64-bit | 290 // elements are accessed directly as SMIs (without a check). On 64-bit |
| 250 // platforms, it is possible to have the top bits of "undefined" take | 291 // platforms, it is possible to have the top bits of "undefined" take |
| 251 // small integer values (or zero), which are more likely to be equal to | 292 // small integer values (or zero), which are more likely to be equal to |
| 252 // the signature index we check against. | 293 // the signature index we check against. |
| 253 for (uint32_t i = static_cast<uint32_t>(module->function_table.size()); | 294 for (uint32_t i = static_cast<uint32_t>(module->function_table.size()); |
| 254 i < table_size; | 295 i < table_size; |
| 255 ++i) { | 296 ++i) { |
| 256 fixed->set(i, Smi::FromInt(-1)); | 297 fixed->set(i, Smi::FromInt(-1)); |
| 257 } | 298 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 } | 420 } |
| 380 } | 421 } |
| 381 } | 422 } |
| 382 return modified; | 423 return modified; |
| 383 } | 424 } |
| 384 | 425 |
| 385 void LinkModuleFunctions(Isolate* isolate, | 426 void LinkModuleFunctions(Isolate* isolate, |
| 386 std::vector<Handle<Code>>& functions) { | 427 std::vector<Handle<Code>>& functions) { |
| 387 for (size_t i = 0; i < functions.size(); ++i) { | 428 for (size_t i = 0; i < functions.size(); ++i) { |
| 388 Handle<Code> code = functions[i]; | 429 Handle<Code> code = functions[i]; |
| 389 bool modified = LinkFunction(code, functions, Code::WASM_FUNCTION); | 430 LinkFunction(code, functions, Code::WASM_FUNCTION); |
| 390 if (modified) { | |
| 391 Assembler::FlushICache(isolate, code->instruction_start(), | |
| 392 code->instruction_size()); | |
| 393 } | |
| 394 } | 431 } |
| 395 } | 432 } |
| 396 | 433 |
| 397 void LinkImports(Isolate* isolate, std::vector<Handle<Code>>& functions, | 434 void LinkImports(Isolate* isolate, std::vector<Handle<Code>>& functions, |
| 398 const std::vector<Handle<Code>>& imports) { | 435 const std::vector<Handle<Code>>& imports) { |
| 399 for (uint32_t i = 0; i < functions.size(); ++i) { | 436 for (uint32_t i = 0; i < functions.size(); ++i) { |
| 400 Handle<Code> code = functions[i]; | 437 Handle<Code> code = functions[i]; |
| 401 bool modified = LinkFunction(code, imports, Code::WASM_TO_JS_FUNCTION); | 438 LinkFunction(code, imports, Code::WASM_TO_JS_FUNCTION); |
| 402 if (modified) { | |
| 403 Assembler::FlushICache(isolate, code->instruction_start(), | |
| 404 code->instruction_size()); | |
| 405 } | |
| 406 } | 439 } |
| 407 } | 440 } |
| 408 | 441 |
| 442 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { | |
| 443 for (int i = 0; i < functions->length(); ++i) { | |
| 444 Handle<Code> code = functions->GetValueChecked<Code>(i); | |
| 445 Assembler::FlushICache(isolate, code->instruction_start(), | |
| 446 code->instruction_size()); | |
| 447 } | |
| 448 } | |
| 449 | |
| 409 } // namespace | 450 } // namespace |
| 410 | 451 |
| 411 WasmModule::WasmModule() | 452 WasmModule::WasmModule() |
| 412 : module_start(nullptr), | 453 : module_start(nullptr), |
| 413 module_end(nullptr), | 454 module_end(nullptr), |
| 414 min_mem_pages(0), | 455 min_mem_pages(0), |
| 415 max_mem_pages(0), | 456 max_mem_pages(0), |
| 416 mem_export(false), | 457 mem_export(false), |
| 417 mem_external(false), | 458 mem_external(false), |
| 418 start_function_index(-1), | 459 start_function_index(-1), |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 795 if (code.is_null()) { | 836 if (code.is_null()) { |
| 796 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(), | 837 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(), |
| 797 str.start()); | 838 str.start()); |
| 798 break; | 839 break; |
| 799 } | 840 } |
| 800 // Install the code into the linker table. | 841 // Install the code into the linker table. |
| 801 functions[i] = code; | 842 functions[i] = code; |
| 802 } | 843 } |
| 803 } | 844 } |
| 804 | 845 |
| 805 void PopulateFunctionTable(WasmModuleInstance* instance) { | |
| 806 if (!instance->function_table.is_null()) { | |
| 807 uint32_t table_size = instance->module->FunctionTableSize(); | |
| 808 DCHECK_EQ(table_size * 2, instance->function_table->length()); | |
| 809 uint32_t populated_table_size = | |
| 810 static_cast<uint32_t>(instance->module->function_table.size()); | |
| 811 for (uint32_t i = 0; i < populated_table_size; ++i) { | |
| 812 instance->function_table->set( | |
| 813 i + table_size, | |
| 814 *instance->function_code[instance->module->function_table[i]]); | |
| 815 } | |
| 816 } | |
| 817 } | |
| 818 | |
| 819 void SetDebugSupport(Factory* factory, Handle<FixedArray> compiled_module, | 846 void SetDebugSupport(Factory* factory, Handle<FixedArray> compiled_module, |
| 820 Handle<JSObject> js_object) { | 847 Handle<JSObject> js_object) { |
| 821 MaybeHandle<String> module_bytes_string = | 848 MaybeHandle<String> module_bytes_string = |
| 822 compiled_module->GetValue<String>(kModuleBytes); | 849 compiled_module->GetValue<String>(kModuleBytes); |
| 823 if (!module_bytes_string.is_null()) { | 850 if (!module_bytes_string.is_null()) { |
| 824 js_object->SetInternalField(kWasmModuleBytesString, | 851 js_object->SetInternalField(kWasmModuleBytesString, |
| 825 *module_bytes_string.ToHandleChecked()); | 852 *module_bytes_string.ToHandleChecked()); |
| 826 } | 853 } |
| 827 Handle<FixedArray> functions = Handle<FixedArray>( | 854 Handle<FixedArray> functions = Handle<FixedArray>( |
| 828 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); | 855 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 914 Handle<FixedArray> code_table = Handle<FixedArray>( | 941 Handle<FixedArray> code_table = Handle<FixedArray>( |
| 915 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 942 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
| 916 // TODO(mtrofin): get the code off std::vector and on FixedArray, for | 943 // TODO(mtrofin): get the code off std::vector and on FixedArray, for |
| 917 // consistency. | 944 // consistency. |
| 918 std::vector<Handle<Code>> function_code(code_table->length()); | 945 std::vector<Handle<Code>> function_code(code_table->length()); |
| 919 for (int i = 0; i < code_table->length(); ++i) { | 946 for (int i = 0; i < code_table->length(); ++i) { |
| 920 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | 947 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); |
| 921 function_code[i] = code; | 948 function_code[i] = code; |
| 922 } | 949 } |
| 923 | 950 |
| 924 instance->SetInternalField(kWasmModuleFunctionTable, Smi::FromInt(0)); | |
| 925 LinkImports(isolate, function_code, import_code); | 951 LinkImports(isolate, function_code, import_code); |
| 926 return true; | 952 return true; |
| 927 } | 953 } |
| 928 | 954 |
| 929 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, | 955 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, |
| 930 Handle<JSObject> instance, ErrorThrower* thrower) { | 956 Handle<JSObject> instance, ErrorThrower* thrower) { |
| 931 Factory* factory = isolate->factory(); | 957 Factory* factory = isolate->factory(); |
| 932 bool mem_export = | 958 bool mem_export = |
| 933 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); | 959 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); |
| 934 ModuleOrigin origin = static_cast<ModuleOrigin>( | 960 ModuleOrigin origin = static_cast<ModuleOrigin>( |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 948 exports_object = factory->NewJSObject(object_function, TENURED); | 974 exports_object = factory->NewJSObject(object_function, TENURED); |
| 949 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); | 975 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); |
| 950 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); | 976 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); |
| 951 } | 977 } |
| 952 if (!maybe_exports.is_null()) { | 978 if (!maybe_exports.is_null()) { |
| 953 Handle<FixedArray> exports = maybe_exports.ToHandleChecked(); | 979 Handle<FixedArray> exports = maybe_exports.ToHandleChecked(); |
| 954 | 980 |
| 955 int exports_size = exports->length(); | 981 int exports_size = exports->length(); |
| 956 for (int i = 0; i < exports_size; ++i) { | 982 for (int i = 0; i < exports_size; ++i) { |
| 957 if (thrower->error()) return false; | 983 if (thrower->error()) return false; |
| 958 Handle<JSFunction> function = exports->GetValueChecked<JSFunction>(i); | 984 Handle<FixedArray> export_metadata = |
| 959 RecordStats(isolate, function->code()); | 985 exports->GetValueChecked<FixedArray>(i); |
| 986 Handle<Code> export_code = | |
| 987 export_metadata->GetValueChecked<Code>(kExportCode); | |
| 988 RecordStats(isolate, *export_code); | |
| 960 Handle<String> name = | 989 Handle<String> name = |
| 961 Handle<String>(String::cast(function->shared()->name())); | 990 export_metadata->GetValueChecked<String>(kExportName); |
| 962 function->SetInternalField(0, *instance); | 991 int arity = Smi::cast(export_metadata->get(kExportArity))->value(); |
| 963 | 992 Handle<JSFunction> function = |
| 993 CreateExport(isolate, export_code, name, arity, instance); | |
| 964 desc.set_value(function); | 994 desc.set_value(function); |
| 965 Maybe<bool> status = JSReceiver::DefineOwnProperty( | 995 Maybe<bool> status = JSReceiver::DefineOwnProperty( |
| 966 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); | 996 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); |
| 967 if (!status.IsJust()) { | 997 if (!status.IsJust()) { |
| 968 thrower->Error("export of %.*s failed.", name->length(), | 998 thrower->Error("export of %.*s failed.", name->length(), |
| 969 name->ToCString().get()); | 999 name->ToCString().get()); |
| 970 return false; | 1000 return false; |
| 971 } | 1001 } |
| 972 } | 1002 } |
| 973 } | 1003 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 984 | 1014 |
| 985 } // namespace | 1015 } // namespace |
| 986 | 1016 |
| 987 MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const { | 1017 MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const { |
| 988 Factory* factory = isolate->factory(); | 1018 Factory* factory = isolate->factory(); |
| 989 ErrorThrower thrower(isolate, "WasmModule::CompileFunctions()"); | 1019 ErrorThrower thrower(isolate, "WasmModule::CompileFunctions()"); |
| 990 | 1020 |
| 991 MaybeHandle<FixedArray> nothing; | 1021 MaybeHandle<FixedArray> nothing; |
| 992 | 1022 |
| 993 WasmModuleInstance temp_instance_for_compilation(this); | 1023 WasmModuleInstance temp_instance_for_compilation(this); |
| 994 temp_instance_for_compilation.function_table = | |
| 995 BuildFunctionTable(isolate, this); | |
| 996 temp_instance_for_compilation.context = isolate->native_context(); | 1024 temp_instance_for_compilation.context = isolate->native_context(); |
| 997 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); | 1025 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); |
| 998 temp_instance_for_compilation.mem_start = nullptr; | 1026 temp_instance_for_compilation.mem_start = nullptr; |
| 999 temp_instance_for_compilation.globals_start = nullptr; | 1027 temp_instance_for_compilation.globals_start = nullptr; |
| 1000 | 1028 |
| 1029 MaybeHandle<FixedArray> indirect_table = BuildFunctionTable(isolate, this); | |
| 1030 if (!indirect_table.is_null()) { | |
| 1031 temp_instance_for_compilation.function_table = | |
| 1032 indirect_table.ToHandleChecked(); | |
| 1033 } | |
| 1034 | |
| 1001 HistogramTimerScope wasm_compile_module_time_scope( | 1035 HistogramTimerScope wasm_compile_module_time_scope( |
| 1002 isolate->counters()->wasm_compile_module_time()); | 1036 isolate->counters()->wasm_compile_module_time()); |
| 1003 | 1037 |
| 1004 ModuleEnv module_env; | 1038 ModuleEnv module_env; |
| 1005 module_env.module = this; | 1039 module_env.module = this; |
| 1006 module_env.instance = &temp_instance_for_compilation; | 1040 module_env.instance = &temp_instance_for_compilation; |
| 1007 module_env.origin = origin; | 1041 module_env.origin = origin; |
| 1008 InitializePlaceholders(factory, &module_env.placeholders, functions.size()); | 1042 InitializePlaceholders(factory, &module_env.placeholders, functions.size()); |
| 1009 | 1043 |
| 1010 Handle<FixedArray> compiled_functions = | 1044 Handle<FixedArray> compiled_functions = |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1021 CompileInParallel(isolate, this, | 1055 CompileInParallel(isolate, this, |
| 1022 temp_instance_for_compilation.function_code, &thrower, | 1056 temp_instance_for_compilation.function_code, &thrower, |
| 1023 &module_env); | 1057 &module_env); |
| 1024 } else { | 1058 } else { |
| 1025 CompileSequentially(isolate, this, | 1059 CompileSequentially(isolate, this, |
| 1026 temp_instance_for_compilation.function_code, &thrower, | 1060 temp_instance_for_compilation.function_code, &thrower, |
| 1027 &module_env); | 1061 &module_env); |
| 1028 } | 1062 } |
| 1029 if (thrower.error()) return nothing; | 1063 if (thrower.error()) return nothing; |
| 1030 | 1064 |
| 1031 LinkModuleFunctions(isolate, temp_instance_for_compilation.function_code); | |
| 1032 | |
| 1033 // At this point, compilation has completed. Update the code table. | 1065 // At this point, compilation has completed. Update the code table. |
| 1034 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 1066 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
| 1035 i < temp_instance_for_compilation.function_code.size(); ++i) { | 1067 i < temp_instance_for_compilation.function_code.size(); ++i) { |
| 1036 Code* code = *temp_instance_for_compilation.function_code[i]; | 1068 Code* code = *temp_instance_for_compilation.function_code[i]; |
| 1037 compiled_functions->set(static_cast<int>(i), code); | 1069 compiled_functions->set(static_cast<int>(i), code); |
| 1038 } | 1070 } |
| 1039 | 1071 |
| 1040 PopulateFunctionTable(&temp_instance_for_compilation); | |
| 1041 | |
| 1042 // Create the compiled module object, and populate with compiled functions | 1072 // Create the compiled module object, and populate with compiled functions |
| 1043 // and information needed at instantiation time. This object needs to be | 1073 // and information needed at instantiation time. This object needs to be |
| 1044 // serializable. Instantiation may occur off a deserialized version of this | 1074 // serializable. Instantiation may occur off a deserialized version of this |
| 1045 // object. | 1075 // object. |
| 1046 Handle<FixedArray> ret = | 1076 Handle<FixedArray> ret = |
| 1047 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); | 1077 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); |
| 1048 ret->set(kFunctions, *compiled_functions); | 1078 ret->set(kFunctions, *compiled_functions); |
| 1049 | 1079 ret->set(kIndirectFunctionTableSize, |
| 1080 Smi::FromInt(static_cast<int>(function_table.size()))); | |
| 1081 if (!indirect_table.is_null()) { | |
| 1082 ret->set(kIndirectFunctionTablePrototype, | |
| 1083 *indirect_table.ToHandleChecked()); | |
| 1084 } | |
| 1050 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); | 1085 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); |
| 1051 ret->set(kImportData, *import_data); | 1086 ret->set(kImportData, *import_data); |
| 1052 | 1087 |
| 1053 // Compile export functions. | 1088 // Compile export functions. |
| 1054 int export_size = static_cast<int>(export_table.size()); | 1089 int export_size = static_cast<int>(export_table.size()); |
| 1055 Handle<JSFunction> startup_fct; | 1090 Handle<Code> startup_fct; |
| 1056 if (export_size > 0) { | 1091 if (export_size > 0) { |
| 1057 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); | 1092 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); |
| 1058 for (int i = 0; i < export_size; ++i) { | 1093 for (int i = 0; i < export_size; ++i) { |
| 1094 Handle<FixedArray> export_metadata = | |
| 1095 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); | |
| 1059 const WasmExport& exp = export_table[i]; | 1096 const WasmExport& exp = export_table[i]; |
| 1060 WasmName str = GetName(exp.name_offset, exp.name_length); | 1097 WasmName str = GetName(exp.name_offset, exp.name_length); |
| 1061 Handle<String> name = factory->InternalizeUtf8String(str); | 1098 Handle<String> name = factory->InternalizeUtf8String(str); |
| 1062 Handle<Code> code = | 1099 Handle<Code> code = |
| 1063 temp_instance_for_compilation.function_code[exp.func_index]; | 1100 temp_instance_for_compilation.function_code[exp.func_index]; |
| 1064 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( | 1101 Handle<Code> export_code = compiler::CompileJSToWasmWrapper( |
| 1065 isolate, &module_env, name, code, exp.func_index); | 1102 isolate, &module_env, code, exp.func_index); |
| 1066 if (thrower.error()) return nothing; | 1103 if (thrower.error()) return nothing; |
| 1067 exports->set(i, *function); | 1104 export_metadata->set(kExportCode, *export_code); |
|
rossberg
2016/07/11 10:49:45
Instead of spreading the details here and elsewher
Mircea Trofin
2016/07/11 16:52:57
It's not really a WasmExport anymore, because it h
| |
| 1105 export_metadata->set(kExportName, *name); | |
| 1106 export_metadata->set( | |
| 1107 kExportArity, Smi::FromInt(static_cast<int>( | |
| 1108 functions[exp.func_index].sig->parameter_count()))); | |
| 1109 export_metadata->set(kExportedFunctionIndex, | |
| 1110 Smi::FromInt(static_cast<int>(exp.func_index))); | |
| 1111 exports->set(i, *export_metadata); | |
| 1068 if (exp.func_index == start_function_index) { | 1112 if (exp.func_index == start_function_index) { |
| 1069 startup_fct = function; | 1113 startup_fct = export_code; |
| 1070 } | 1114 } |
| 1071 } | 1115 } |
| 1072 ret->set(kExports, *exports); | 1116 ret->set(kExports, *exports); |
| 1073 } | 1117 } |
| 1074 | 1118 |
| 1075 // Compile startup function, if we haven't already. | 1119 // Compile startup function, if we haven't already. |
| 1076 if (start_function_index >= 0) { | 1120 if (start_function_index >= 0) { |
| 1121 uint32_t index = static_cast<uint32_t>(start_function_index); | |
| 1077 HandleScope scope(isolate); | 1122 HandleScope scope(isolate); |
| 1078 if (startup_fct.is_null()) { | 1123 if (startup_fct.is_null()) { |
| 1079 uint32_t index = static_cast<uint32_t>(start_function_index); | |
| 1080 Handle<String> name = factory->NewStringFromStaticChars("start"); | |
| 1081 Handle<Code> code = temp_instance_for_compilation.function_code[index]; | 1124 Handle<Code> code = temp_instance_for_compilation.function_code[index]; |
| 1082 startup_fct = compiler::CompileJSToWasmWrapper(isolate, &module_env, name, | 1125 DCHECK_EQ(0, functions[index].sig->parameter_count()); |
| 1083 code, index); | 1126 startup_fct = |
| 1127 compiler::CompileJSToWasmWrapper(isolate, &module_env, code, index); | |
| 1084 } | 1128 } |
| 1085 ret->set(kStartupFunction, *startup_fct); | 1129 Handle<FixedArray> metadata = |
| 1130 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); | |
| 1131 metadata->set(kExportCode, *startup_fct); | |
| 1132 metadata->set(kExportArity, Smi::FromInt(0)); | |
| 1133 metadata->set(kExportedFunctionIndex, Smi::FromInt(start_function_index)); | |
| 1134 ret->set(kStartupFunction, *metadata); | |
| 1086 } | 1135 } |
| 1087 | 1136 |
| 1088 // TODO(wasm): saving the module bytes for debugging is wasteful. We should | 1137 // TODO(wasm): saving the module bytes for debugging is wasteful. We should |
| 1089 // consider downloading this on-demand. | 1138 // consider downloading this on-demand. |
| 1090 { | 1139 { |
| 1091 size_t module_bytes_len = module_end - module_start; | 1140 size_t module_bytes_len = module_end - module_start; |
| 1092 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); | 1141 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); |
| 1093 Vector<const uint8_t> module_bytes_vec(module_start, | 1142 Vector<const uint8_t> module_bytes_vec(module_start, |
| 1094 static_cast<int>(module_bytes_len)); | 1143 static_cast<int>(module_bytes_len)); |
| 1095 Handle<String> module_bytes_string = | 1144 Handle<String> module_bytes_string = |
| 1096 factory->NewStringFromOneByte(module_bytes_vec, TENURED) | 1145 factory->NewStringFromOneByte(module_bytes_vec, TENURED) |
| 1097 .ToHandleChecked(); | 1146 .ToHandleChecked(); |
| 1098 ret->set(kModuleBytes, *module_bytes_string); | 1147 ret->set(kModuleBytes, *module_bytes_string); |
| 1099 } | 1148 } |
| 1100 | 1149 |
| 1101 Handle<ByteArray> function_name_table = | 1150 Handle<ByteArray> function_name_table = |
| 1102 BuildFunctionNamesTable(isolate, module_env.module); | 1151 BuildFunctionNamesTable(isolate, module_env.module); |
| 1103 ret->set(kFunctionNameTable, *function_name_table); | 1152 ret->set(kFunctionNameTable, *function_name_table); |
| 1104 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); | 1153 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); |
| 1105 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); | 1154 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); |
| 1106 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); | 1155 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); |
| 1107 ret->set(kExportMem, Smi::FromInt(mem_export)); | 1156 ret->set(kExportMem, Smi::FromInt(mem_export)); |
| 1108 ret->set(kOrigin, Smi::FromInt(origin)); | 1157 ret->set(kOrigin, Smi::FromInt(origin)); |
| 1109 return ret; | 1158 return ret; |
| 1110 } | 1159 } |
| 1111 | 1160 |
| 1161 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, | |
| 1162 Handle<Code> new_target) { | |
| 1163 AllowDeferredHandleDereference embedding_raw_address; | |
| 1164 bool seen = false; | |
| 1165 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); | |
| 1166 it.next()) { | |
| 1167 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | |
| 1168 if (target->kind() == Code::WASM_FUNCTION) { | |
| 1169 DCHECK(!seen); | |
| 1170 seen = true; | |
| 1171 it.rinfo()->set_target_address(new_target->instruction_start(), | |
| 1172 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
| 1173 } | |
| 1174 } | |
| 1175 CHECK(seen); | |
| 1176 Assembler::FlushICache(isolate, wrapper->instruction_start(), | |
| 1177 wrapper->instruction_size()); | |
| 1178 } | |
| 1179 | |
| 1180 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, | |
| 1181 Handle<FixedArray> original) { | |
| 1182 Factory* factory = isolate->factory(); | |
| 1183 Handle<FixedArray> clone = factory->CopyFixedArray(original); | |
| 1184 | |
| 1185 Handle<FixedArray> orig_wasm_functions = | |
| 1186 original->GetValueChecked<FixedArray>(kFunctions); | |
| 1187 Handle<FixedArray> clone_wasm_functions = | |
| 1188 factory->CopyFixedArray(orig_wasm_functions); | |
| 1189 clone->set(kFunctions, *clone_wasm_functions); | |
| 1190 | |
| 1191 MaybeHandle<FixedArray> maybe_indirect_table = | |
| 1192 original->GetValue<FixedArray>(kIndirectFunctionTablePrototype); | |
| 1193 | |
| 1194 Handle<FixedArray> indirect_table; | |
| 1195 Handle<FixedArray> old_table; | |
| 1196 if (!maybe_indirect_table.is_null()) { | |
|
rossberg
2016/07/11 10:49:45
Nit: use ToHandle instead of separate is_null and
Mircea Trofin
2016/07/11 16:52:57
Done.
| |
| 1197 old_table = maybe_indirect_table.ToHandleChecked(); | |
| 1198 indirect_table = factory->CopyFixedArray(old_table); | |
| 1199 clone->set(kIndirectFunctionTablePrototype, *indirect_table); | |
| 1200 } | |
| 1201 | |
| 1202 for (int i = 0; i < orig_wasm_functions->length(); ++i) { | |
| 1203 Handle<Code> orig_code = orig_wasm_functions->GetValueChecked<Code>(i); | |
| 1204 Handle<Code> cloned_code = factory->CopyCode(orig_code); | |
| 1205 clone_wasm_functions->set(i, *cloned_code); | |
| 1206 if (!maybe_indirect_table.is_null()) { | |
| 1207 PatchFunctionTable(cloned_code, old_table, indirect_table); | |
| 1208 } | |
| 1209 } | |
| 1210 | |
| 1211 MaybeHandle<FixedArray> maybe_orig_exports = | |
| 1212 original->GetValue<FixedArray>(kExports); | |
| 1213 if (!maybe_orig_exports.is_null()) { | |
| 1214 Handle<FixedArray> orig_exports = maybe_orig_exports.ToHandleChecked(); | |
| 1215 Handle<FixedArray> cloned_exports = factory->CopyFixedArray(orig_exports); | |
| 1216 clone->set(kExports, *cloned_exports); | |
| 1217 for (int i = 0; i < orig_exports->length(); ++i) { | |
| 1218 Handle<FixedArray> export_metadata = | |
| 1219 orig_exports->GetValueChecked<FixedArray>(i); | |
| 1220 Handle<FixedArray> clone_metadata = | |
| 1221 factory->CopyFixedArray(export_metadata); | |
| 1222 cloned_exports->set(i, *clone_metadata); | |
| 1223 Handle<Code> orig_code = | |
| 1224 export_metadata->GetValueChecked<Code>(kExportCode); | |
| 1225 Handle<Code> cloned_code = factory->CopyCode(orig_code); | |
| 1226 clone_metadata->set(kExportCode, *cloned_code); | |
| 1227 // TODO(wasm): This is actually a uint32_t, but since FixedArray indexes | |
| 1228 // in int, | |
| 1229 // we are taking the risk of invalid values. We should fix this in | |
|
rossberg
2016/07/11 10:49:45
FixedArray cannot actually support the full uint32
Mircea Trofin
2016/07/11 16:52:57
We should talk about this separately. I trimmed th
| |
| 1230 // FixedArray, by | |
| 1231 // moving it to size_t indexing, like std::vector does. | |
| 1232 int exported_fct_index = | |
| 1233 Smi::cast(export_metadata->get(kExportedFunctionIndex))->value(); | |
| 1234 CHECK_GE(exported_fct_index, 0); | |
| 1235 CHECK_LT(exported_fct_index, clone_wasm_functions->length()); | |
| 1236 Handle<Code> new_target = | |
| 1237 clone_wasm_functions->GetValueChecked<Code>(exported_fct_index); | |
| 1238 PatchJSWrapper(isolate, cloned_code, new_target); | |
| 1239 } | |
| 1240 } | |
| 1241 | |
| 1242 MaybeHandle<FixedArray> maybe_startup = | |
| 1243 original->GetValue<FixedArray>(kStartupFunction); | |
| 1244 if (!maybe_startup.is_null()) { | |
| 1245 Handle<FixedArray> startup_metadata = | |
| 1246 factory->CopyFixedArray(maybe_startup.ToHandleChecked()); | |
| 1247 Handle<Code> startup_fct_clone = | |
| 1248 factory->CopyCode(startup_metadata->GetValueChecked<Code>(kExportCode)); | |
| 1249 startup_metadata->set(kExportCode, *startup_fct_clone); | |
| 1250 clone->set(kStartupFunction, *startup_metadata); | |
| 1251 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. | |
| 1252 int startup_fct_index = | |
| 1253 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); | |
| 1254 CHECK_GE(startup_fct_index, 0); | |
| 1255 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); | |
| 1256 Handle<Code> new_target = | |
| 1257 clone_wasm_functions->GetValueChecked<Code>(startup_fct_index); | |
| 1258 PatchJSWrapper(isolate, startup_fct_clone, new_target); | |
| 1259 } | |
| 1260 return clone; | |
| 1261 } | |
| 1262 | |
| 1112 // Instantiates a wasm module as a JSObject. | 1263 // Instantiates a wasm module as a JSObject. |
| 1113 // * allocates a backing store of {mem_size} bytes. | 1264 // * allocates a backing store of {mem_size} bytes. |
| 1114 // * installs a named property "memory" for that buffer if exported | 1265 // * installs a named property "memory" for that buffer if exported |
| 1115 // * installs named properties on the object for exported functions | 1266 // * installs named properties on the object for exported functions |
| 1116 // * compiles wasm code to machine code | 1267 // * compiles wasm code to machine code |
| 1117 MaybeHandle<JSObject> WasmModule::Instantiate( | 1268 MaybeHandle<JSObject> WasmModule::Instantiate( |
| 1118 Isolate* isolate, Handle<FixedArray> compiled_module, | 1269 Isolate* isolate, Handle<FixedArray> compiled_module, |
| 1119 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { | 1270 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { |
| 1120 HistogramTimerScope wasm_instantiate_module_time_scope( | 1271 HistogramTimerScope wasm_instantiate_module_time_scope( |
| 1121 isolate->counters()->wasm_instantiate_module_time()); | 1272 isolate->counters()->wasm_instantiate_module_time()); |
| 1122 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 1273 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
| 1123 Factory* factory = isolate->factory(); | 1274 Factory* factory = isolate->factory(); |
| 1124 | 1275 |
| 1276 compiled_module = CloneModuleForInstance(isolate, compiled_module); | |
| 1277 | |
| 1125 // These fields are compulsory. | 1278 // These fields are compulsory. |
| 1126 Handle<FixedArray> code_table = | 1279 Handle<FixedArray> code_table = |
| 1127 compiled_module->GetValueChecked<FixedArray>(kFunctions); | 1280 compiled_module->GetValueChecked<FixedArray>(kFunctions); |
| 1128 | 1281 |
| 1282 { | |
| 1283 std::vector<Handle<Code>> functions( | |
| 1284 static_cast<size_t>(code_table->length())); | |
| 1285 for (int i = 0; i < code_table->length(); ++i) { | |
| 1286 functions[static_cast<size_t>(i)] = code_table->GetValueChecked<Code>(i); | |
| 1287 } | |
| 1288 LinkModuleFunctions(isolate, functions); | |
| 1289 } | |
| 1290 | |
| 1129 RecordStats(isolate, code_table); | 1291 RecordStats(isolate, code_table); |
| 1130 | 1292 |
| 1131 MaybeHandle<JSObject> nothing; | 1293 MaybeHandle<JSObject> nothing; |
| 1132 | 1294 |
| 1133 Handle<Map> map = factory->NewMap( | 1295 Handle<Map> map = factory->NewMap( |
| 1134 JS_OBJECT_TYPE, | 1296 JS_OBJECT_TYPE, |
| 1135 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 1297 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
| 1136 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); | 1298 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); |
| 1137 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 1299 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
| 1138 | 1300 |
| 1139 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, | 1301 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, |
| 1140 &thrower) && | 1302 &thrower) && |
| 1141 SetupGlobals(isolate, compiled_module, js_object, &thrower) && | 1303 SetupGlobals(isolate, compiled_module, js_object, &thrower) && |
| 1142 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && | 1304 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && |
| 1143 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { | 1305 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { |
| 1144 return nothing; | 1306 return nothing; |
| 1145 } | 1307 } |
| 1146 | 1308 |
| 1147 SetDebugSupport(factory, compiled_module, js_object); | 1309 SetDebugSupport(factory, compiled_module, js_object); |
| 1148 | 1310 |
| 1311 FlushAssemblyCache(isolate, code_table); | |
| 1312 | |
| 1313 MaybeHandle<FixedArray> maybe_indirect_table = | |
| 1314 compiled_module->GetValue<FixedArray>(kIndirectFunctionTablePrototype); | |
| 1315 if (!maybe_indirect_table.is_null()) { | |
| 1316 int table_size = | |
| 1317 Smi::cast(compiled_module->get(kIndirectFunctionTableSize))->value(); | |
| 1318 Handle<FixedArray> indirect_table = maybe_indirect_table.ToHandleChecked(); | |
| 1319 int half_point = indirect_table->length() / 2; | |
| 1320 for (int i = half_point; i < half_point + table_size; ++i) { | |
| 1321 int index = Smi::cast(indirect_table->get(i))->value(); | |
| 1322 DCHECK_GE(index, 0); | |
| 1323 DCHECK_LT(index, code_table->length()); | |
| 1324 indirect_table->set(i, code_table->get(index)); | |
| 1325 } | |
| 1326 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_table); | |
| 1327 } | |
| 1328 | |
| 1149 // Run the start function if one was specified. | 1329 // Run the start function if one was specified. |
| 1150 MaybeHandle<JSFunction> maybe_startup_fct = | 1330 MaybeHandle<FixedArray> maybe_startup_fct = |
| 1151 compiled_module->GetValue<JSFunction>(kStartupFunction); | 1331 compiled_module->GetValue<FixedArray>(kStartupFunction); |
| 1152 if (!maybe_startup_fct.is_null()) { | 1332 if (!maybe_startup_fct.is_null()) { |
| 1153 HandleScope scope(isolate); | 1333 HandleScope scope(isolate); |
| 1154 Handle<JSFunction> startup_fct = maybe_startup_fct.ToHandleChecked(); | 1334 Handle<FixedArray> metadata = maybe_startup_fct.ToHandleChecked(); |
| 1155 RecordStats(isolate, startup_fct->code()); | 1335 Handle<Code> startup_code = metadata->GetValueChecked<Code>(kExportCode); |
| 1156 startup_fct->SetInternalField(0, *js_object); | 1336 int arity = Smi::cast(metadata->get(kExportArity))->value(); |
| 1337 Handle<JSFunction> startup_fct = | |
| 1338 CreateExport(isolate, startup_code, | |
| 1339 factory->InternalizeUtf8String("start"), arity, js_object); | |
| 1340 RecordStats(isolate, *startup_code); | |
| 1157 // Call the JS function. | 1341 // Call the JS function. |
| 1158 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1342 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 1159 MaybeHandle<Object> retval = | 1343 MaybeHandle<Object> retval = |
| 1160 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); | 1344 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); |
| 1161 | 1345 |
| 1162 if (retval.is_null()) { | 1346 if (retval.is_null()) { |
| 1163 thrower.Error("WASM.instantiateModule(): start function failed"); | 1347 thrower.Error("WASM.instantiateModule(): start function failed"); |
| 1164 return nothing; | 1348 return nothing; |
| 1165 } | 1349 } |
| 1166 } | 1350 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1327 } | 1511 } |
| 1328 if (module->export_table.size() == 0) { | 1512 if (module->export_table.size() == 0) { |
| 1329 thrower.Error("Not supported: module has no exports."); | 1513 thrower.Error("Not supported: module has no exports."); |
| 1330 } | 1514 } |
| 1331 | 1515 |
| 1332 if (thrower.error()) return -1; | 1516 if (thrower.error()) return -1; |
| 1333 MaybeHandle<FixedArray> compiled_module = module->CompileFunctions(isolate); | 1517 MaybeHandle<FixedArray> compiled_module = module->CompileFunctions(isolate); |
| 1334 | 1518 |
| 1335 if (compiled_module.is_null()) return -1; | 1519 if (compiled_module.is_null()) return -1; |
| 1336 Handle<JSObject> instance = | 1520 Handle<JSObject> instance = |
| 1337 module | 1521 WasmModule::Instantiate(isolate, compiled_module.ToHandleChecked(), |
| 1338 ->Instantiate(isolate, compiled_module.ToHandleChecked(), | 1522 Handle<JSReceiver>::null(), |
| 1339 Handle<JSReceiver>::null(), | 1523 Handle<JSArrayBuffer>::null()) |
| 1340 Handle<JSArrayBuffer>::null()) | |
| 1341 .ToHandleChecked(); | 1524 .ToHandleChecked(); |
| 1342 | 1525 |
| 1343 Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports"); | 1526 Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports"); |
| 1344 Handle<JSObject> exports_object = Handle<JSObject>::cast( | 1527 Handle<JSObject> exports_object = Handle<JSObject>::cast( |
| 1345 JSObject::GetProperty(instance, exports).ToHandleChecked()); | 1528 JSObject::GetProperty(instance, exports).ToHandleChecked()); |
| 1346 Handle<Name> main_name = isolate->factory()->NewStringFromStaticChars("main"); | 1529 Handle<Name> main_name = isolate->factory()->NewStringFromStaticChars("main"); |
| 1347 PropertyDescriptor desc; | 1530 PropertyDescriptor desc; |
| 1348 Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor( | 1531 Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor( |
| 1349 isolate, exports_object, main_name, &desc); | 1532 isolate, exports_object, main_name, &desc); |
| 1350 if (!property_found.FromMaybe(false)) return -1; | 1533 if (!property_found.FromMaybe(false)) return -1; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1369 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 1552 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
| 1370 } | 1553 } |
| 1371 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 1554 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
| 1372 return -1; | 1555 return -1; |
| 1373 } | 1556 } |
| 1374 | 1557 |
| 1375 } // namespace testing | 1558 } // namespace testing |
| 1376 } // namespace wasm | 1559 } // namespace wasm |
| 1377 } // namespace internal | 1560 } // namespace internal |
| 1378 } // namespace v8 | 1561 } // namespace v8 |
| OLD | NEW |