Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: src/wasm/wasm-module.cc

Issue 2395063002: [wasm] Fix wasm instantiation flakes (Closed)
Patch Set: better fix Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/mjsunit/mjsunit.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/mjsunit.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698