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 1154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 MaybeHandle<JSObject> nothing; | 1165 MaybeHandle<JSObject> nothing; |
1166 HistogramTimerScope wasm_instantiate_module_time_scope( | 1166 HistogramTimerScope wasm_instantiate_module_time_scope( |
1167 isolate_->counters()->wasm_instantiate_module_time()); | 1167 isolate_->counters()->wasm_instantiate_module_time()); |
1168 Factory* factory = isolate_->factory(); | 1168 Factory* factory = isolate_->factory(); |
1169 | 1169 |
1170 //-------------------------------------------------------------------------- | 1170 //-------------------------------------------------------------------------- |
1171 // Reuse the compiled module (if no owner), otherwise clone. | 1171 // Reuse the compiled module (if no owner), otherwise clone. |
1172 //-------------------------------------------------------------------------- | 1172 //-------------------------------------------------------------------------- |
1173 Handle<FixedArray> code_table; | 1173 Handle<FixedArray> code_table; |
1174 Handle<FixedArray> old_code_table; | 1174 Handle<FixedArray> old_code_table; |
1175 Handle<JSObject> owner; | 1175 MaybeHandle<JSObject> owner; |
1176 // If we don't clone, this will be null(). Otherwise, this will | |
1177 // be a weak link to the original. If we lose the original to GC, | |
1178 // this will be a cleared. We'll link the instances chain last. | |
1179 MaybeHandle<WeakCell> link_to_original; | |
1180 | 1176 |
1181 TRACE("Starting new module instantiation\n"); | 1177 TRACE("Starting new module instantiation\n"); |
1182 { | 1178 { |
1183 Handle<WasmCompiledModule> original( | 1179 // Root the owner, if any, before doing any allocations, which |
1184 WasmCompiledModule::cast(module_object_->GetInternalField(0)), | 1180 // may trigger GC. |
1185 isolate_); | 1181 // Both owner and original template need to be in sync. Even |
| 1182 // after we lose the original template handle, the code |
| 1183 // objects we copied from it have data relative to the |
| 1184 // instance - such as globals addresses. |
| 1185 Handle<WasmCompiledModule> original; |
| 1186 { |
| 1187 DisallowHeapAllocation no_gc; |
| 1188 original = handle( |
| 1189 WasmCompiledModule::cast(module_object_->GetInternalField(0))); |
| 1190 if (original->has_weak_owning_instance()) { |
| 1191 owner = |
| 1192 handle(JSObject::cast(original->weak_owning_instance()->value())); |
| 1193 } |
| 1194 } |
| 1195 DCHECK(!original.is_null()); |
1186 // Always make a new copy of the code_table, since the old_code_table | 1196 // Always make a new copy of the code_table, since the old_code_table |
1187 // may still have placeholders for imports. | 1197 // may still have placeholders for imports. |
1188 old_code_table = original->code_table(); | 1198 old_code_table = original->code_table(); |
1189 code_table = factory->CopyFixedArray(old_code_table); | 1199 code_table = factory->CopyFixedArray(old_code_table); |
1190 | 1200 |
1191 if (original->has_weak_owning_instance()) { | 1201 if (original->has_weak_owning_instance()) { |
1192 WeakCell* tmp = original->ptr_to_weak_owning_instance(); | 1202 // Clone, but don't insert yet the clone in the instances chain. |
1193 DCHECK(!tmp->cleared()); | 1203 // We do that last. Since we are holding on to the owner instance, |
1194 // There is already an owner, clone everything. | 1204 // the owner + original state used for cloning and patching |
1195 owner = Handle<JSObject>(JSObject::cast(tmp->value()), isolate_); | 1205 // won't be mutated by possible finalizer runs. |
1196 // Insert the latest clone in front. | 1206 DCHECK(!owner.is_null()); |
1197 TRACE("Cloning from %d\n", original->instance_id()); | 1207 TRACE("Cloning from %d\n", original->instance_id()); |
1198 compiled_module_ = WasmCompiledModule::Clone(isolate_, original); | 1208 compiled_module_ = WasmCompiledModule::Clone(isolate_, original); |
1199 // Replace the strong reference to point to the new instance here. | |
1200 // This allows any of the other instances, including the original, | |
1201 // to be collected. | |
1202 module_object_->SetInternalField(0, *compiled_module_); | |
1203 compiled_module_->set_weak_module_object( | |
1204 original->weak_module_object()); | |
1205 link_to_original = factory->NewWeakCell(original); | |
1206 // Don't link to original here. We remember the original | |
1207 // as a weak link. If that link isn't clear by the time we finish | |
1208 // instantiating this instance, then we link it at that time. | |
1209 compiled_module_->reset_weak_next_instance(); | |
1210 | 1209 |
1211 // Clone the code for WASM functions and exports. | 1210 // Clone the code for WASM functions and exports. |
1212 for (int i = 0; i < code_table->length(); ++i) { | 1211 for (int i = 0; i < code_table->length(); ++i) { |
1213 Handle<Code> orig_code = | 1212 Handle<Code> orig_code = |
1214 code_table->GetValueChecked<Code>(isolate_, i); | 1213 code_table->GetValueChecked<Code>(isolate_, i); |
1215 switch (orig_code->kind()) { | 1214 switch (orig_code->kind()) { |
1216 case Code::WASM_TO_JS_FUNCTION: | 1215 case Code::WASM_TO_JS_FUNCTION: |
1217 // Imports will be overwritten with newly compiled wrappers. | 1216 // Imports will be overwritten with newly compiled wrappers. |
1218 break; | 1217 break; |
1219 case Code::JS_TO_WASM_FUNCTION: | 1218 case Code::JS_TO_WASM_FUNCTION: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 MaybeHandle<JSArrayBuffer> globals; | 1252 MaybeHandle<JSArrayBuffer> globals; |
1254 uint32_t globals_size = compiled_module_->globals_size(); | 1253 uint32_t globals_size = compiled_module_->globals_size(); |
1255 if (globals_size > 0) { | 1254 if (globals_size > 0) { |
1256 Handle<JSArrayBuffer> global_buffer = | 1255 Handle<JSArrayBuffer> global_buffer = |
1257 NewArrayBuffer(isolate_, globals_size); | 1256 NewArrayBuffer(isolate_, globals_size); |
1258 globals = global_buffer; | 1257 globals = global_buffer; |
1259 if (globals.is_null()) { | 1258 if (globals.is_null()) { |
1260 thrower_->Error("Out of memory: wasm globals"); | 1259 thrower_->Error("Out of memory: wasm globals"); |
1261 return nothing; | 1260 return nothing; |
1262 } | 1261 } |
1263 Address old_address = | 1262 Address old_address = owner.is_null() |
1264 owner.is_null() ? nullptr : GetGlobalStartAddressFromCodeTemplate( | 1263 ? nullptr |
1265 *factory->undefined_value(), | 1264 : GetGlobalStartAddressFromCodeTemplate( |
1266 JSObject::cast(*owner)); | 1265 *factory->undefined_value(), |
| 1266 JSObject::cast(*owner.ToHandleChecked())); |
1267 RelocateGlobals(instance, old_address, | 1267 RelocateGlobals(instance, old_address, |
1268 static_cast<Address>(global_buffer->backing_store())); | 1268 static_cast<Address>(global_buffer->backing_store())); |
1269 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer); | 1269 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer); |
1270 } | 1270 } |
1271 | 1271 |
1272 //-------------------------------------------------------------------------- | 1272 //-------------------------------------------------------------------------- |
1273 // Process the imports for the module. | 1273 // Process the imports for the module. |
1274 //-------------------------------------------------------------------------- | 1274 //-------------------------------------------------------------------------- |
1275 int num_imported_functions = ProcessImports(globals, code_table, instance); | 1275 int num_imported_functions = ProcessImports(globals, code_table, instance); |
1276 if (num_imported_functions < 0) return nothing; | 1276 if (num_imported_functions < 0) return nothing; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1339 static_cast<size_t>(code_table->length())); | 1339 static_cast<size_t>(code_table->length())); |
1340 for (int i = 0; i < code_table->length(); ++i) { | 1340 for (int i = 0; i < code_table->length(); ++i) { |
1341 functions[i] = code_table->GetValueChecked<Code>(isolate_, i); | 1341 functions[i] = code_table->GetValueChecked<Code>(isolate_, i); |
1342 } | 1342 } |
1343 | 1343 |
1344 if (compiled_module_->has_indirect_function_tables()) { | 1344 if (compiled_module_->has_indirect_function_tables()) { |
1345 Handle<FixedArray> indirect_tables_template = | 1345 Handle<FixedArray> indirect_tables_template = |
1346 compiled_module_->indirect_function_tables(); | 1346 compiled_module_->indirect_function_tables(); |
1347 Handle<FixedArray> to_replace = | 1347 Handle<FixedArray> to_replace = |
1348 owner.is_null() ? indirect_tables_template | 1348 owner.is_null() ? indirect_tables_template |
1349 : handle(FixedArray::cast(owner->GetInternalField( | 1349 : handle(FixedArray::cast( |
1350 kWasmModuleFunctionTable))); | 1350 owner.ToHandleChecked()->GetInternalField( |
| 1351 kWasmModuleFunctionTable))); |
1351 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( | 1352 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( |
1352 isolate_, code_table, indirect_tables_template, to_replace); | 1353 isolate_, code_table, indirect_tables_template, to_replace); |
1353 for (int i = 0; i < indirect_tables->length(); ++i) { | 1354 for (int i = 0; i < indirect_tables->length(); ++i) { |
1354 Handle<FixedArray> metadata = | 1355 Handle<FixedArray> metadata = |
1355 indirect_tables->GetValueChecked<FixedArray>(isolate_, i); | 1356 indirect_tables->GetValueChecked<FixedArray>(isolate_, i); |
1356 uint32_t size = Smi::cast(metadata->get(kSize))->value(); | 1357 uint32_t size = Smi::cast(metadata->get(kSize))->value(); |
1357 Handle<FixedArray> table = | 1358 Handle<FixedArray> table = |
1358 metadata->GetValueChecked<FixedArray>(isolate_, kTable); | 1359 metadata->GetValueChecked<FixedArray>(isolate_, kTable); |
1359 PopulateFunctionTable(table, size, &functions); | 1360 PopulateFunctionTable(table, size, &functions); |
1360 } | 1361 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 MaybeHandle<Object> retval = | 1397 MaybeHandle<Object> retval = |
1397 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); | 1398 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); |
1398 | 1399 |
1399 if (retval.is_null()) { | 1400 if (retval.is_null()) { |
1400 thrower_->Error("WASM.instantiateModule(): start function failed"); | 1401 thrower_->Error("WASM.instantiateModule(): start function failed"); |
1401 return nothing; | 1402 return nothing; |
1402 } | 1403 } |
1403 } | 1404 } |
1404 | 1405 |
1405 { | 1406 { |
1406 Handle<WeakCell> link_to_owner = factory->NewWeakCell(instance); | |
1407 | |
1408 Handle<Object> global_handle = | 1407 Handle<Object> global_handle = |
1409 isolate_->global_handles()->Create(*instance); | 1408 isolate_->global_handles()->Create(*instance); |
1410 Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module_); | 1409 Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module_); |
| 1410 Handle<WeakCell> link_to_owning_instance = factory->NewWeakCell(instance); |
| 1411 MaybeHandle<WeakCell> link_to_original; |
| 1412 MaybeHandle<WasmCompiledModule> original; |
| 1413 if (!owner.is_null()) { |
| 1414 // prepare the data needed for publishing in a chain, but don't link |
| 1415 // just yet, because |
| 1416 // we want all the publishing to happen free from GC interruptions, and |
| 1417 // so we do it in |
| 1418 // one GC-free scope afterwards. |
| 1419 original = handle(WasmCompiledModule::cast( |
| 1420 owner.ToHandleChecked()->GetInternalField(kWasmCompiledModule))); |
| 1421 link_to_original = factory->NewWeakCell(original.ToHandleChecked()); |
| 1422 } |
| 1423 // Publish the new instance to the instances chain. |
1411 { | 1424 { |
1412 DisallowHeapAllocation no_gc; | 1425 DisallowHeapAllocation no_gc; |
1413 compiled_module_->set_weak_owning_instance(link_to_owner); | 1426 if (!link_to_original.is_null()) { |
1414 Handle<WeakCell> next; | 1427 compiled_module_->set_weak_next_instance( |
1415 if (link_to_original.ToHandle(&next) && !next->cleared()) { | 1428 link_to_original.ToHandleChecked()); |
1416 WasmCompiledModule* original = | 1429 original.ToHandleChecked()->set_weak_prev_instance(link_to_clone); |
1417 WasmCompiledModule::cast(next->value()); | 1430 compiled_module_->set_weak_module_object( |
1418 DCHECK(original->has_weak_owning_instance()); | 1431 original.ToHandleChecked()->weak_module_object()); |
1419 DCHECK(!original->weak_owning_instance()->cleared()); | |
1420 compiled_module_->set_weak_next_instance(next); | |
1421 original->set_weak_prev_instance(link_to_clone); | |
1422 } | 1432 } |
1423 | 1433 module_object_->SetInternalField(0, *compiled_module_); |
1424 compiled_module_->set_weak_owning_instance(link_to_owner); | |
1425 instance->SetInternalField(kWasmCompiledModule, *compiled_module_); | 1434 instance->SetInternalField(kWasmCompiledModule, *compiled_module_); |
| 1435 compiled_module_->set_weak_owning_instance(link_to_owning_instance); |
1426 GlobalHandles::MakeWeak(global_handle.location(), | 1436 GlobalHandles::MakeWeak(global_handle.location(), |
1427 global_handle.location(), &InstanceFinalizer, | 1437 global_handle.location(), &InstanceFinalizer, |
1428 v8::WeakCallbackType::kFinalizer); | 1438 v8::WeakCallbackType::kFinalizer); |
1429 } | 1439 } |
1430 } | 1440 } |
1431 | 1441 |
1432 DCHECK(wasm::IsWasmObject(*instance)); | 1442 DCHECK(wasm::IsWasmObject(*instance)); |
1433 | 1443 |
1434 TRACE("Finishing instance %d\n", compiled_module_->instance_id()); | 1444 TRACE("Finishing instance %d\n", compiled_module_->instance_id()); |
1435 TRACE_CHAIN(WasmCompiledModule::cast(module_object_->GetInternalField(0))); | 1445 TRACE_CHAIN(WasmCompiledModule::cast(module_object_->GetInternalField(0))); |
(...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 WasmCompiledModule* compiled_module = | 2261 WasmCompiledModule* compiled_module = |
2252 WasmCompiledModule::cast(instance->GetInternalField(kWasmCompiledModule)); | 2262 WasmCompiledModule::cast(instance->GetInternalField(kWasmCompiledModule)); |
2253 CHECK(compiled_module->has_weak_module_object()); | 2263 CHECK(compiled_module->has_weak_module_object()); |
2254 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); | 2264 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); |
2255 } | 2265 } |
2256 | 2266 |
2257 } // namespace testing | 2267 } // namespace testing |
2258 } // namespace wasm | 2268 } // namespace wasm |
2259 } // namespace internal | 2269 } // namespace internal |
2260 } // namespace v8 | 2270 } // namespace v8 |
OLD | NEW |