| 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/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 | 9 |
| 10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 kInternalModuleInstance, | 46 kInternalModuleInstance, |
| 47 kInternalArity, | 47 kInternalArity, |
| 48 kInternalSignature | 48 kInternalSignature |
| 49 }; | 49 }; |
| 50 | 50 |
| 51 // Internal constants for the layout of the module object. | 51 // Internal constants for the layout of the module object. |
| 52 enum WasmInstanceObjectFields { | 52 enum WasmInstanceObjectFields { |
| 53 kWasmCompiledModule = 0, | 53 kWasmCompiledModule = 0, |
| 54 kWasmModuleFunctionTable, | 54 kWasmModuleFunctionTable, |
| 55 kWasmModuleCodeTable, | 55 kWasmModuleCodeTable, |
| 56 kWasmMemObject, |
| 56 kWasmMemArrayBuffer, | 57 kWasmMemArrayBuffer, |
| 57 kWasmGlobalsArrayBuffer, | 58 kWasmGlobalsArrayBuffer, |
| 58 kWasmDebugInfo, | 59 kWasmDebugInfo, |
| 59 kWasmModuleInternalFieldCount | 60 kWasmModuleInternalFieldCount |
| 60 }; | 61 }; |
| 61 | 62 |
| 62 enum WasmImportData { | 63 enum WasmImportData { |
| 63 kImportKind, // Smi. an ExternalKind | 64 kImportKind, // Smi. an ExternalKind |
| 64 kImportGlobalType, // Smi. Type for globals. | 65 kImportGlobalType, // Smi. Type for globals. |
| 65 kImportIndex, // Smi. index for the import. | 66 kImportIndex, // Smi. index for the import. |
| (...skipping 1170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1236 } | 1237 } |
| 1237 | 1238 |
| 1238 //-------------------------------------------------------------------------- | 1239 //-------------------------------------------------------------------------- |
| 1239 // Allocate the instance object. | 1240 // Allocate the instance object. |
| 1240 //-------------------------------------------------------------------------- | 1241 //-------------------------------------------------------------------------- |
| 1241 Handle<Map> map = factory->NewMap( | 1242 Handle<Map> map = factory->NewMap( |
| 1242 JS_OBJECT_TYPE, | 1243 JS_OBJECT_TYPE, |
| 1243 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 1244 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
| 1244 Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED); | 1245 Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED); |
| 1245 instance->SetInternalField(kWasmModuleCodeTable, *code_table); | 1246 instance->SetInternalField(kWasmModuleCodeTable, *code_table); |
| 1247 instance->SetInternalField(kWasmMemObject, *factory->undefined_value()); |
| 1248 |
| 1249 //-------------------------------------------------------------------------- |
| 1250 // Set up the globals for the new instance. |
| 1251 //-------------------------------------------------------------------------- |
| 1252 MaybeHandle<JSArrayBuffer> old_globals; |
| 1253 MaybeHandle<JSArrayBuffer> globals; |
| 1254 uint32_t globals_size = compiled_module_->globals_size(); |
| 1255 if (globals_size > 0) { |
| 1256 Handle<JSArrayBuffer> global_buffer = |
| 1257 NewArrayBuffer(isolate_, globals_size); |
| 1258 globals = global_buffer; |
| 1259 if (globals.is_null()) { |
| 1260 thrower_->Error("Out of memory: wasm globals"); |
| 1261 return nothing; |
| 1262 } |
| 1263 Address old_address = |
| 1264 owner.is_null() ? nullptr : GetGlobalStartAddressFromCodeTemplate( |
| 1265 *factory->undefined_value(), |
| 1266 JSObject::cast(*owner)); |
| 1267 RelocateGlobals(instance, old_address, |
| 1268 static_cast<Address>(global_buffer->backing_store())); |
| 1269 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer); |
| 1270 } |
| 1271 |
| 1272 //-------------------------------------------------------------------------- |
| 1273 // Process the imports for the module. |
| 1274 //-------------------------------------------------------------------------- |
| 1275 int num_imported_functions = ProcessImports(globals, code_table, instance); |
| 1276 if (num_imported_functions < 0) return nothing; |
| 1246 | 1277 |
| 1247 //-------------------------------------------------------------------------- | 1278 //-------------------------------------------------------------------------- |
| 1248 // Set up the memory for the new instance. | 1279 // Set up the memory for the new instance. |
| 1249 //-------------------------------------------------------------------------- | 1280 //-------------------------------------------------------------------------- |
| 1250 MaybeHandle<JSArrayBuffer> old_memory; | 1281 MaybeHandle<JSArrayBuffer> old_memory; |
| 1251 // TODO(titzer): handle imported memory properly. | 1282 // TODO(titzer): handle imported memory properly. |
| 1252 | 1283 |
| 1253 uint32_t min_mem_pages = compiled_module_->min_memory_pages(); | 1284 uint32_t min_mem_pages = compiled_module_->min_memory_pages(); |
| 1254 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 1285 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); |
| 1255 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. | 1286 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1272 Address old_mem_start = | 1303 Address old_mem_start = |
| 1273 compiled_module_->has_heap() | 1304 compiled_module_->has_heap() |
| 1274 ? static_cast<Address>(compiled_module_->heap()->backing_store()) | 1305 ? static_cast<Address>(compiled_module_->heap()->backing_store()) |
| 1275 : nullptr; | 1306 : nullptr; |
| 1276 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size, | 1307 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size, |
| 1277 mem_size); | 1308 mem_size); |
| 1278 compiled_module_->set_heap(memory_); | 1309 compiled_module_->set_heap(memory_); |
| 1279 } | 1310 } |
| 1280 | 1311 |
| 1281 //-------------------------------------------------------------------------- | 1312 //-------------------------------------------------------------------------- |
| 1282 // Set up the globals for the new instance. | |
| 1283 //-------------------------------------------------------------------------- | |
| 1284 MaybeHandle<JSArrayBuffer> old_globals; | |
| 1285 MaybeHandle<JSArrayBuffer> globals; | |
| 1286 uint32_t globals_size = compiled_module_->globals_size(); | |
| 1287 if (globals_size > 0) { | |
| 1288 Handle<JSArrayBuffer> global_buffer = | |
| 1289 NewArrayBuffer(isolate_, globals_size); | |
| 1290 globals = global_buffer; | |
| 1291 if (globals.is_null()) { | |
| 1292 thrower_->Error("Out of memory: wasm globals"); | |
| 1293 return nothing; | |
| 1294 } | |
| 1295 Address old_address = | |
| 1296 owner.is_null() ? nullptr : GetGlobalStartAddressFromCodeTemplate( | |
| 1297 *factory->undefined_value(), | |
| 1298 JSObject::cast(*owner)); | |
| 1299 RelocateGlobals(instance, old_address, | |
| 1300 static_cast<Address>(global_buffer->backing_store())); | |
| 1301 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer); | |
| 1302 } | |
| 1303 | |
| 1304 //-------------------------------------------------------------------------- | |
| 1305 // Process the imports for the module. | |
| 1306 //-------------------------------------------------------------------------- | |
| 1307 int num_imported_functions = ProcessImports(globals, code_table); | |
| 1308 if (num_imported_functions < 0) return nothing; | |
| 1309 | |
| 1310 //-------------------------------------------------------------------------- | |
| 1311 // Process the initialization for the module's globals. | 1313 // Process the initialization for the module's globals. |
| 1312 //-------------------------------------------------------------------------- | 1314 //-------------------------------------------------------------------------- |
| 1313 ProcessInits(globals); | 1315 ProcessInits(globals); |
| 1314 | 1316 |
| 1315 //-------------------------------------------------------------------------- | 1317 //-------------------------------------------------------------------------- |
| 1316 // Set up the runtime support for the new instance. | 1318 // Set up the runtime support for the new instance. |
| 1317 //-------------------------------------------------------------------------- | 1319 //-------------------------------------------------------------------------- |
| 1318 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); | 1320 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); |
| 1319 | 1321 |
| 1320 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; | 1322 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 break; | 1621 break; |
| 1620 default: | 1622 default: |
| 1621 UNREACHABLE(); | 1623 UNREACHABLE(); |
| 1622 } | 1624 } |
| 1623 } | 1625 } |
| 1624 | 1626 |
| 1625 // Process the imports, including functions, tables, globals, and memory, in | 1627 // Process the imports, including functions, tables, globals, and memory, in |
| 1626 // order, loading them from the {ffi_} object. Returns the number of imported | 1628 // order, loading them from the {ffi_} object. Returns the number of imported |
| 1627 // functions. | 1629 // functions. |
| 1628 int ProcessImports(MaybeHandle<JSArrayBuffer> globals, | 1630 int ProcessImports(MaybeHandle<JSArrayBuffer> globals, |
| 1629 Handle<FixedArray> code_table) { | 1631 Handle<FixedArray> code_table, Handle<JSObject> instance) { |
| 1630 int num_imported_functions = 0; | 1632 int num_imported_functions = 0; |
| 1631 if (!compiled_module_->has_imports()) return num_imported_functions; | 1633 if (!compiled_module_->has_imports()) return num_imported_functions; |
| 1632 | 1634 |
| 1633 Handle<FixedArray> imports = compiled_module_->imports(); | 1635 Handle<FixedArray> imports = compiled_module_->imports(); |
| 1634 for (int index = 0; index < imports->length(); ++index) { | 1636 for (int index = 0; index < imports->length(); ++index) { |
| 1635 Handle<FixedArray> data = | 1637 Handle<FixedArray> data = |
| 1636 imports->GetValueChecked<FixedArray>(isolate_, index); | 1638 imports->GetValueChecked<FixedArray>(isolate_, index); |
| 1637 | 1639 |
| 1638 Handle<String> module_name = | 1640 Handle<String> module_name = |
| 1639 data->GetValueChecked<String>(isolate_, kModuleName); | 1641 data->GetValueChecked<String>(isolate_, kModuleName); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1661 function_name); | 1663 function_name); |
| 1662 int func_index = Smi::cast(data->get(kImportIndex))->value(); | 1664 int func_index = Smi::cast(data->get(kImportIndex))->value(); |
| 1663 code_table->set(func_index, *import_wrapper); | 1665 code_table->set(func_index, *import_wrapper); |
| 1664 RecordStats(isolate_, *import_wrapper); | 1666 RecordStats(isolate_, *import_wrapper); |
| 1665 num_imported_functions++; | 1667 num_imported_functions++; |
| 1666 break; | 1668 break; |
| 1667 } | 1669 } |
| 1668 case kExternalTable: | 1670 case kExternalTable: |
| 1669 // TODO(titzer): Table imports must be a WebAssembly.Table. | 1671 // TODO(titzer): Table imports must be a WebAssembly.Table. |
| 1670 break; | 1672 break; |
| 1671 case kExternalMemory: | 1673 case kExternalMemory: { |
| 1672 // TODO(titzer): Memory imports must be a WebAssembly.Memory. | 1674 Handle<Object> object = result.ToHandleChecked(); |
| 1675 if (!WasmJs::IsWasmMemoryObject(isolate_, object)) { |
| 1676 ReportFFIError("memory import must be a WebAssembly.Memory object", |
| 1677 index, module_name, function_name); |
| 1678 return -1; |
| 1679 } |
| 1680 instance->SetInternalField(kWasmMemObject, *object); |
| 1681 memory_ = WasmJs::GetWasmMemoryArrayBuffer(isolate_, object); |
| 1673 break; | 1682 break; |
| 1683 } |
| 1674 case kExternalGlobal: { | 1684 case kExternalGlobal: { |
| 1675 // Global imports are converted to numbers and written into the | 1685 // Global imports are converted to numbers and written into the |
| 1676 // {globals} array buffer. | 1686 // {globals} array buffer. |
| 1677 Handle<Object> object = result.ToHandleChecked(); | 1687 Handle<Object> object = result.ToHandleChecked(); |
| 1678 MaybeHandle<Object> number = Object::ToNumber(object); | 1688 MaybeHandle<Object> number = Object::ToNumber(object); |
| 1679 if (number.is_null()) { | 1689 if (number.is_null()) { |
| 1680 ReportFFIError("global import could not be converted to number", | 1690 ReportFFIError("global import could not be converted to number", |
| 1681 index, module_name, function_name); | 1691 index, module_name, function_name); |
| 1682 return -1; | 1692 return -1; |
| 1683 } | 1693 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1780 export_data->GetValue<ByteArray>(isolate_, kExportedSignature); | 1790 export_data->GetValue<ByteArray>(isolate_, kExportedSignature); |
| 1781 desc.set_value(WrapExportCodeAsJSFunction( | 1791 desc.set_value(WrapExportCodeAsJSFunction( |
| 1782 isolate_, export_code, name, arity, signature, instance)); | 1792 isolate_, export_code, name, arity, signature, instance)); |
| 1783 break; | 1793 break; |
| 1784 } | 1794 } |
| 1785 case kExternalTable: | 1795 case kExternalTable: |
| 1786 // TODO(titzer): create a WebAssembly.Table instance. | 1796 // TODO(titzer): create a WebAssembly.Table instance. |
| 1787 // TODO(titzer): should it have the same identity as an import? | 1797 // TODO(titzer): should it have the same identity as an import? |
| 1788 break; | 1798 break; |
| 1789 case kExternalMemory: { | 1799 case kExternalMemory: { |
| 1790 // TODO(titzer): should memory have the same identity as an | 1800 // Export the memory as a WebAssembly.Memory object. |
| 1791 // import? | 1801 Handle<Object> memory_object( |
| 1792 Handle<JSArrayBuffer> buffer = | 1802 instance->GetInternalField(kWasmMemObject), isolate_); |
| 1793 Handle<JSArrayBuffer>(JSArrayBuffer::cast( | 1803 if (memory_object->IsUndefined(isolate_)) { |
| 1794 instance->GetInternalField(kWasmMemArrayBuffer))); | 1804 // If there was no imported WebAssembly.Memory object, create one. |
| 1795 desc.set_value( | 1805 Handle<JSArrayBuffer> buffer( |
| 1796 WasmJs::CreateWasmMemoryObject(isolate_, buffer, false, 0)); | 1806 JSArrayBuffer::cast( |
| 1807 instance->GetInternalField(kWasmMemArrayBuffer)), |
| 1808 isolate_); |
| 1809 memory_object = |
| 1810 WasmJs::CreateWasmMemoryObject(isolate_, buffer, false, 0); |
| 1811 instance->SetInternalField(kWasmMemObject, *memory_object); |
| 1812 } |
| 1813 |
| 1814 desc.set_value(memory_object); |
| 1797 break; | 1815 break; |
| 1798 } | 1816 } |
| 1799 case kExternalGlobal: { | 1817 case kExternalGlobal: { |
| 1800 // Export the value of the global variable as a number. | 1818 // Export the value of the global variable as a number. |
| 1801 int offset = Smi::cast(export_data->get(kExportIndex))->value(); | 1819 int offset = Smi::cast(export_data->get(kExportIndex))->value(); |
| 1802 byte* ptr = raw_buffer_ptr(globals, offset); | 1820 byte* ptr = raw_buffer_ptr(globals, offset); |
| 1803 double num = 0; | 1821 double num = 0; |
| 1804 switch (Smi::cast(export_data->get(kExportGlobalType))->value()) { | 1822 switch (Smi::cast(export_data->get(kExportGlobalType))->value()) { |
| 1805 case kLocalI32: | 1823 case kLocalI32: |
| 1806 num = *reinterpret_cast<int32_t*>(ptr); | 1824 num = *reinterpret_cast<int32_t*>(ptr); |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2233 WasmCompiledModule* compiled_module = | 2251 WasmCompiledModule* compiled_module = |
| 2234 WasmCompiledModule::cast(instance->GetInternalField(kWasmCompiledModule)); | 2252 WasmCompiledModule::cast(instance->GetInternalField(kWasmCompiledModule)); |
| 2235 CHECK(compiled_module->has_weak_module_object()); | 2253 CHECK(compiled_module->has_weak_module_object()); |
| 2236 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); | 2254 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); |
| 2237 } | 2255 } |
| 2238 | 2256 |
| 2239 } // namespace testing | 2257 } // namespace testing |
| 2240 } // namespace wasm | 2258 } // namespace wasm |
| 2241 } // namespace internal | 2259 } // namespace internal |
| 2242 } // namespace v8 | 2260 } // namespace v8 |
| OLD | NEW |