Commit 8aadf7c5 authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm][debug] Generate debug sidetable from code alone

Instead of passing a bunch of objects and pointers to
{GenerateLiftoffDebugSideTable}, just pass the WasmCode pointer for
which the debug sidetable should be created.

This requires changing the corresponding cctests to actually compile
code, such that we can get a WasmCode pointer.

R=thibaudm@chromium.org

Bug: chromium:1172299
Change-Id: If42f06a545feb590f9c2377ce95e6214bbc6f566
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2674006Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72526}
parent a9eff909
...@@ -5364,22 +5364,32 @@ WasmCompilationResult ExecuteLiftoffCompilation( ...@@ -5364,22 +5364,32 @@ WasmCompilationResult ExecuteLiftoffCompilation(
} }
std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable( std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable(
AccountingAllocator* allocator, CompilationEnv* env, const WasmCode* code) {
const FunctionBody& func_body, int func_index, ForDebugging for_debugging) { auto* native_module = code->native_module();
auto* function = &native_module->module()->functions[code->index()];
ModuleWireBytes wire_bytes{native_module->wire_bytes()};
Vector<const byte> function_bytes = wire_bytes.GetFunctionBytes(function);
CompilationEnv env = native_module->CreateCompilationEnv();
FunctionBody func_body{function->sig, 0, function_bytes.begin(),
function_bytes.end()};
AccountingAllocator* allocator = native_module->engine()->allocator();
Zone zone(allocator, "LiftoffDebugSideTableZone"); Zone zone(allocator, "LiftoffDebugSideTableZone");
auto call_descriptor = compiler::GetWasmCallDescriptor(&zone, func_body.sig); auto call_descriptor = compiler::GetWasmCallDescriptor(&zone, function->sig);
DebugSideTableBuilder debug_sidetable_builder; DebugSideTableBuilder debug_sidetable_builder;
WasmFeatures detected; WasmFeatures detected;
constexpr int kSteppingBreakpoints[] = {0}; constexpr int kSteppingBreakpoints[] = {0};
DCHECK(for_debugging == kForDebugging || for_debugging == kForStepping); DCHECK(code->for_debugging() == kForDebugging ||
Vector<const int> breakpoints = for_debugging == kForStepping code->for_debugging() == kForStepping);
Vector<const int> breakpoints = code->for_debugging() == kForStepping
? ArrayVector(kSteppingBreakpoints) ? ArrayVector(kSteppingBreakpoints)
: Vector<const int>{}; : Vector<const int>{};
WasmFullDecoder<Decoder::kBooleanValidation, LiftoffCompiler> decoder( WasmFullDecoder<Decoder::kBooleanValidation, LiftoffCompiler> decoder(
&zone, env->module, env->enabled_features, &detected, func_body, &zone, native_module->module(), env.enabled_features, &detected,
call_descriptor, env, &zone, func_body, call_descriptor, &env, &zone,
NewAssemblerBuffer(AssemblerBase::kDefaultBufferSize), NewAssemblerBuffer(AssemblerBase::kDefaultBufferSize),
&debug_sidetable_builder, for_debugging, func_index, breakpoints); &debug_sidetable_builder, code->for_debugging(), code->index(),
breakpoints);
decoder.Decode(); decoder.Decode();
DCHECK(decoder.ok()); DCHECK(decoder.ok());
DCHECK(!decoder.interface().did_bailout()); DCHECK(!decoder.interface().did_bailout());
......
...@@ -60,8 +60,7 @@ V8_EXPORT_PRIVATE WasmCompilationResult ExecuteLiftoffCompilation( ...@@ -60,8 +60,7 @@ V8_EXPORT_PRIVATE WasmCompilationResult ExecuteLiftoffCompilation(
std::unique_ptr<DebugSideTable>* = nullptr, int dead_breakpoint = 0); std::unique_ptr<DebugSideTable>* = nullptr, int dead_breakpoint = 0);
V8_EXPORT_PRIVATE std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable( V8_EXPORT_PRIVATE std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable(
AccountingAllocator*, CompilationEnv*, const FunctionBody&, int func_index, const WasmCode*);
ForDebugging);
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
......
...@@ -481,17 +481,8 @@ class DebugInfoImpl { ...@@ -481,17 +481,8 @@ class DebugInfoImpl {
} }
// Otherwise create the debug side table now. // Otherwise create the debug side table now.
auto* module = native_module_->module();
auto* allocator = native_module_->engine()->allocator();
auto* function = &module->functions[code->index()];
ModuleWireBytes wire_bytes{native_module_->wire_bytes()};
Vector<const byte> function_bytes = wire_bytes.GetFunctionBytes(function);
CompilationEnv env = native_module_->CreateCompilationEnv();
FunctionBody func_body{function->sig, 0, function_bytes.begin(),
function_bytes.end()};
std::unique_ptr<DebugSideTable> debug_side_table = std::unique_ptr<DebugSideTable> debug_side_table =
GenerateLiftoffDebugSideTable(allocator, &env, func_body, code->index(), GenerateLiftoffDebugSideTable(code);
code->for_debugging());
DebugSideTable* ret = debug_side_table.get(); DebugSideTable* ret = debug_side_table.get();
// Check cache again, maybe another thread concurrently generated a debug // Check cache again, maybe another thread concurrently generated a debug
......
...@@ -20,15 +20,16 @@ class LiftoffCompileEnvironment { ...@@ -20,15 +20,16 @@ class LiftoffCompileEnvironment {
: isolate_(CcTest::InitIsolateOnce()), : isolate_(CcTest::InitIsolateOnce()),
handle_scope_(isolate_), handle_scope_(isolate_),
zone_(isolate_->allocator(), ZONE_NAME), zone_(isolate_->allocator(), ZONE_NAME),
module_builder_(&zone_, nullptr, TestExecutionTier::kLiftoff, wasm_runner_(nullptr, TestExecutionTier::kLiftoff, 0,
kRuntimeExceptionSupport, kNoLowerSimd) { kRuntimeExceptionSupport, kNoLowerSimd) {
// Add a table of length 1, for indirect calls. // Add a table of length 1, for indirect calls.
module_builder_.AddIndirectFunctionTable(nullptr, 1); wasm_runner_.builder().AddIndirectFunctionTable(nullptr, 1);
// Set tiered down such that we generate debugging code.
wasm_runner_.builder().SetTieredDown();
} }
struct TestFunction { struct TestFunction {
OwnedVector<uint8_t> body_bytes; WasmCode* code;
WasmFunction* function;
FunctionBody body; FunctionBody body;
}; };
...@@ -39,17 +40,15 @@ class LiftoffCompileEnvironment { ...@@ -39,17 +40,15 @@ class LiftoffCompileEnvironment {
auto test_func = AddFunction(return_types, param_types, raw_function_bytes); auto test_func = AddFunction(return_types, param_types, raw_function_bytes);
// Now compile the function with Liftoff two times. // Now compile the function with Liftoff two times.
CompilationEnv env = module_builder_.CreateCompilationEnv(); CompilationEnv env = wasm_runner_.builder().CreateCompilationEnv();
WasmFeatures detected1; WasmFeatures detected1;
WasmFeatures detected2; WasmFeatures detected2;
WasmCompilationResult result1 = WasmCompilationResult result1 = ExecuteLiftoffCompilation(
ExecuteLiftoffCompilation(isolate_->allocator(), &env, test_func.body, isolate_->allocator(), &env, test_func.body, test_func.code->index(),
test_func.function->func_index, kNoDebugging, kNoDebugging, isolate_->counters(), &detected1);
isolate_->counters(), &detected1); WasmCompilationResult result2 = ExecuteLiftoffCompilation(
WasmCompilationResult result2 = isolate_->allocator(), &env, test_func.body, test_func.code->index(),
ExecuteLiftoffCompilation(isolate_->allocator(), &env, test_func.body, kNoDebugging, isolate_->counters(), &detected2);
test_func.function->func_index, kNoDebugging,
isolate_->counters(), &detected2);
CHECK(result1.succeeded()); CHECK(result1.succeeded());
CHECK(result2.succeeded()); CHECK(result2.succeeded());
...@@ -70,20 +69,20 @@ class LiftoffCompileEnvironment { ...@@ -70,20 +69,20 @@ class LiftoffCompileEnvironment {
std::vector<int> breakpoints = {}) { std::vector<int> breakpoints = {}) {
auto test_func = AddFunction(return_types, param_types, raw_function_bytes); auto test_func = AddFunction(return_types, param_types, raw_function_bytes);
CompilationEnv env = module_builder_.CreateCompilationEnv(); CompilationEnv env = wasm_runner_.builder().CreateCompilationEnv();
WasmFeatures detected; WasmFeatures detected;
std::unique_ptr<DebugSideTable> debug_side_table_via_compilation; std::unique_ptr<DebugSideTable> debug_side_table_via_compilation;
ExecuteLiftoffCompilation(CcTest::i_isolate()->allocator(), &env, auto result = ExecuteLiftoffCompilation(
test_func.body, 0, kForDebugging, nullptr, CcTest::i_isolate()->allocator(), &env, test_func.body, 0,
&detected, VectorOf(breakpoints), kForDebugging, nullptr, &detected, VectorOf(breakpoints),
&debug_side_table_via_compilation); &debug_side_table_via_compilation);
CHECK(result.succeeded());
// If there are no breakpoint, then {ExecuteLiftoffCompilation} should // If there are no breakpoint, then {ExecuteLiftoffCompilation} should
// provide the same debug side table. // provide the same debug side table.
if (breakpoints.empty()) { if (breakpoints.empty()) {
std::unique_ptr<DebugSideTable> debug_side_table = std::unique_ptr<DebugSideTable> debug_side_table =
GenerateLiftoffDebugSideTable(CcTest::i_isolate()->allocator(), &env, GenerateLiftoffDebugSideTable(test_func.code);
test_func.body, 0, kForDebugging);
CheckTableEquals(*debug_side_table, *debug_side_table_via_compilation); CheckTableEquals(*debug_side_table, *debug_side_table_via_compilation);
} }
...@@ -94,6 +93,7 @@ class LiftoffCompileEnvironment { ...@@ -94,6 +93,7 @@ class LiftoffCompileEnvironment {
static void CheckTableEquals(const DebugSideTable& a, static void CheckTableEquals(const DebugSideTable& a,
const DebugSideTable& b) { const DebugSideTable& b) {
CHECK_EQ(a.num_locals(), b.num_locals()); CHECK_EQ(a.num_locals(), b.num_locals());
CHECK_EQ(a.entries().size(), b.entries().size());
CHECK(std::equal(a.entries().begin(), a.entries().end(), CHECK(std::equal(a.entries().begin(), a.entries().end(),
b.entries().begin(), b.entries().end(), b.entries().begin(), b.entries().end(),
&CheckEntryEquals)); &CheckEntryEquals));
...@@ -125,19 +125,6 @@ class LiftoffCompileEnvironment { ...@@ -125,19 +125,6 @@ class LiftoffCompileEnvironment {
return true; return true;
} }
OwnedVector<uint8_t> GenerateFunctionBody(
std::initializer_list<uint8_t> raw_function_bytes) {
// Build the function bytes by prepending the locals decl and appending an
// "end" opcode.
OwnedVector<uint8_t> function_bytes =
OwnedVector<uint8_t>::New(raw_function_bytes.size() + 2);
function_bytes[0] = WASM_NO_LOCALS;
std::copy(raw_function_bytes.begin(), raw_function_bytes.end(),
&function_bytes[1]);
function_bytes[raw_function_bytes.size() + 1] = WASM_END;
return function_bytes;
}
FunctionSig* AddSig(std::initializer_list<ValueType> return_types, FunctionSig* AddSig(std::initializer_list<ValueType> return_types,
std::initializer_list<ValueType> param_types) { std::initializer_list<ValueType> param_types) {
ValueType* storage = ValueType* storage =
...@@ -147,30 +134,41 @@ class LiftoffCompileEnvironment { ...@@ -147,30 +134,41 @@ class LiftoffCompileEnvironment {
storage + return_types.size()); storage + return_types.size());
FunctionSig* sig = zone_.New<FunctionSig>(return_types.size(), FunctionSig* sig = zone_.New<FunctionSig>(return_types.size(),
param_types.size(), storage); param_types.size(), storage);
module_builder_.AddSignature(sig);
return sig; return sig;
} }
TestFunction AddFunction(std::initializer_list<ValueType> return_types, TestFunction AddFunction(std::initializer_list<ValueType> return_types,
std::initializer_list<ValueType> param_types, std::initializer_list<ValueType> param_types,
std::initializer_list<uint8_t> raw_function_bytes) { std::initializer_list<uint8_t> function_bytes) {
OwnedVector<uint8_t> function_bytes =
GenerateFunctionBody(raw_function_bytes);
FunctionSig* sig = AddSig(return_types, param_types); FunctionSig* sig = AddSig(return_types, param_types);
int func_index = // Compile the function so we can get the WasmCode* which is later used to
module_builder_.AddFunction(sig, "f", TestingModuleBuilder::kWasm); // generate the debug side table lazily.
WasmFunction* function = module_builder_.GetFunctionAt(func_index); auto& func_compiler = wasm_runner_.NewFunction(sig, "f");
function->code = {module_builder_.AddBytes(function_bytes.as_vector()), func_compiler.Build(function_bytes.begin(), function_bytes.end());
static_cast<uint32_t>(function_bytes.size())};
FunctionBody body{function->sig, 0, function_bytes.begin(), WasmCode* code =
function_bytes.end()}; wasm_runner_.builder().GetFunctionCode(func_compiler.function_index());
return {std::move(function_bytes), function, body};
// Get the wire bytes created by the function compiler (including locals
// declaration and the trailing "end" opcode).
NativeModule* native_module = code->native_module();
auto* function = &native_module->module()->functions[code->index()];
Vector<const uint8_t> function_wire_bytes =
native_module->wire_bytes().SubVector(function->code.offset(),
function->code.end_offset());
FunctionBody body{sig, 0, function_wire_bytes.begin(),
function_wire_bytes.end()};
return {code, body};
} }
Isolate* isolate_; Isolate* isolate_;
HandleScope handle_scope_; HandleScope handle_scope_;
Zone zone_; Zone zone_;
TestingModuleBuilder module_builder_; // wasm_runner_ is used to build actual code objects needed to request lazy
// generation of debug side tables.
WasmRunnerBase wasm_runner_;
WasmCodeRefScope code_ref_scope_;
}; };
struct DebugSideTableEntry { struct DebugSideTableEntry {
......
...@@ -233,12 +233,16 @@ class TestingModuleBuilder { ...@@ -233,12 +233,16 @@ class TestingModuleBuilder {
void SetExecutable() { native_module_->SetExecutable(true); } void SetExecutable() { native_module_->SetExecutable(true); }
void TierDown() { void SetTieredDown() {
native_module_->SetTieringState(kTieredDown); native_module_->SetTieringState(kTieredDown);
native_module_->RecompileForTiering();
execution_tier_ = TestExecutionTier::kLiftoff; execution_tier_ = TestExecutionTier::kLiftoff;
} }
void TierDown() {
SetTieredDown();
native_module_->RecompileForTiering();
}
CompilationEnv CreateCompilationEnv(); CompilationEnv CreateCompilationEnv();
ExecutionTier execution_tier() const { ExecutionTier execution_tier() const {
......
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