[wasm][debug] Avoid repeated recompilation
If multiple isolates share the same module, and the debugger gets enabled, then we trigger tier down in each isolate separately. To avoid generating too much code, we only recompile functions that are not already in the right tier. This CL is only the first step towards an actual fix. Since we only check already installed code (and ignore compilations that are already scheduled), we might still compile the same functions multiple times. A second CL will make sure that only one recompilation is running at the same time. R=thibaudm@chromium.org Bug: chromium:1084369, v8:10359 Change-Id: Ic4f9afac1add0fe8ad9e5d68f22d3d41ba2e52be Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2213438 Reviewed-by: Thibaud Michaud <thibaudm@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#67957}
This commit is contained in:
parent
a0e7456d38
commit
447d7d6784
@ -2583,26 +2583,44 @@ void CompilationStateImpl::InitializeRecompilation(
|
||||
// Generate necessary compilation units on the fly.
|
||||
CompilationUnitBuilder builder(native_module_);
|
||||
|
||||
// Information about compilation progress is shared between this class and the
|
||||
// NativeModule. Before updating information here, consult the NativeModule to
|
||||
// find all functions that need recompilation.
|
||||
// Since the current tiering state is updated on the NativeModule before
|
||||
// triggering recompilation, it's OK if the information is slightly outdated.
|
||||
// If we compile functions twice, the NativeModule will ignore all redundant
|
||||
// code (or code compiled for the wrong tier).
|
||||
std::vector<int> recompile_function_indexes =
|
||||
native_module_->FindFunctionsToRecompile(new_tiering_state);
|
||||
|
||||
{
|
||||
base::MutexGuard guard(&callbacks_mutex_);
|
||||
|
||||
// Restart recompilation if another recompilation is already happening.
|
||||
outstanding_recompilation_functions_ = 0;
|
||||
// If compilation hasn't started yet then code would be kept as tiered-down
|
||||
// and don't need to recompile.
|
||||
// If compilation progress is not initialized yet, then compilation didn't
|
||||
// start yet, and new code will be kept tiered-down from the start. For
|
||||
// streaming compilation, there is a special path to tier down later, when
|
||||
// the module is complete. In any case, we don't need to recompile here.
|
||||
if (compilation_progress_.size() > 0) {
|
||||
const WasmModule* module = native_module_->module();
|
||||
DCHECK_EQ(module->num_declared_functions, compilation_progress_.size());
|
||||
DCHECK_GE(module->num_declared_functions,
|
||||
recompile_function_indexes.size());
|
||||
outstanding_recompilation_functions_ =
|
||||
static_cast<int>(recompile_function_indexes.size());
|
||||
// Restart recompilation if another recompilation is already happening.
|
||||
for (auto& progress : compilation_progress_) {
|
||||
progress = MissingRecompilationField::update(progress, false);
|
||||
}
|
||||
auto new_tier = new_tiering_state == kTieredDown
|
||||
? ExecutionTier::kLiftoff
|
||||
: ExecutionTier::kTurbofan;
|
||||
int imported = module->num_imported_functions;
|
||||
int declared = module->num_declared_functions;
|
||||
outstanding_recompilation_functions_ = declared;
|
||||
DCHECK_EQ(declared, compilation_progress_.size());
|
||||
for (int slot_index = 0; slot_index < declared; ++slot_index) {
|
||||
compilation_progress_[slot_index] = MissingRecompilationField::update(
|
||||
compilation_progress_[slot_index], true);
|
||||
builder.AddRecompilationUnit(imported + slot_index,
|
||||
new_tiering_state == kTieredDown
|
||||
? ExecutionTier::kLiftoff
|
||||
: ExecutionTier::kTurbofan);
|
||||
for (int function_index : recompile_function_indexes) {
|
||||
DCHECK_LE(imported, function_index);
|
||||
int slot_index = function_index - imported;
|
||||
auto& progress = compilation_progress_[slot_index];
|
||||
progress = MissingRecompilationField::update(progress, true);
|
||||
builder.AddRecompilationUnit(function_index, new_tier);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1869,6 +1869,23 @@ void NativeModule::TriggerRecompilation() {
|
||||
RecompileNativeModule(this, current_state);
|
||||
}
|
||||
|
||||
std::vector<int> NativeModule::FindFunctionsToRecompile(
|
||||
TieringState new_tiering_state) {
|
||||
base::MutexGuard guard(&allocation_mutex_);
|
||||
std::vector<int> function_indexes;
|
||||
int imported = module()->num_imported_functions;
|
||||
int declared = module()->num_declared_functions;
|
||||
for (int slot_index = 0; slot_index < declared; ++slot_index) {
|
||||
int function_index = imported + slot_index;
|
||||
WasmCode* code = code_table_[slot_index];
|
||||
bool code_is_good = new_tiering_state == kTieredDown
|
||||
? code && code->for_debugging()
|
||||
: code && code->tier() == ExecutionTier::kTurbofan;
|
||||
if (!code_is_good) function_indexes.push_back(function_index);
|
||||
}
|
||||
return function_indexes;
|
||||
}
|
||||
|
||||
void NativeModule::FreeCode(Vector<WasmCode* const> codes) {
|
||||
// Free the code space.
|
||||
code_allocator_.FreeCode(codes);
|
||||
|
@ -612,6 +612,12 @@ class V8_EXPORT_PRIVATE NativeModule final {
|
||||
// concurrently, so this method might return before it is complete.
|
||||
void TriggerRecompilation();
|
||||
|
||||
// Find all functions that need to be recompiled for a new tier. Note that
|
||||
// compilation jobs might run concurrently, so this method only considers the
|
||||
// compilation state of this native module at the time of the call.
|
||||
// Returns a vector of function indexes to recompile.
|
||||
std::vector<int> FindFunctionsToRecompile(TieringState);
|
||||
|
||||
// Free a set of functions of this module. Uncommits whole pages if possible.
|
||||
// The given vector must be ordered by the instruction start address, and all
|
||||
// {WasmCode} objects must not be used any more.
|
||||
|
Loading…
Reference in New Issue
Block a user