[wasm] Store whether code was generated for debugging

This adds a flag to {WasmCode} objects to store whether this code was
generated for debugging. This flag can be set for Liftoff code (in which
case the code will e.g. have an extended prologue for debugging), but it
can also be set for TurboFan, in case Liftoff bailed out when producing
the debugging code.

Having this flag allows us to remove the hack to pass the compilation
results to {OnFinishedUnits} just to check whether we actually wanted to
compile Liftoff functions.

Drive-by: Replace the {ReachedRecompilationTierField} by a
{MissingRecompilationField}, because all we need to know is if we are
still waiting for that function to get recompiled.

R=ahaas@chromium.org

Bug: v8:10330,v8:10410
Change-Id: Ia023df8955a60d9f5595a6cb2737e14d83baf716
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2142259
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67119}
This commit is contained in:
Clemens Backes 2020-04-14 12:47:00 +02:00 committed by Commit Bot
parent 8c6f906725
commit 4721585bee
12 changed files with 74 additions and 64 deletions

View File

@ -6626,7 +6626,7 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine,
result.tagged_parameter_slots,
result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), wasm::WasmCode::kWasmToCapiWrapper,
wasm::ExecutionTier::kNone);
wasm::ExecutionTier::kNone, wasm::kNoDebugging);
return native_module->PublishCode(std::move(wasm_code));
}

View File

@ -3323,6 +3323,7 @@ WasmCompilationResult ExecuteLiftoffCompilation(
result.tagged_parameter_slots = call_descriptor->GetTaggedParameterSlots();
result.func_index = func_index;
result.result_tier = ExecutionTier::kLiftoff;
result.for_debugging = for_debugging;
if (debug_sidetable) {
*debug_sidetable = debug_sidetable_builder->GenerateDebugSideTable();
}

View File

@ -202,6 +202,7 @@ WasmCompilationResult WasmCompilationUnit::ExecuteFunctionCompilation(
case ExecutionTier::kTurbofan:
result = compiler::ExecuteTurbofanWasmCompilation(
wasm_engine, env, func_body, func_index_, counters, detected);
result.for_debugging = for_debugging_;
break;
case ExecutionTier::kInterpreter:

View File

@ -72,6 +72,7 @@ struct WasmCompilationResult {
ExecutionTier requested_tier;
ExecutionTier result_tier;
Kind kind = kFunction;
ForDebugging for_debugging = kNoDebugging;
};
class V8_EXPORT_PRIVATE WasmCompilationUnit final {

View File

@ -409,7 +409,7 @@ class CompilationStateImpl {
void FinalizeJSToWasmWrappers(Isolate* isolate, const WasmModule* module,
Handle<FixedArray>* export_wrappers_out);
void OnFinishedUnits(Vector<WasmCode*>, Vector<WasmCompilationResult>);
void OnFinishedUnits(Vector<WasmCode*>);
void OnFinishedJSToWasmWrapperUnits(int num);
void OnBackgroundTaskStopped(int task_id, const WasmFeatures& detected);
@ -564,7 +564,7 @@ class CompilationStateImpl {
using RequiredBaselineTierField = base::BitField8<ExecutionTier, 0, 2>;
using RequiredTopTierField = base::BitField8<ExecutionTier, 2, 2>;
using ReachedTierField = base::BitField8<ExecutionTier, 4, 2>;
using ReachedRecompilationTierField = base::BitField8<ExecutionTier, 6, 2>;
using MissingRecompilationField = base::BitField8<bool, 6, 1>;
};
CompilationStateImpl* Impl(CompilationState* compilation_state) {
@ -1061,6 +1061,7 @@ bool ExecuteCompilationUnits(
std::vector<std::unique_ptr<WasmCode>> unpublished_code =
compile_scope->native_module()->AddCompiledCode(
VectorOf(results_to_publish));
results_to_publish.clear();
// TODO(clemensb): Avoid blocking to publish code
// (https://crbug.com/v8/10330).
std::vector<WasmCode*> code_vector =
@ -1070,7 +1071,6 @@ bool ExecuteCompilationUnits(
// For import wrapper compilation units, add result to the cache.
const NativeModule* native_module = compile_scope->native_module();
int num_imported_functions = native_module->num_imported_functions();
DCHECK_EQ(code_vector.size(), results_to_publish.size());
WasmImportWrapperCache* cache = native_module->import_wrapper_cache();
for (WasmCode* code : code_vector) {
int func_index = code->index();
@ -1092,9 +1092,7 @@ bool ExecuteCompilationUnits(
native_module->engine()->LogCode(VectorOf(code_vector));
compile_scope->compilation_state()->OnFinishedUnits(
VectorOf(code_vector), VectorOf(results_to_publish));
results_to_publish.clear();
compile_scope->compilation_state()->OnFinishedUnits(VectorOf(code_vector));
};
bool compilation_failed = false;
@ -2548,14 +2546,12 @@ void CompilationStateImpl::InitializeRecompilation(
ReachedTierField::decode(compilation_progress_[slot_index]);
// Ignore Liftoff code, since we don't know if it was compiled with
// debugging support.
// TODO(clemensb): Introduce {kLiftoffDebug} as a separate tier.
bool has_correct_tier =
tier == ExecutionTier::kTurbofan && reached_tier == tier &&
native_module_->HasCodeWithTier(function_index, tier);
if (!has_correct_tier) {
compilation_progress_[slot_index] =
ReachedRecompilationTierField::update(
compilation_progress_[slot_index], ExecutionTier::kNone);
compilation_progress_[slot_index] = MissingRecompilationField::update(
compilation_progress_[slot_index], true);
outstanding_recompilation_functions_++;
builder.AddRecompilationUnit(function_index, tier);
}
@ -2649,8 +2645,7 @@ CompilationStateImpl::GetNextCompilationUnit(
return compilation_unit_queues_.GetNextUnit(task_id, baseline_only);
}
void CompilationStateImpl::OnFinishedUnits(
Vector<WasmCode*> code_vector, Vector<WasmCompilationResult> results) {
void CompilationStateImpl::OnFinishedUnits(Vector<WasmCode*> code_vector) {
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "OnFinishedUnits",
"num_units", code_vector.size());
@ -2715,21 +2710,21 @@ void CompilationStateImpl::OnFinishedUnits(
outstanding_top_tier_functions_--;
}
// If there is recompilation in progress, we would only count the
// functions which are not Liftoff already, and would only decrement the
// counter once a function reaches Liftoff.
if (outstanding_recompilation_functions_ > 0) {
// TODO(duongn): extend this logic for tier up.
ExecutionTier recompilation_tier =
ReachedRecompilationTierField::decode(function_progress);
if (results[i].requested_tier == recompilation_tier_ &&
recompilation_tier == ExecutionTier::kNone) {
DCHECK(code->tier() >= recompilation_tier_);
if (V8_UNLIKELY(outstanding_recompilation_functions_ > 0) &&
MissingRecompilationField::decode(function_progress)) {
// If tiering up, accept any TurboFan code. For tiering down, look at
// the {for_debugging} flag. The tier can be Liftoff or TurboFan and is
// irrelevant here. In particular, we want to ignore any outstanding
// non-debugging units.
// TODO(clemensb): Replace {recompilation_tier_} by a better flag.
bool matches = recompilation_tier_ == ExecutionTier::kLiftoff
? code->for_debugging()
: code->tier() == ExecutionTier::kTurbofan;
if (matches) {
outstanding_recompilation_functions_--;
// Update function's recompilation progress.
compilation_progress_[slot_index] =
ReachedRecompilationTierField::update(
compilation_progress_[slot_index], code->tier());
compilation_progress_[slot_index] = MissingRecompilationField::update(
compilation_progress_[slot_index], false);
if (outstanding_recompilation_functions_ == 0) {
triggered_events.Add(CompilationEvent::kFinishedRecompilation);
}
@ -2988,7 +2983,7 @@ WasmCode* CompileImportWrapper(
result.tagged_parameter_slots,
result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), GetCodeKind(result),
ExecutionTier::kNone);
ExecutionTier::kNone, kNoDebugging);
WasmCode* published_code = native_module->PublishCode(std::move(wasm_code));
(*cache_scope)[key] = published_code;
published_code->IncRef();

View File

@ -896,7 +896,8 @@ WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) {
reloc_info.as_vector(), // reloc_info
source_pos.as_vector(), // source positions
WasmCode::kFunction, // kind
ExecutionTier::kNone}}; // tier
ExecutionTier::kNone, // tier
kNoDebugging}}; // for_debugging
new_code->MaybePrint(nullptr);
new_code->Validate();
@ -942,23 +943,23 @@ std::unique_ptr<WasmCode> NativeModule::AddCode(
int index, const CodeDesc& desc, int stack_slots,
int tagged_parameter_slots, Vector<const byte> protected_instructions_data,
Vector<const byte> source_position_table, WasmCode::Kind kind,
ExecutionTier tier) {
ExecutionTier tier, ForDebugging for_debugging) {
Vector<byte> code_space =
code_allocator_.AllocateForCode(this, desc.instr_size);
auto jump_table_ref =
FindJumpTablesForRegion(base::AddressRegionOf(code_space));
return AddCodeWithCodeSpace(index, desc, stack_slots, tagged_parameter_slots,
protected_instructions_data,
source_position_table, kind, tier, code_space,
jump_table_ref);
source_position_table, kind, tier, for_debugging,
code_space, jump_table_ref);
}
std::unique_ptr<WasmCode> NativeModule::AddCodeWithCodeSpace(
int index, const CodeDesc& desc, int stack_slots,
int tagged_parameter_slots, Vector<const byte> protected_instructions_data,
Vector<const byte> source_position_table, WasmCode::Kind kind,
ExecutionTier tier, Vector<uint8_t> dst_code_bytes,
const JumpTablesRef& jump_tables) {
ExecutionTier tier, ForDebugging for_debugging,
Vector<uint8_t> dst_code_bytes, const JumpTablesRef& jump_tables) {
Vector<byte> reloc_info{desc.buffer + desc.buffer_size - desc.reloc_size,
static_cast<size_t>(desc.reloc_size)};
@ -1008,7 +1009,7 @@ std::unique_ptr<WasmCode> NativeModule::AddCodeWithCodeSpace(
this, index, dst_code_bytes, stack_slots, tagged_parameter_slots,
safepoint_table_offset, handler_table_offset, constant_pool_offset,
code_comments_offset, instr_size, protected_instructions_data, reloc_info,
source_position_table, kind, tier}};
source_position_table, kind, tier, for_debugging}};
code->MaybePrint();
code->Validate();
@ -1120,7 +1121,7 @@ WasmCode* NativeModule::AddDeserializedCode(
this, index, dst_code_bytes, stack_slots, tagged_parameter_slots,
safepoint_table_offset, handler_table_offset, constant_pool_offset,
code_comments_offset, unpadded_binary_size, protected_instructions_data,
reloc_info, source_position_table, kind, tier}};
reloc_info, source_position_table, kind, tier, kNoDebugging}};
// Note: we do not flush the i-cache here, since the code needs to be
// relocated anyway. The caller is responsible for flushing the i-cache later.
@ -1172,21 +1173,22 @@ WasmCode* NativeModule::CreateEmptyJumpTableInRegion(
DCHECK(!code_space.empty());
ZapCode(reinterpret_cast<Address>(code_space.begin()), code_space.size());
std::unique_ptr<WasmCode> code{
new WasmCode{this, // native_module
kAnonymousFuncIndex, // index
code_space, // instructions
0, // stack_slots
0, // tagged_parameter_slots
0, // safepoint_table_offset
jump_table_size, // handler_table_offset
jump_table_size, // constant_pool_offset
jump_table_size, // code_comments_offset
jump_table_size, // unpadded_binary_size
{}, // protected_instructions
{}, // reloc_info
{}, // source_pos
WasmCode::kJumpTable, // kind
ExecutionTier::kNone}}; // tier
new WasmCode{this, // native_module
kAnonymousFuncIndex, // index
code_space, // instructions
0, // stack_slots
0, // tagged_parameter_slots
0, // safepoint_table_offset
jump_table_size, // handler_table_offset
jump_table_size, // constant_pool_offset
jump_table_size, // code_comments_offset
jump_table_size, // unpadded_binary_size
{}, // protected_instructions
{}, // reloc_info
{}, // source_pos
WasmCode::kJumpTable, // kind
ExecutionTier::kNone, // tier
kNoDebugging}}; // for_debugging
return PublishCode(std::move(code));
}
@ -1819,7 +1821,8 @@ std::vector<std::unique_ptr<WasmCode>> NativeModule::AddCompiledCode(
result.tagged_parameter_slots,
result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), GetCodeKind(result),
result.result_tier, this_code_space, jump_tables));
result.result_tier, result.for_debugging, this_code_space,
jump_tables));
}
DCHECK_EQ(0, code_space.size());

View File

@ -225,6 +225,10 @@ class V8_EXPORT_PRIVATE WasmCode final {
// Returns the last source position before {offset}.
int GetSourcePositionBefore(int offset);
// Returns whether this code was generated for debugging. If this returns
// true, but {tier()} is not {kLiftoff}, then Liftoff compilation bailed out.
bool for_debugging() const { return ForDebuggingField::decode(flags_); }
enum FlushICache : bool { kFlushICache = true, kNoFlushICache = false };
private:
@ -238,10 +242,11 @@ class V8_EXPORT_PRIVATE WasmCode final {
Vector<const byte> protected_instructions_data,
Vector<const byte> reloc_info,
Vector<const byte> source_position_table, Kind kind,
ExecutionTier tier)
ExecutionTier tier, ForDebugging for_debugging)
: native_module_(native_module),
instructions_(instructions.begin()),
flags_(KindField::encode(kind) | ExecutionTierField::encode(tier)),
flags_(KindField::encode(kind) | ExecutionTierField::encode(tier) |
ForDebuggingField::encode(for_debugging)),
meta_data_(ConcatenateBytes(
{protected_instructions_data, reloc_info, source_position_table})),
instructions_size_(instructions.length()),
@ -315,7 +320,7 @@ class V8_EXPORT_PRIVATE WasmCode final {
// Bits encoded in {flags_}:
using KindField = base::BitField8<Kind, 0, 3>;
using ExecutionTierField = KindField::Next<ExecutionTier, 2>;
// TODO(clemensb): Add "is_debug" flag.
using ForDebuggingField = ExecutionTierField::Next<ForDebugging, 1>;
// WasmCode is ref counted. Counters are held by:
// 1) The jump table / code table.
@ -447,7 +452,8 @@ class V8_EXPORT_PRIVATE NativeModule final {
int stack_slots, int tagged_parameter_slots,
Vector<const byte> protected_instructions,
Vector<const byte> source_position_table,
WasmCode::Kind kind, ExecutionTier tier);
WasmCode::Kind kind, ExecutionTier tier,
ForDebugging for_debugging);
// {PublishCode} makes the code available to the system by entering it into
// the code table and patching the jump table. It returns a raw pointer to the
@ -630,8 +636,8 @@ class V8_EXPORT_PRIVATE NativeModule final {
int tagged_parameter_slots,
Vector<const byte> protected_instructions_data,
Vector<const byte> source_position_table, WasmCode::Kind kind,
ExecutionTier tier, Vector<uint8_t> code_space,
const JumpTablesRef& jump_tables_ref);
ExecutionTier tier, ForDebugging for_debugging,
Vector<uint8_t> code_space, const JumpTablesRef& jump_tables_ref);
WasmCode* CreateEmptyJumpTableInRegion(
int jump_table_size, base::AddressRegion,

View File

@ -1124,7 +1124,7 @@ void WasmDebugInfo::RedirectToInterpreter(Handle<WasmDebugInfo> debug_info,
result.tagged_parameter_slots,
result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), wasm::WasmCode::kInterpreterEntry,
wasm::ExecutionTier::kInterpreter);
wasm::ExecutionTier::kInterpreter, wasm::kNoDebugging);
native_module->PublishCode(std::move(wasm_code));
DCHECK(native_module->IsRedirectedToInterpreter(func_index));
}

View File

@ -1455,7 +1455,7 @@ void WasmInstanceObject::ImportWasmJSFunctionIntoTable(
result.tagged_parameter_slots,
result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), GetCodeKind(result),
wasm::ExecutionTier::kNone);
wasm::ExecutionTier::kNone, wasm::kNoDebugging);
wasm::WasmCode* published_code =
native_module->PublishCode(std::move(wasm_code));
isolate->counters()->wasm_generated_code_size()->Increment(

View File

@ -3752,9 +3752,9 @@ TEST(Liftoff_tier_up) {
memcpy(buffer.get(), sub_code->instructions().begin(), sub_size);
desc.buffer = buffer.get();
desc.instr_size = static_cast<int>(sub_size);
std::unique_ptr<WasmCode> new_code =
native_module->AddCode(add.function_index(), desc, 0, 0, {}, {},
WasmCode::kFunction, ExecutionTier::kTurbofan);
std::unique_ptr<WasmCode> new_code = native_module->AddCode(
add.function_index(), desc, 0, 0, {}, {}, WasmCode::kFunction,
ExecutionTier::kTurbofan, kNoDebugging);
native_module->PublishCode(std::move(new_code));
// Second run should now execute {sub}.

View File

@ -178,7 +178,7 @@ uint32_t TestingModuleBuilder::AddFunction(const FunctionSig* sig,
result.tagged_parameter_slots,
result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), wasm::WasmCode::kInterpreterEntry,
wasm::ExecutionTier::kInterpreter);
wasm::ExecutionTier::kInterpreter, wasm::kNoDebugging);
native_module_->PublishCode(std::move(code));
}
DCHECK_LT(index, kMaxFunctions); // limited for testing.

View File

@ -4,7 +4,10 @@
// Flags: --experimental-wasm-anyref
load("test/mjsunit/wasm/wasm-module-builder.js");
// Test that tiering up and tiering down works even if functions cannot be
// compiled with Liftoff.
load('test/mjsunit/wasm/wasm-module-builder.js');
// Create a simple Wasm module.
function create_builder(i) {