Commit c134f0af authored by Thibaud Michaud's avatar Thibaud Michaud Committed by V8 LUCI CQ

[wasm][liftoff] Add step counter in Liftoff

Add a new testing tier based on Liftoff. In this tier, the Liftoff
compiler takes an address to a counter, and decrements that counter at
every instruction. When the counter reaches 0, execution aborts.

R=clemensb@chromium.org

Bug: v8:11856
Change-Id: I20970e323ff19f7cb6ab6855377c678ca391421e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2944440Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75022}
parent 385f304d
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "src/utils/ostreams.h" #include "src/utils/ostreams.h"
#include "src/utils/utils.h" #include "src/utils/utils.h"
#include "src/wasm/baseline/liftoff-assembler.h" #include "src/wasm/baseline/liftoff-assembler.h"
#include "src/wasm/baseline/liftoff-register.h"
#include "src/wasm/function-body-decoder-impl.h" #include "src/wasm/function-body-decoder-impl.h"
#include "src/wasm/function-compiler.h" #include "src/wasm/function-compiler.h"
#include "src/wasm/memory-tracing.h" #include "src/wasm/memory-tracing.h"
...@@ -455,7 +456,8 @@ class LiftoffCompiler { ...@@ -455,7 +456,8 @@ class LiftoffCompiler {
std::unique_ptr<AssemblerBuffer> buffer, std::unique_ptr<AssemblerBuffer> buffer,
DebugSideTableBuilder* debug_sidetable_builder, DebugSideTableBuilder* debug_sidetable_builder,
ForDebugging for_debugging, int func_index, ForDebugging for_debugging, int func_index,
Vector<const int> breakpoints = {}, int dead_breakpoint = 0) Vector<const int> breakpoints = {}, int dead_breakpoint = 0,
int* max_steps = nullptr)
: asm_(std::move(buffer)), : asm_(std::move(buffer)),
descriptor_( descriptor_(
GetLoweredCallDescriptor(compilation_zone, call_descriptor)), GetLoweredCallDescriptor(compilation_zone, call_descriptor)),
...@@ -471,7 +473,8 @@ class LiftoffCompiler { ...@@ -471,7 +473,8 @@ class LiftoffCompiler {
next_breakpoint_ptr_(breakpoints.begin()), next_breakpoint_ptr_(breakpoints.begin()),
next_breakpoint_end_(breakpoints.end()), next_breakpoint_end_(breakpoints.end()),
dead_breakpoint_(dead_breakpoint), dead_breakpoint_(dead_breakpoint),
handlers_(compilation_zone) { handlers_(compilation_zone),
max_steps_(max_steps) {
if (breakpoints.empty()) { if (breakpoints.empty()) {
next_breakpoint_ptr_ = next_breakpoint_end_ = nullptr; next_breakpoint_ptr_ = next_breakpoint_end_ = nullptr;
} }
...@@ -1018,6 +1021,26 @@ class LiftoffCompiler { ...@@ -1018,6 +1021,26 @@ class LiftoffCompiler {
EmitBreakpoint(decoder); EmitBreakpoint(decoder);
__ bind(&cont); __ bind(&cont);
} }
if (V8_UNLIKELY(max_steps_ != nullptr)) {
LiftoffRegList pinned;
LiftoffRegister max_steps = __ GetUnusedRegister(kGpReg, {});
pinned.set(max_steps);
LiftoffRegister max_steps_addr = __ GetUnusedRegister(kGpReg, pinned);
pinned.set(max_steps_addr);
__ LoadConstant(
max_steps_addr,
WasmValue::ForUintPtr(reinterpret_cast<uintptr_t>(max_steps_)));
__ Load(max_steps, max_steps_addr.gp(), no_reg, 0, LoadType::kI32Load,
pinned);
Label cont;
__ emit_i32_cond_jumpi(kUnequal, &cont, max_steps.gp(), 0);
// Abort.
Trap(decoder, kTrapUnreachable);
__ bind(&cont);
__ emit_i32_subi(max_steps.gp(), max_steps.gp(), 1);
__ Store(max_steps_addr.gp(), no_reg, 0, max_steps, StoreType::kI32Store,
pinned);
}
} }
void NextInstruction(FullDecoder* decoder, WasmOpcode opcode) { void NextInstruction(FullDecoder* decoder, WasmOpcode opcode) {
...@@ -6079,6 +6102,8 @@ class LiftoffCompiler { ...@@ -6079,6 +6102,8 @@ class LiftoffCompiler {
// Current number of exception refs on the stack. // Current number of exception refs on the stack.
int num_exceptions_ = 0; int num_exceptions_ = 0;
int* max_steps_;
bool has_outstanding_op() const { bool has_outstanding_op() const {
return outstanding_op_ != kNoOutstandingOp; return outstanding_op_ != kNoOutstandingOp;
} }
...@@ -6135,7 +6160,8 @@ WasmCompilationResult ExecuteLiftoffCompilation( ...@@ -6135,7 +6160,8 @@ WasmCompilationResult ExecuteLiftoffCompilation(
AccountingAllocator* allocator, CompilationEnv* env, AccountingAllocator* allocator, CompilationEnv* env,
const FunctionBody& func_body, int func_index, ForDebugging for_debugging, const FunctionBody& func_body, int func_index, ForDebugging for_debugging,
Counters* counters, WasmFeatures* detected, Vector<const int> breakpoints, Counters* counters, WasmFeatures* detected, Vector<const int> breakpoints,
std::unique_ptr<DebugSideTable>* debug_sidetable, int dead_breakpoint) { std::unique_ptr<DebugSideTable>* debug_sidetable, int dead_breakpoint,
int* max_steps) {
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",
...@@ -6153,11 +6179,12 @@ WasmCompilationResult ExecuteLiftoffCompilation( ...@@ -6153,11 +6179,12 @@ WasmCompilationResult ExecuteLiftoffCompilation(
if (debug_sidetable) { if (debug_sidetable) {
debug_sidetable_builder = std::make_unique<DebugSideTableBuilder>(); debug_sidetable_builder = std::make_unique<DebugSideTableBuilder>();
} }
DCHECK_IMPLIES(max_steps, for_debugging == kForDebugging);
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, detected, func_body,
call_descriptor, env, &zone, instruction_buffer->CreateView(), call_descriptor, env, &zone, instruction_buffer->CreateView(),
debug_sidetable_builder.get(), for_debugging, func_index, breakpoints, debug_sidetable_builder.get(), for_debugging, func_index, breakpoints,
dead_breakpoint); dead_breakpoint, max_steps);
decoder.Decode(); decoder.Decode();
LiftoffCompiler* compiler = &decoder.interface(); LiftoffCompiler* compiler = &decoder.interface();
if (decoder.failed()) compiler->OnFirstError(&decoder); if (decoder.failed()) compiler->OnFirstError(&decoder);
......
...@@ -57,7 +57,8 @@ V8_EXPORT_PRIVATE WasmCompilationResult ExecuteLiftoffCompilation( ...@@ -57,7 +57,8 @@ V8_EXPORT_PRIVATE WasmCompilationResult ExecuteLiftoffCompilation(
AccountingAllocator*, CompilationEnv*, const FunctionBody&, int func_index, AccountingAllocator*, CompilationEnv*, const FunctionBody&, int func_index,
ForDebugging, Counters*, WasmFeatures* detected_features, ForDebugging, Counters*, WasmFeatures* detected_features,
Vector<const int> breakpoints = {}, Vector<const int> breakpoints = {},
std::unique_ptr<DebugSideTable>* = nullptr, int dead_breakpoint = 0); std::unique_ptr<DebugSideTable>* = nullptr, int dead_breakpoint = 0,
int* max_steps = nullptr);
V8_EXPORT_PRIVATE std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable( V8_EXPORT_PRIVATE std::unique_ptr<DebugSideTable> GenerateLiftoffDebugSideTable(
const WasmCode*); const WasmCode*);
......
...@@ -430,6 +430,7 @@ v8_source_set("cctest_sources") { ...@@ -430,6 +430,7 @@ v8_source_set("cctest_sources") {
"wasm/test-gc.cc", "wasm/test-gc.cc",
"wasm/test-grow-memory.cc", "wasm/test-grow-memory.cc",
"wasm/test-jump-table-assembler.cc", "wasm/test-jump-table-assembler.cc",
"wasm/test-liftoff-for-fuzzing.cc",
"wasm/test-liftoff-inspection.cc", "wasm/test-liftoff-inspection.cc",
"wasm/test-run-wasm-64.cc", "wasm/test-run-wasm-64.cc",
"wasm/test-run-wasm-asmjs.cc", "wasm/test-run-wasm-asmjs.cc",
......
...@@ -586,6 +586,7 @@ ...@@ -586,6 +586,7 @@
'test-gc/*': [SKIP], 'test-gc/*': [SKIP],
'test-grow-memory/*': [SKIP], 'test-grow-memory/*': [SKIP],
'test-js-to-wasm/*': [SKIP], 'test-js-to-wasm/*': [SKIP],
'test-liftoff-for-fuzzing/*': [SKIP],
'test-liftoff-inspection/*': [SKIP], 'test-liftoff-inspection/*': [SKIP],
'test-run-wasm*': [SKIP], 'test-run-wasm*': [SKIP],
'test-streaming-compilation/*': [SKIP], 'test-streaming-compilation/*': [SKIP],
......
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// #include "src/api/api-inl.h"
// #include "test/cctest/wasm/wasm-atomics-utils.h"
#include "test/cctest/cctest.h"
#include "test/cctest/wasm/wasm-run-utils.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-macro-gen.h"
namespace v8 {
namespace internal {
namespace wasm {
namespace test_liftoff_for_fuzzing {
TEST(MaxSteps) {
WasmRunner<uint32_t> r(TestExecutionTier::kLiftoffForFuzzing);
BUILD(r, WASM_LOOP(WASM_BR(0)), WASM_I32V(23));
r.SetMaxSteps(10);
r.CheckCallViaJSTraps();
}
} // namespace test_liftoff_for_fuzzing
} // namespace wasm
} // namespace internal
} // namespace v8
...@@ -4,9 +4,11 @@ ...@@ -4,9 +4,11 @@
#include "test/cctest/wasm/wasm-run-utils.h" #include "test/cctest/wasm/wasm-run-utils.h"
#include "src/base/optional.h"
#include "src/codegen/assembler-inl.h" #include "src/codegen/assembler-inl.h"
#include "src/diagnostics/code-tracer.h" #include "src/diagnostics/code-tracer.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
#include "src/wasm/baseline/liftoff-compiler.h"
#include "src/wasm/graph-builder-interface.h" #include "src/wasm/graph-builder-interface.h"
#include "src/wasm/leb-helper.h" #include "src/wasm/leb-helper.h"
#include "src/wasm/module-compiler.h" #include "src/wasm/module-compiler.h"
...@@ -547,15 +549,26 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) { ...@@ -547,15 +549,26 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
builder_->instance_object()->module_object().native_module(); builder_->instance_object()->module_object().native_module();
ForDebugging for_debugging = ForDebugging for_debugging =
native_module->IsTieredDown() ? kForDebugging : kNoDebugging; native_module->IsTieredDown() ? kForDebugging : kNoDebugging;
WasmCompilationUnit unit(function_->func_index, builder_->execution_tier(),
for_debugging);
WasmFeatures unused_detected_features; WasmFeatures unused_detected_features;
WasmCompilationResult result = unit.ExecuteCompilation(
isolate()->wasm_engine(), &env, base::Optional<WasmCompilationResult> result;
native_module->compilation_state()->GetWireBytesStorage(), if (builder_->test_execution_tier() ==
isolate()->counters(), &unused_detected_features); TestExecutionTier::kLiftoffForFuzzing) {
result.emplace(ExecuteLiftoffCompilation(
isolate()->wasm_engine()->allocator(), &env, func_body,
function_->func_index, kForDebugging, isolate()->counters(),
&unused_detected_features, {}, nullptr, 0, builder_->max_steps_ptr()));
} else {
WasmCompilationUnit unit(function_->func_index, builder_->execution_tier(),
for_debugging);
result.emplace(unit.ExecuteCompilation(
isolate()->wasm_engine(), &env,
native_module->compilation_state()->GetWireBytesStorage(),
isolate()->counters(), &unused_detected_features));
}
WasmCode* code = native_module->PublishCode( WasmCode* code = native_module->PublishCode(
native_module->AddCompiledCode(std::move(result))); native_module->AddCompiledCode(std::move(*result)));
DCHECK_NOT_NULL(code); DCHECK_NOT_NULL(code);
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
Script script = builder_->instance_object()->module_object().script(); Script script = builder_->instance_object()->module_object().script();
......
...@@ -50,7 +50,8 @@ namespace wasm { ...@@ -50,7 +50,8 @@ namespace wasm {
enum class TestExecutionTier : int8_t { enum class TestExecutionTier : int8_t {
kLiftoff = static_cast<int8_t>(ExecutionTier::kLiftoff), kLiftoff = static_cast<int8_t>(ExecutionTier::kLiftoff),
kTurbofan = static_cast<int8_t>(ExecutionTier::kTurbofan), kTurbofan = static_cast<int8_t>(ExecutionTier::kTurbofan),
kInterpreter kInterpreter,
kLiftoffForFuzzing
}; };
static_assert( static_assert(
std::is_same<std::underlying_type<ExecutionTier>::type, std::is_same<std::underlying_type<ExecutionTier>::type,
...@@ -242,6 +243,8 @@ class TestingModuleBuilder { ...@@ -242,6 +243,8 @@ class TestingModuleBuilder {
CompilationEnv CreateCompilationEnv(); CompilationEnv CreateCompilationEnv();
TestExecutionTier test_execution_tier() const { return execution_tier_; }
ExecutionTier execution_tier() const { ExecutionTier execution_tier() const {
switch (execution_tier_) { switch (execution_tier_) {
case TestExecutionTier::kTurbofan: case TestExecutionTier::kTurbofan:
...@@ -257,6 +260,9 @@ class TestingModuleBuilder { ...@@ -257,6 +260,9 @@ class TestingModuleBuilder {
return runtime_exception_support_; return runtime_exception_support_;
} }
void set_max_steps(int n) { max_steps_ = n; }
int* max_steps_ptr() { return &max_steps_; }
void EnableFeature(WasmFeature feature) { enabled_features_.Add(feature); } void EnableFeature(WasmFeature feature) { enabled_features_.Add(feature); }
private: private:
...@@ -272,6 +278,7 @@ class TestingModuleBuilder { ...@@ -272,6 +278,7 @@ class TestingModuleBuilder {
Handle<WasmInstanceObject> instance_object_; Handle<WasmInstanceObject> instance_object_;
NativeModule* native_module_ = nullptr; NativeModule* native_module_ = nullptr;
RuntimeExceptionSupport runtime_exception_support_; RuntimeExceptionSupport runtime_exception_support_;
int max_steps_ = 0;
// Data segment arrays that are normally allocated on the instance. // Data segment arrays that are normally allocated on the instance.
std::vector<byte> data_segment_data_; std::vector<byte> data_segment_data_;
...@@ -626,6 +633,8 @@ class WasmRunner : public WasmRunnerBase { ...@@ -626,6 +633,8 @@ class WasmRunner : public WasmRunnerBase {
void CheckCallViaJSTraps(ParamTypes... p) { void CheckCallViaJSTraps(ParamTypes... p) {
CheckCallViaJS(static_cast<double>(0xDEADBEEF), p...); CheckCallViaJS(static_cast<double>(0xDEADBEEF), p...);
} }
void SetMaxSteps(int n) { builder_.set_max_steps(n); }
}; };
// A macro to define tests that run in different engine configurations. // A macro to define tests that run in different engine configurations.
......
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