[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/+/2674006
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72526}
This commit is contained in:
Clemens Backes 2021-02-04 11:42:33 +01:00 committed by Commit Bot
parent a9eff909e9
commit 8aadf7c5cb
5 changed files with 71 additions and 69 deletions

View File

@ -5364,22 +5364,32 @@ WasmCompilationResult ExecuteLiftoffCompilation(
}
std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable(
AccountingAllocator* allocator, CompilationEnv* env,
const FunctionBody& func_body, int func_index, ForDebugging for_debugging) {
const WasmCode* code) {
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");
auto call_descriptor = compiler::GetWasmCallDescriptor(&zone, func_body.sig);
auto call_descriptor = compiler::GetWasmCallDescriptor(&zone, function->sig);
DebugSideTableBuilder debug_sidetable_builder;
WasmFeatures detected;
constexpr int kSteppingBreakpoints[] = {0};
DCHECK(for_debugging == kForDebugging || for_debugging == kForStepping);
Vector<const int> breakpoints = for_debugging == kForStepping
DCHECK(code->for_debugging() == kForDebugging ||
code->for_debugging() == kForStepping);
Vector<const int> breakpoints = code->for_debugging() == kForStepping
? ArrayVector(kSteppingBreakpoints)
: Vector<const int>{};
WasmFullDecoder<Decoder::kBooleanValidation, LiftoffCompiler> decoder(
&zone, env->module, env->enabled_features, &detected, func_body,
call_descriptor, env, &zone,
&zone, native_module->module(), env.enabled_features, &detected,
func_body, call_descriptor, &env, &zone,
NewAssemblerBuffer(AssemblerBase::kDefaultBufferSize),
&debug_sidetable_builder, for_debugging, func_index, breakpoints);
&debug_sidetable_builder, code->for_debugging(), code->index(),
breakpoints);
decoder.Decode();
DCHECK(decoder.ok());
DCHECK(!decoder.interface().did_bailout());

View File

@ -60,8 +60,7 @@ V8_EXPORT_PRIVATE WasmCompilationResult ExecuteLiftoffCompilation(
std::unique_ptr<DebugSideTable>* = nullptr, int dead_breakpoint = 0);
V8_EXPORT_PRIVATE std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable(
AccountingAllocator*, CompilationEnv*, const FunctionBody&, int func_index,
ForDebugging);
const WasmCode*);
} // namespace wasm
} // namespace internal

View File

@ -481,17 +481,8 @@ class DebugInfoImpl {
}
// 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 =
GenerateLiftoffDebugSideTable(allocator, &env, func_body, code->index(),
code->for_debugging());
GenerateLiftoffDebugSideTable(code);
DebugSideTable* ret = debug_side_table.get();
// Check cache again, maybe another thread concurrently generated a debug

View File

@ -20,15 +20,16 @@ class LiftoffCompileEnvironment {
: isolate_(CcTest::InitIsolateOnce()),
handle_scope_(isolate_),
zone_(isolate_->allocator(), ZONE_NAME),
module_builder_(&zone_, nullptr, TestExecutionTier::kLiftoff,
kRuntimeExceptionSupport, kNoLowerSimd) {
wasm_runner_(nullptr, TestExecutionTier::kLiftoff, 0,
kRuntimeExceptionSupport, kNoLowerSimd) {
// 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 {
OwnedVector<uint8_t> body_bytes;
WasmFunction* function;
WasmCode* code;
FunctionBody body;
};
@ -39,17 +40,15 @@ class LiftoffCompileEnvironment {
auto test_func = AddFunction(return_types, param_types, raw_function_bytes);
// Now compile the function with Liftoff two times.
CompilationEnv env = module_builder_.CreateCompilationEnv();
CompilationEnv env = wasm_runner_.builder().CreateCompilationEnv();
WasmFeatures detected1;
WasmFeatures detected2;
WasmCompilationResult result1 =
ExecuteLiftoffCompilation(isolate_->allocator(), &env, test_func.body,
test_func.function->func_index, kNoDebugging,
isolate_->counters(), &detected1);
WasmCompilationResult result2 =
ExecuteLiftoffCompilation(isolate_->allocator(), &env, test_func.body,
test_func.function->func_index, kNoDebugging,
isolate_->counters(), &detected2);
WasmCompilationResult result1 = ExecuteLiftoffCompilation(
isolate_->allocator(), &env, test_func.body, test_func.code->index(),
kNoDebugging, isolate_->counters(), &detected1);
WasmCompilationResult result2 = ExecuteLiftoffCompilation(
isolate_->allocator(), &env, test_func.body, test_func.code->index(),
kNoDebugging, isolate_->counters(), &detected2);
CHECK(result1.succeeded());
CHECK(result2.succeeded());
@ -70,20 +69,20 @@ class LiftoffCompileEnvironment {
std::vector<int> breakpoints = {}) {
auto test_func = AddFunction(return_types, param_types, raw_function_bytes);
CompilationEnv env = module_builder_.CreateCompilationEnv();
CompilationEnv env = wasm_runner_.builder().CreateCompilationEnv();
WasmFeatures detected;
std::unique_ptr<DebugSideTable> debug_side_table_via_compilation;
ExecuteLiftoffCompilation(CcTest::i_isolate()->allocator(), &env,
test_func.body, 0, kForDebugging, nullptr,
&detected, VectorOf(breakpoints),
&debug_side_table_via_compilation);
auto result = ExecuteLiftoffCompilation(
CcTest::i_isolate()->allocator(), &env, test_func.body, 0,
kForDebugging, nullptr, &detected, VectorOf(breakpoints),
&debug_side_table_via_compilation);
CHECK(result.succeeded());
// If there are no breakpoint, then {ExecuteLiftoffCompilation} should
// provide the same debug side table.
if (breakpoints.empty()) {
std::unique_ptr<DebugSideTable> debug_side_table =
GenerateLiftoffDebugSideTable(CcTest::i_isolate()->allocator(), &env,
test_func.body, 0, kForDebugging);
GenerateLiftoffDebugSideTable(test_func.code);
CheckTableEquals(*debug_side_table, *debug_side_table_via_compilation);
}
@ -94,6 +93,7 @@ class LiftoffCompileEnvironment {
static void CheckTableEquals(const DebugSideTable& a,
const DebugSideTable& b) {
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(),
b.entries().begin(), b.entries().end(),
&CheckEntryEquals));
@ -125,19 +125,6 @@ class LiftoffCompileEnvironment {
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,
std::initializer_list<ValueType> param_types) {
ValueType* storage =
@ -147,30 +134,41 @@ class LiftoffCompileEnvironment {
storage + return_types.size());
FunctionSig* sig = zone_.New<FunctionSig>(return_types.size(),
param_types.size(), storage);
module_builder_.AddSignature(sig);
return sig;
}
TestFunction AddFunction(std::initializer_list<ValueType> return_types,
std::initializer_list<ValueType> param_types,
std::initializer_list<uint8_t> raw_function_bytes) {
OwnedVector<uint8_t> function_bytes =
GenerateFunctionBody(raw_function_bytes);
std::initializer_list<uint8_t> function_bytes) {
FunctionSig* sig = AddSig(return_types, param_types);
int func_index =
module_builder_.AddFunction(sig, "f", TestingModuleBuilder::kWasm);
WasmFunction* function = module_builder_.GetFunctionAt(func_index);
function->code = {module_builder_.AddBytes(function_bytes.as_vector()),
static_cast<uint32_t>(function_bytes.size())};
FunctionBody body{function->sig, 0, function_bytes.begin(),
function_bytes.end()};
return {std::move(function_bytes), function, body};
// Compile the function so we can get the WasmCode* which is later used to
// generate the debug side table lazily.
auto& func_compiler = wasm_runner_.NewFunction(sig, "f");
func_compiler.Build(function_bytes.begin(), function_bytes.end());
WasmCode* code =
wasm_runner_.builder().GetFunctionCode(func_compiler.function_index());
// 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_;
HandleScope handle_scope_;
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 {

View File

@ -233,12 +233,16 @@ class TestingModuleBuilder {
void SetExecutable() { native_module_->SetExecutable(true); }
void TierDown() {
void SetTieredDown() {
native_module_->SetTieringState(kTieredDown);
native_module_->RecompileForTiering();
execution_tier_ = TestExecutionTier::kLiftoff;
}
void TierDown() {
SetTieredDown();
native_module_->RecompileForTiering();
}
CompilationEnv CreateCompilationEnv();
ExecutionTier execution_tier() const {