Commit 61150c17 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[liftoff] Refactor options for Liftoff compilation

The number of arguments for the LiftoffCompiler has grown significantly
since its initial implementation, and it becomes hard to keep track of
all options at the call sites.

This CL refactors all optional parameters into a {LiftoffOptions} struct
which has a factory-like interface.
This will allow us to add more options in the future, e.g. for dynamic
tiering.

R=thibaudm@chromium.org

Change-Id: I66697bb2f99b676a84c158304cc3a285e1b077d0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3069148
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76098}
parent c2f30c2b
...@@ -7915,6 +7915,8 @@ wasm::WasmCompilationResult ExecuteTurbofanWasmCompilation( ...@@ -7915,6 +7915,8 @@ wasm::WasmCompilationResult ExecuteTurbofanWasmCompilation(
std::vector<WasmLoopInfo> loop_infos; std::vector<WasmLoopInfo> loop_infos;
wasm::WasmFeatures unused_detected_features;
if (!detected) detected = &unused_detected_features;
if (!BuildGraphForWasmFunction(env, func_body, func_index, detected, mcgraph, if (!BuildGraphForWasmFunction(env, func_body, func_index, detected, mcgraph,
&loop_infos, node_origins, source_positions)) { &loop_infos, node_origins, source_positions)) {
return wasm::WasmCompilationResult{}; return wasm::WasmCompilationResult{};
......
...@@ -6275,10 +6275,7 @@ constexpr base::EnumSet<ValueKind> LiftoffCompiler::kUnconditionallySupported; ...@@ -6275,10 +6275,7 @@ constexpr base::EnumSet<ValueKind> LiftoffCompiler::kUnconditionallySupported;
WasmCompilationResult ExecuteLiftoffCompilation( WasmCompilationResult ExecuteLiftoffCompilation(
CompilationEnv* env, const FunctionBody& func_body, int func_index, CompilationEnv* env, const FunctionBody& func_body, int func_index,
ForDebugging for_debugging, Counters* counters, WasmFeatures* detected, ForDebugging for_debugging, const LiftoffOptions& compiler_options) {
base::Vector<const int> breakpoints,
std::unique_ptr<DebugSideTable>* debug_sidetable, int dead_breakpoint,
int32_t* max_steps, int32_t* nondeterminism) {
int func_body_size = static_cast<int>(func_body.end - func_body.start); int func_body_size = static_cast<int>(func_body.end - func_body.start);
TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"), TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
"wasm.CompileBaseline", "funcIndex", func_index, "bodySize", "wasm.CompileBaseline", "funcIndex", func_index, "bodySize",
...@@ -6294,20 +6291,25 @@ WasmCompilationResult ExecuteLiftoffCompilation( ...@@ -6294,20 +6291,25 @@ WasmCompilationResult ExecuteLiftoffCompilation(
// have to grow more often. // have to grow more often.
int initial_buffer_size = static_cast<int>(128 + code_size_estimate * 4 / 3); int initial_buffer_size = static_cast<int>(128 + code_size_estimate * 4 / 3);
std::unique_ptr<DebugSideTableBuilder> debug_sidetable_builder; std::unique_ptr<DebugSideTableBuilder> debug_sidetable_builder;
if (debug_sidetable) { if (compiler_options.debug_sidetable) {
debug_sidetable_builder = std::make_unique<DebugSideTableBuilder>(); debug_sidetable_builder = std::make_unique<DebugSideTableBuilder>();
} }
DCHECK_IMPLIES(max_steps, for_debugging == kForDebugging); DCHECK_IMPLIES(compiler_options.max_steps, for_debugging == kForDebugging);
WasmFeatures unused_detected_features;
WasmFullDecoder<Decoder::kBooleanValidation, LiftoffCompiler> decoder( WasmFullDecoder<Decoder::kBooleanValidation, LiftoffCompiler> decoder(
&zone, env->module, env->enabled_features, detected, func_body, &zone, env->module, env->enabled_features,
call_descriptor, env, &zone, NewAssemblerBuffer(initial_buffer_size), compiler_options.detected_features ? compiler_options.detected_features
debug_sidetable_builder.get(), for_debugging, func_index, breakpoints, : &unused_detected_features,
dead_breakpoint, max_steps, nondeterminism); func_body, call_descriptor, env, &zone,
NewAssemblerBuffer(initial_buffer_size), debug_sidetable_builder.get(),
for_debugging, func_index, compiler_options.breakpoints,
compiler_options.dead_breakpoint, compiler_options.max_steps,
compiler_options.nondeterminism);
decoder.Decode(); decoder.Decode();
LiftoffCompiler* compiler = &decoder.interface(); LiftoffCompiler* compiler = &decoder.interface();
if (decoder.failed()) compiler->OnFirstError(&decoder); if (decoder.failed()) compiler->OnFirstError(&decoder);
if (counters) { if (auto* counters = compiler_options.counters) {
// Check that the histogram for the bailout reasons has the correct size. // Check that the histogram for the bailout reasons has the correct size.
DCHECK_EQ(0, counters->liftoff_bailout_reasons()->min()); DCHECK_EQ(0, counters->liftoff_bailout_reasons()->min());
DCHECK_EQ(kNumBailoutReasons - 1, DCHECK_EQ(kNumBailoutReasons - 1,
...@@ -6331,7 +6333,7 @@ WasmCompilationResult ExecuteLiftoffCompilation( ...@@ -6331,7 +6333,7 @@ WasmCompilationResult ExecuteLiftoffCompilation(
result.func_index = func_index; result.func_index = func_index;
result.result_tier = ExecutionTier::kLiftoff; result.result_tier = ExecutionTier::kLiftoff;
result.for_debugging = for_debugging; result.for_debugging = for_debugging;
if (debug_sidetable) { if (auto* debug_sidetable = compiler_options.debug_sidetable) {
*debug_sidetable = debug_sidetable_builder->GenerateDebugSideTable(); *debug_sidetable = debug_sidetable_builder->GenerateDebugSideTable();
} }
......
...@@ -53,12 +53,46 @@ enum LiftoffBailoutReason : int8_t { ...@@ -53,12 +53,46 @@ enum LiftoffBailoutReason : int8_t {
kNumBailoutReasons kNumBailoutReasons
}; };
V8_EXPORT_PRIVATE WasmCompilationResult ExecuteLiftoffCompilation( struct LiftoffOptions {
CompilationEnv*, const FunctionBody&, int func_index, ForDebugging, Counters* counters = nullptr;
Counters*, WasmFeatures* detected_features, WasmFeatures* detected_features = nullptr;
base::Vector<const int> breakpoints = {}, base::Vector<const int> breakpoints = {};
std::unique_ptr<DebugSideTable>* = nullptr, int dead_breakpoint = 0, std::unique_ptr<DebugSideTable>* debug_sidetable = nullptr;
int32_t* max_steps = nullptr, int32_t* nondeterminism = nullptr); int dead_breakpoint = 0;
int32_t* max_steps = nullptr;
int32_t* nondeterminism = nullptr;
// We keep the macro as small as possible by offloading the actual DCHECK and
// assignment to another function. This makes debugging easier.
#define SETTER(field) \
template <typename T> \
LiftoffOptions& set_##field(T new_value) { \
return Set<decltype(field)>(&field, new_value); \
}
SETTER(counters)
SETTER(detected_features)
SETTER(breakpoints)
SETTER(debug_sidetable)
SETTER(dead_breakpoint)
SETTER(max_steps)
SETTER(nondeterminism)
#undef SETTER
private:
template <typename T>
LiftoffOptions& Set(T* ptr, T new_value) {
// The field must still have its default value.
DCHECK_EQ(*ptr, T{});
*ptr = new_value;
return *this;
}
};
V8_EXPORT_PRIVATE WasmCompilationResult
ExecuteLiftoffCompilation(CompilationEnv*, const FunctionBody&, int func_index,
ForDebugging, const LiftoffOptions& = {});
V8_EXPORT_PRIVATE std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable( V8_EXPORT_PRIVATE std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable(
const WasmCode*); const WasmCode*);
......
...@@ -107,18 +107,20 @@ WasmCompilationResult WasmCompilationUnit::ExecuteFunctionCompilation( ...@@ -107,18 +107,20 @@ WasmCompilationResult WasmCompilationUnit::ExecuteFunctionCompilation(
if (V8_LIKELY(FLAG_wasm_tier_mask_for_testing == 0) || if (V8_LIKELY(FLAG_wasm_tier_mask_for_testing == 0) ||
func_index_ >= 32 || func_index_ >= 32 ||
((FLAG_wasm_tier_mask_for_testing & (1 << func_index_)) == 0)) { ((FLAG_wasm_tier_mask_for_testing & (1 << func_index_)) == 0)) {
if (V8_LIKELY(func_index_ >= 32 || (FLAG_wasm_debug_mask_for_testing & // We do not use the debug side table, we only (optionally) pass it to
(1 << func_index_)) == 0)) { // cover different code paths in Liftoff for testing.
result = ExecuteLiftoffCompilation( std::unique_ptr<DebugSideTable> unused_debug_sidetable;
env, func_body, func_index_, for_debugging_, counters, detected); std::unique_ptr<DebugSideTable>* debug_sidetable_ptr = nullptr;
} else { if (V8_UNLIKELY(func_index_ < 32 && (FLAG_wasm_debug_mask_for_testing &
// We don't use the debug side table, we only pass it to cover (1 << func_index_)) != 0)) {
// different code paths in Liftoff for testing. debug_sidetable_ptr = &unused_debug_sidetable;
std::unique_ptr<DebugSideTable> debug_sidetable;
result = ExecuteLiftoffCompilation(env, func_body, func_index_,
kForDebugging, counters, detected,
{}, &debug_sidetable);
} }
result = ExecuteLiftoffCompilation(
env, func_body, func_index_, for_debugging_,
LiftoffOptions{}
.set_counters(counters)
.set_detected_features(detected)
.set_debug_sidetable(debug_sidetable_ptr));
if (result.succeeded()) break; if (result.succeeded()) break;
} }
......
...@@ -280,12 +280,13 @@ class DebugInfoImpl { ...@@ -280,12 +280,13 @@ class DebugInfoImpl {
// Debug side tables for stepping are generated lazily. // Debug side tables for stepping are generated lazily.
bool generate_debug_sidetable = for_debugging == kWithBreakpoints; bool generate_debug_sidetable = for_debugging == kWithBreakpoints;
Counters* counters = nullptr;
WasmFeatures unused_detected;
WasmCompilationResult result = ExecuteLiftoffCompilation( WasmCompilationResult result = ExecuteLiftoffCompilation(
&env, body, func_index, for_debugging, counters, &unused_detected, &env, body, func_index, for_debugging,
offsets, generate_debug_sidetable ? &debug_sidetable : nullptr, LiftoffOptions{}
dead_breakpoint); .set_breakpoints(offsets)
.set_dead_breakpoint(dead_breakpoint)
.set_debug_sidetable(generate_debug_sidetable ? &debug_sidetable
: nullptr));
// Liftoff compilation failure is a FATAL error. We rely on complete Liftoff // Liftoff compilation failure is a FATAL error. We rely on complete Liftoff
// support for debugging. // support for debugging.
if (!result.succeeded()) FATAL("Liftoff compilation failed"); if (!result.succeeded()) FATAL("Liftoff compilation failed");
......
...@@ -46,10 +46,10 @@ class LiftoffCompileEnvironment { ...@@ -46,10 +46,10 @@ class LiftoffCompileEnvironment {
WasmFeatures detected2; WasmFeatures detected2;
WasmCompilationResult result1 = ExecuteLiftoffCompilation( WasmCompilationResult result1 = ExecuteLiftoffCompilation(
&env, test_func.body, test_func.code->index(), kNoDebugging, &env, test_func.body, test_func.code->index(), kNoDebugging,
isolate_->counters(), &detected1); LiftoffOptions{}.set_detected_features(&detected1));
WasmCompilationResult result2 = ExecuteLiftoffCompilation( WasmCompilationResult result2 = ExecuteLiftoffCompilation(
&env, test_func.body, test_func.code->index(), kNoDebugging, &env, test_func.body, test_func.code->index(), kNoDebugging,
isolate_->counters(), &detected2); LiftoffOptions{}.set_detected_features(&detected2));
CHECK(result1.succeeded()); CHECK(result1.succeeded());
CHECK(result2.succeeded()); CHECK(result2.succeeded());
...@@ -71,11 +71,12 @@ class LiftoffCompileEnvironment { ...@@ -71,11 +71,12 @@ class LiftoffCompileEnvironment {
auto test_func = AddFunction(return_types, param_types, raw_function_bytes); auto test_func = AddFunction(return_types, param_types, raw_function_bytes);
CompilationEnv env = wasm_runner_.builder().CreateCompilationEnv(); CompilationEnv env = wasm_runner_.builder().CreateCompilationEnv();
WasmFeatures detected;
std::unique_ptr<DebugSideTable> debug_side_table_via_compilation; std::unique_ptr<DebugSideTable> debug_side_table_via_compilation;
auto result = ExecuteLiftoffCompilation( auto result = ExecuteLiftoffCompilation(
&env, test_func.body, 0, kForDebugging, nullptr, &detected, &env, test_func.body, 0, kForDebugging,
base::VectorOf(breakpoints), &debug_side_table_via_compilation); LiftoffOptions{}
.set_breakpoints(base::VectorOf(breakpoints))
.set_debug_sidetable(&debug_side_table_via_compilation));
CHECK(result.succeeded()); CHECK(result.succeeded());
// If there are no breakpoint, then {ExecuteLiftoffCompilation} should // If there are no breakpoint, then {ExecuteLiftoffCompilation} should
......
...@@ -549,21 +549,20 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) { ...@@ -549,21 +549,20 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
ForDebugging for_debugging = ForDebugging for_debugging =
native_module->IsTieredDown() ? kForDebugging : kNoDebugging; native_module->IsTieredDown() ? kForDebugging : kNoDebugging;
WasmFeatures unused_detected_features;
base::Optional<WasmCompilationResult> result; base::Optional<WasmCompilationResult> result;
if (builder_->test_execution_tier() == if (builder_->test_execution_tier() ==
TestExecutionTier::kLiftoffForFuzzing) { TestExecutionTier::kLiftoffForFuzzing) {
result.emplace(ExecuteLiftoffCompilation( result.emplace(ExecuteLiftoffCompilation(
&env, func_body, function_->func_index, kForDebugging, &env, func_body, function_->func_index, kForDebugging,
isolate()->counters(), &unused_detected_features, {}, nullptr, 0, LiftoffOptions{}
builder_->max_steps_ptr(), builder_->non_determinism_ptr())); .set_max_steps(builder_->max_steps_ptr())
.set_nondeterminism(builder_->non_determinism_ptr())));
} else { } else {
WasmCompilationUnit unit(function_->func_index, builder_->execution_tier(), WasmCompilationUnit unit(function_->func_index, builder_->execution_tier(),
for_debugging); for_debugging);
result.emplace(unit.ExecuteCompilation( result.emplace(unit.ExecuteCompilation(
&env, native_module->compilation_state()->GetWireBytesStorage().get(), &env, native_module->compilation_state()->GetWireBytesStorage().get(),
isolate()->counters(), &unused_detected_features)); nullptr, nullptr));
} }
WasmCode* code = native_module->PublishCode( WasmCode* code = native_module->PublishCode(
native_module->AddCompiledCode(std::move(*result))); native_module->AddCompiledCode(std::move(*result)));
......
...@@ -59,12 +59,12 @@ Handle<WasmModuleObject> CompileReferenceModule(Zone* zone, Isolate* isolate, ...@@ -59,12 +59,12 @@ Handle<WasmModuleObject> CompileReferenceModule(Zone* zone, Isolate* isolate,
++i) { ++i) {
auto& func = module->functions[i]; auto& func = module->functions[i];
base::Vector<const uint8_t> func_code = wire_bytes.GetFunctionBytes(&func); base::Vector<const uint8_t> func_code = wire_bytes.GetFunctionBytes(&func);
WasmFeatures unused_detected_features;
FunctionBody func_body(func.sig, func.code.offset(), func_code.begin(), FunctionBody func_body(func.sig, func.code.offset(), func_code.begin(),
func_code.end()); func_code.end());
auto result = ExecuteLiftoffCompilation( auto result = ExecuteLiftoffCompilation(
&env, func_body, func.func_index, kForDebugging, isolate->counters(), &env, func_body, func.func_index, kForDebugging,
&unused_detected_features, {}, nullptr, 0, max_steps, nondeterminism); LiftoffOptions{}.set_max_steps(max_steps).set_nondeterminism(
nondeterminism));
native_module->PublishCode( native_module->PublishCode(
native_module->AddCompiledCode(std::move(result))); native_module->AddCompiledCode(std::move(result)));
} }
......
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