Commit 4721585b authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[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: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67119}
parent 8c6f9067
......@@ -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));
}
......
......@@ -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();
}
......
......@@ -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:
......
......@@ -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 {
......
......@@ -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();
......
......@@ -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.
......@@ -1186,7 +1187,8 @@ WasmCode* NativeModule::CreateEmptyJumpTableInRegion(
{}, // reloc_info
{}, // source_pos
WasmCode::kJumpTable, // kind
ExecutionTier::kNone}}; // tier
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());
......
......@@ -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,
......
......@@ -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));
}
......
......@@ -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(
......
......@@ -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}.
......
......@@ -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.
......
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment