Revert "[wasm-debug-eval] Implement additional evaluator API methods"
This reverts commit f2ea42d6b8
.
Reason for revert: Makes UBSan unhappy: https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20UBSan/10634
Original change's description:
> [wasm-debug-eval] Implement additional evaluator API methods
>
> This CL implements the __getLocal and __sbrk APIs of the evaluator
> interface. Also includes a drive-by fix of the imports' module: put
> them on the "env" module.
>
> Change-Id: Ie16d1b1cf924b88734eda184d1ce98d52f32f828
> Bug: chromium:1020120
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2132786
> Commit-Queue: Philip Pfaffe <pfaffe@chromium.org>
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#67122}
TBR=jkummerow@chromium.org,pfaffe@chromium.org
Change-Id: I23b078d37971e083c08c9b83994bbf38ac13f103
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:1020120
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2148787
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67124}
This commit is contained in:
parent
cf382c89fe
commit
efea740768
@ -5,7 +5,6 @@
|
||||
#include "src/wasm/wasm-debug-evaluate.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include "src/api/api-inl.h"
|
||||
#include "src/codegen/machine-type.h"
|
||||
@ -77,8 +76,7 @@ static bool CheckRangeOutOfBounds(uint32_t offset, uint32_t size,
|
||||
|
||||
class DebugEvaluatorProxy {
|
||||
public:
|
||||
explicit DebugEvaluatorProxy(Isolate* isolate, InterpretedFrame* frame)
|
||||
: isolate_(isolate), frame_(frame) {}
|
||||
explicit DebugEvaluatorProxy(Isolate* isolate) : isolate_(isolate) {}
|
||||
|
||||
static void GetMemoryTrampoline(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
@ -105,68 +103,17 @@ class DebugEvaluatorProxy {
|
||||
&debuggee_->memory_start()[offset], size);
|
||||
}
|
||||
|
||||
// void* __sbrk(intptr_t increment);
|
||||
uint32_t Sbrk(uint32_t increment) {
|
||||
if (increment > 0 && evaluator_->memory_size() <=
|
||||
std::numeric_limits<uint32_t>::max() - increment) {
|
||||
Handle<WasmMemoryObject> memory(evaluator_->memory_object(), isolate_);
|
||||
uint32_t new_pages =
|
||||
(increment - 1 + wasm::kWasmPageSize) / wasm::kWasmPageSize;
|
||||
WasmMemoryObject::Grow(isolate_, memory, new_pages);
|
||||
}
|
||||
return static_cast<uint32_t>(evaluator_->memory_size());
|
||||
}
|
||||
template <typename CallableT>
|
||||
Handle<JSReceiver> WrapAsV8Function(CallableT callback) {
|
||||
v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
|
||||
v8::Local<v8::Context> context = api_isolate->GetCurrentContext();
|
||||
std::string data;
|
||||
v8::Local<v8::Function> func =
|
||||
v8::Function::New(context, callback,
|
||||
v8::External::New(api_isolate, this))
|
||||
.ToLocalChecked();
|
||||
|
||||
static void SbrkTrampoline(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto& proxy = GetProxy(args);
|
||||
uint32_t size = proxy.GetArgAsUInt32(args, 0);
|
||||
|
||||
uint32_t result = proxy.Sbrk(size);
|
||||
args.GetReturnValue().Set(result);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_result(const WasmValue& result, uint32_t result_offset) {
|
||||
wasm::ScheduledErrorThrower thrower(isolate_, "debug evaluate proxy");
|
||||
T val = result.to<T>();
|
||||
static_assert(static_cast<uint32_t>(sizeof(T)) == sizeof(T),
|
||||
"Unexpected size");
|
||||
if (CheckRangeOutOfBounds(result_offset, sizeof(T),
|
||||
evaluator_->memory_size(), &thrower)) {
|
||||
return;
|
||||
}
|
||||
memcpy(&evaluator_->memory_start()[result_offset], &val, sizeof(T));
|
||||
}
|
||||
|
||||
// void __getLocal(uint32_t local, void* result);
|
||||
void GetLocal(uint32_t local, uint32_t result_offset) {
|
||||
WasmValue result = frame_->GetLocalValue(local);
|
||||
|
||||
switch (result.type().kind()) {
|
||||
case ValueType::kI32:
|
||||
write_result<uint32_t>(result, result_offset);
|
||||
break;
|
||||
case ValueType::kI64:
|
||||
write_result<int64_t>(result, result_offset);
|
||||
break;
|
||||
case ValueType::kF32:
|
||||
write_result<float>(result, result_offset);
|
||||
break;
|
||||
case ValueType::kF64:
|
||||
write_result<double>(result, result_offset);
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
}
|
||||
|
||||
static void GetLocalTrampoline(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto& proxy = GetProxy(args);
|
||||
uint32_t local = proxy.GetArgAsUInt32(args, 0);
|
||||
uint32_t result = proxy.GetArgAsUInt32(args, 1);
|
||||
|
||||
proxy.GetLocal(local, result);
|
||||
return Utils::OpenHandle(*func);
|
||||
}
|
||||
|
||||
Handle<JSObject> CreateImports() {
|
||||
@ -174,16 +121,14 @@ class DebugEvaluatorProxy {
|
||||
isolate_->factory()->NewJSObject(isolate_->object_function());
|
||||
Handle<JSObject> import_module_obj =
|
||||
isolate_->factory()->NewJSObject(isolate_->object_function());
|
||||
Object::SetProperty(isolate_, imports_obj, V8String(isolate_, "env"),
|
||||
import_module_obj)
|
||||
Object::SetProperty(isolate_, imports_obj,
|
||||
isolate_->factory()->empty_string(), import_module_obj)
|
||||
.Assert();
|
||||
|
||||
AddImport(import_module_obj, "__getLocal",
|
||||
DebugEvaluatorProxy::GetLocalTrampoline);
|
||||
AddImport(import_module_obj, "__getMemory",
|
||||
DebugEvaluatorProxy::GetMemoryTrampoline);
|
||||
AddImport(import_module_obj, "__sbrk", DebugEvaluatorProxy::SbrkTrampoline);
|
||||
|
||||
Object::SetProperty(
|
||||
isolate_, import_module_obj, V8String(isolate_, "__getMemory"),
|
||||
WrapAsV8Function(DebugEvaluatorProxy::GetMemoryTrampoline))
|
||||
.Assert();
|
||||
return imports_obj;
|
||||
}
|
||||
|
||||
@ -208,26 +153,7 @@ class DebugEvaluatorProxy {
|
||||
args.Data().As<v8::External>()->Value());
|
||||
}
|
||||
|
||||
template <typename CallableT>
|
||||
void AddImport(Handle<JSObject> import_module_obj, const char* function_name,
|
||||
CallableT callback) {
|
||||
v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
|
||||
v8::Local<v8::Context> context = api_isolate->GetCurrentContext();
|
||||
std::string data;
|
||||
v8::Local<v8::Function> v8_function =
|
||||
v8::Function::New(context, callback,
|
||||
v8::External::New(api_isolate, this))
|
||||
.ToLocalChecked();
|
||||
|
||||
auto wrapped_function = Utils::OpenHandle(*v8_function);
|
||||
|
||||
Object::SetProperty(isolate_, import_module_obj,
|
||||
V8String(isolate_, function_name), wrapped_function)
|
||||
.Assert();
|
||||
}
|
||||
|
||||
Isolate* isolate_;
|
||||
InterpretedFrame* frame_;
|
||||
Handle<WasmInstanceObject> evaluator_;
|
||||
Handle<WasmInstanceObject> debuggee_;
|
||||
};
|
||||
@ -245,31 +171,10 @@ static bool VerifyEvaluatorInterface(const WasmModule* raw_module,
|
||||
if (!CheckSignature(kWasmI32, {}, F.sig, thrower)) return false;
|
||||
} else if (F.imported) {
|
||||
if (name == "__getMemory") {
|
||||
// void __getMemory(uint32_t offset, uint32_t size, void* result);
|
||||
if (!CheckSignature(kWasmBottom, {kWasmI32, kWasmI32, kWasmI32}, F.sig,
|
||||
thrower)) {
|
||||
return false;
|
||||
}
|
||||
} else if (name == "__getLocal") {
|
||||
// void __getLocal(uint32_t local, void* result)
|
||||
if (!CheckSignature(kWasmBottom, {kWasmI32, kWasmI32}, F.sig,
|
||||
thrower)) {
|
||||
return false;
|
||||
}
|
||||
} else if (name == "__debug") {
|
||||
// void __debug(uint32_t flag, uint32_t value)
|
||||
if (!CheckSignature(kWasmBottom, {kWasmI32, kWasmI32}, F.sig,
|
||||
thrower)) {
|
||||
return false;
|
||||
}
|
||||
} else if (name == "__sbrk") {
|
||||
// uint32_t __sbrk(uint32_t increment)
|
||||
if (!CheckSignature(kWasmI32, {kWasmI32}, F.sig, thrower)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
thrower->LinkError("Unknown import \"%s\"", name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -302,7 +207,7 @@ Maybe<std::string> DebugEvaluateImpl(
|
||||
}
|
||||
|
||||
// Set up imports.
|
||||
DebugEvaluatorProxy proxy(isolate, frame.get());
|
||||
DebugEvaluatorProxy proxy(isolate);
|
||||
Handle<JSObject> imports = proxy.CreateImports();
|
||||
|
||||
// Instantiate Module.
|
||||
|
@ -2,19 +2,21 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/wasm/wasm-module-builder.h"
|
||||
|
||||
#include "src/base/memory.h"
|
||||
#include "src/codegen/signature.h"
|
||||
|
||||
#include "src/handles/handles.h"
|
||||
#include "src/init/v8.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
|
||||
#include "src/wasm/function-body-decoder.h"
|
||||
#include "src/wasm/leb-helper.h"
|
||||
#include "src/wasm/wasm-constants.h"
|
||||
#include "src/wasm/wasm-module-builder.h"
|
||||
#include "src/wasm/wasm-module.h"
|
||||
#include "src/wasm/wasm-opcodes.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
|
||||
#include "src/base/memory.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -334,17 +336,16 @@ uint32_t WasmModuleBuilder::AddTable(ValueType type, uint32_t min_size,
|
||||
return static_cast<uint32_t>(tables_.size() - 1);
|
||||
}
|
||||
|
||||
uint32_t WasmModuleBuilder::AddImport(Vector<const char> name, FunctionSig* sig,
|
||||
Vector<const char> module) {
|
||||
uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
|
||||
FunctionSig* sig) {
|
||||
DCHECK(adding_imports_allowed_);
|
||||
function_imports_.push_back({module, name, AddSignature(sig)});
|
||||
function_imports_.push_back({name, AddSignature(sig)});
|
||||
return static_cast<uint32_t>(function_imports_.size() - 1);
|
||||
}
|
||||
|
||||
uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name,
|
||||
ValueType type, bool mutability,
|
||||
Vector<const char> module) {
|
||||
global_imports_.push_back({module, name, type.value_type_code(), mutability});
|
||||
ValueType type, bool mutability) {
|
||||
global_imports_.push_back({name, type.value_type_code(), mutability});
|
||||
return static_cast<uint32_t>(global_imports_.size() - 1);
|
||||
}
|
||||
|
||||
@ -423,15 +424,15 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const {
|
||||
size_t start = EmitSection(kImportSectionCode, buffer);
|
||||
buffer->write_size(global_imports_.size() + function_imports_.size());
|
||||
for (auto import : global_imports_) {
|
||||
buffer->write_string(import.module); // module name
|
||||
buffer->write_string(import.name); // field name
|
||||
buffer->write_u32v(0); // module name (length)
|
||||
buffer->write_string(import.name); // field name
|
||||
buffer->write_u8(kExternalGlobal);
|
||||
buffer->write_u8(import.type_code);
|
||||
buffer->write_u8(import.mutability ? 1 : 0);
|
||||
}
|
||||
for (auto import : function_imports_) {
|
||||
buffer->write_string(import.module); // module name
|
||||
buffer->write_string(import.name); // field name
|
||||
buffer->write_u32v(0); // module name (length)
|
||||
buffer->write_string(import.name); // field name
|
||||
buffer->write_u8(kExternalFunction);
|
||||
buffer->write_u32v(import.sig_index);
|
||||
}
|
||||
|
@ -5,15 +5,16 @@
|
||||
#ifndef V8_WASM_WASM_MODULE_BUILDER_H_
|
||||
#define V8_WASM_WASM_MODULE_BUILDER_H_
|
||||
|
||||
#include "src/base/memory.h"
|
||||
#include "src/codegen/signature.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
|
||||
#include "src/base/memory.h"
|
||||
#include "src/utils/vector.h"
|
||||
#include "src/wasm/leb-helper.h"
|
||||
#include "src/wasm/local-decl-encoder.h"
|
||||
#include "src/wasm/wasm-module.h"
|
||||
#include "src/wasm/wasm-opcodes.h"
|
||||
#include "src/wasm/wasm-result.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -231,13 +232,12 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
|
||||
explicit WasmModuleBuilder(Zone* zone);
|
||||
|
||||
// Building methods.
|
||||
uint32_t AddImport(Vector<const char> name, FunctionSig* sig,
|
||||
Vector<const char> module = {});
|
||||
uint32_t AddImport(Vector<const char> name, FunctionSig* sig);
|
||||
WasmFunctionBuilder* AddFunction(FunctionSig* sig = nullptr);
|
||||
uint32_t AddGlobal(ValueType type, bool mutability = true,
|
||||
const WasmInitExpr& init = WasmInitExpr());
|
||||
uint32_t AddGlobalImport(Vector<const char> name, ValueType type,
|
||||
bool mutability, Vector<const char> module = {});
|
||||
bool mutability);
|
||||
void AddDataSegment(const byte* data, uint32_t size, uint32_t dest);
|
||||
uint32_t AddSignature(FunctionSig* sig);
|
||||
// In the current implementation, it's supported to have uninitialized slots
|
||||
@ -271,13 +271,11 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
|
||||
|
||||
private:
|
||||
struct WasmFunctionImport {
|
||||
Vector<const char> module;
|
||||
Vector<const char> name;
|
||||
uint32_t sig_index;
|
||||
};
|
||||
|
||||
struct WasmGlobalImport {
|
||||
Vector<const char> module;
|
||||
Vector<const char> name;
|
||||
ValueTypeCode type_code;
|
||||
bool mutability;
|
||||
|
@ -43,20 +43,14 @@ namespace {
|
||||
template <typename... FunctionArgsT>
|
||||
class TestCode {
|
||||
public:
|
||||
TestCode(WasmRunnerBase* runner, std::initializer_list<byte> code,
|
||||
std::initializer_list<ValueType::Kind> locals = {})
|
||||
: compiler_(&runner->NewFunction<FunctionArgsT...>()),
|
||||
code_(code),
|
||||
locals_(static_cast<uint32_t>(locals.size())) {
|
||||
for (ValueType::Kind T : locals) {
|
||||
compiler_->AllocateLocal(ValueType(T));
|
||||
}
|
||||
TestCode(WasmRunnerBase* runner, std::initializer_list<byte> code)
|
||||
: compiler_(&runner->NewFunction<FunctionArgsT...>()), code_(code) {
|
||||
compiler_->Build(code.begin(), code.end());
|
||||
}
|
||||
|
||||
Handle<BreakPoint> BreakOnReturn(WasmRunnerBase* runner) {
|
||||
runner->TierDown();
|
||||
uint32_t return_offset_in_function = locals_ + FindReturn();
|
||||
uint32_t return_offset_in_function = FindReturn();
|
||||
|
||||
int function_index = compiler_->function_index();
|
||||
int function_offset =
|
||||
@ -104,7 +98,6 @@ class TestCode {
|
||||
|
||||
WasmFunctionCompiler* compiler_;
|
||||
std::vector<byte> code_;
|
||||
uint32_t locals_;
|
||||
};
|
||||
|
||||
class WasmEvaluatorBuilder {
|
||||
@ -115,9 +108,6 @@ class WasmEvaluatorBuilder {
|
||||
: zone_(&allocator_, ZONE_NAME), builder_(&zone_) {
|
||||
get_memory_function_index = AddImport<void, uint32_t, uint32_t, uint32_t>(
|
||||
CStrVector("__getMemory"));
|
||||
get_local_function_index =
|
||||
AddImport<void, uint32_t, uint32_t>(CStrVector("__getLocal"));
|
||||
sbrk_function_index = AddImport<uint32_t, uint32_t>(CStrVector("__sbrk"));
|
||||
wasm_format_function =
|
||||
builder_.AddFunction(WasmRunnerBase::CreateSig<uint32_t>(&zone_));
|
||||
wasm_format_function->SetName(CStrVector("wasm_format"));
|
||||
@ -129,8 +119,7 @@ class WasmEvaluatorBuilder {
|
||||
template <typename ReturnT, typename... ArgTs>
|
||||
uint32_t AddImport(Vector<const char> name) {
|
||||
return builder_.AddImport(
|
||||
name, WasmRunnerBase::CreateSig<ReturnT, ArgTs...>(&zone_),
|
||||
CStrVector("env"));
|
||||
name, WasmRunnerBase::CreateSig<ReturnT, ArgTs...>(&zone_));
|
||||
}
|
||||
|
||||
void push_back(std::initializer_list<byte> code) {
|
||||
@ -138,16 +127,6 @@ class WasmEvaluatorBuilder {
|
||||
static_cast<uint32_t>(code.size()));
|
||||
}
|
||||
|
||||
void CallSbrk(std::initializer_list<byte> args) {
|
||||
push_back(args);
|
||||
push_back({WASM_CALL_FUNCTION0(sbrk_function_index)});
|
||||
}
|
||||
|
||||
void CallGetLocal(std::initializer_list<byte> args) {
|
||||
push_back(args);
|
||||
push_back({WASM_CALL_FUNCTION0(get_local_function_index)});
|
||||
}
|
||||
|
||||
void CallGetMemory(std::initializer_list<byte> args) {
|
||||
push_back(args);
|
||||
push_back({WASM_CALL_FUNCTION0(get_memory_function_index)});
|
||||
@ -164,8 +143,6 @@ class WasmEvaluatorBuilder {
|
||||
Zone zone_;
|
||||
WasmModuleBuilder builder_;
|
||||
uint32_t get_memory_function_index = 0;
|
||||
uint32_t get_local_function_index = 0;
|
||||
uint32_t sbrk_function_index = 0;
|
||||
WasmFunctionBuilder* wasm_format_function = nullptr;
|
||||
};
|
||||
|
||||
@ -241,7 +218,7 @@ WASM_COMPILED_EXEC_TEST(WasmDebugEvaluate_CompileFailed) {
|
||||
code.BreakOnReturn(&runner);
|
||||
|
||||
WasmEvaluatorBuilder evaluator(execution_tier);
|
||||
// Create a module that doesn't compile by missing the END bytecode.
|
||||
// Create a module that doesn't compile by missing the END bytecode
|
||||
evaluator.push_back({WASM_RETURN1(WASM_I32V_1(33))});
|
||||
|
||||
Isolate* isolate = runner.main_isolate();
|
||||
@ -285,12 +262,11 @@ WASM_COMPILED_EXEC_TEST(WasmDebugEvaluate_ExecuteFailed_SEGV) {
|
||||
|
||||
TestCode<int> code(&runner, {WASM_RETURN1(WASM_I32V_1(32))});
|
||||
|
||||
// Use a max memory size of 2 here to verify the precondition for the
|
||||
// GrowMemory test below.
|
||||
WasmEvaluatorBuilder evaluator(execution_tier, 1, 2);
|
||||
// Create a module that doesn't compile by missing the END bytecode
|
||||
WasmEvaluatorBuilder evaluator(execution_tier);
|
||||
code.BreakOnReturn(&runner);
|
||||
|
||||
// Load 1 byte from an address that's too high.
|
||||
// Load 1 byte from an address that's too high
|
||||
evaluator.CallGetMemory(
|
||||
{WASM_I32V_1(32), WASM_I32V_1(1), WASM_I32V_3((1 << 16) + 1)});
|
||||
evaluator.push_back({WASM_RETURN1(WASM_I32V_1(33)), WASM_END});
|
||||
@ -307,34 +283,6 @@ WASM_COMPILED_EXEC_TEST(WasmDebugEvaluate_ExecuteFailed_SEGV) {
|
||||
std::string::npos);
|
||||
}
|
||||
|
||||
WASM_COMPILED_EXEC_TEST(WasmDebugEvaluate_GrowMemory) {
|
||||
WasmRunner<int> runner(execution_tier);
|
||||
runner.builder().AddMemoryElems<int32_t>(64);
|
||||
|
||||
TestCode<int> code(
|
||||
&runner,
|
||||
{WASM_STORE_MEM(MachineType::Int32(), WASM_I32V_1(32), WASM_I32V_2('A')),
|
||||
WASM_RETURN1(WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(32)))});
|
||||
code.BreakOnReturn(&runner);
|
||||
|
||||
WasmEvaluatorBuilder evaluator(execution_tier, 1, 2);
|
||||
// Grow the memory.
|
||||
evaluator.CallSbrk({WASM_I32V_1(1)});
|
||||
// Load 1 byte from an address that's too high for the default memory.
|
||||
evaluator.CallGetMemory(
|
||||
{WASM_I32V_1(32), WASM_I32V_1(1), WASM_I32V_3((1 << 16) + 1)});
|
||||
evaluator.push_back({WASM_RETURN1(WASM_I32V_3((1 << 16) + 1)), WASM_END});
|
||||
|
||||
Isolate* isolate = runner.main_isolate();
|
||||
WasmBreakHandler break_handler(isolate, evaluator.bytes());
|
||||
CHECK(!code.Run(&runner).is_null());
|
||||
|
||||
WasmBreakHandler::EvaluationResult result =
|
||||
break_handler.result().ToChecked();
|
||||
CHECK(result.error.IsNothing());
|
||||
CHECK_EQ(result.result.ToChecked(), "A");
|
||||
}
|
||||
|
||||
WASM_COMPILED_EXEC_TEST(WasmDebugEvaluate_LinearMemory) {
|
||||
WasmRunner<int> runner(execution_tier);
|
||||
runner.builder().AddMemoryElems<int32_t>(64);
|
||||
@ -361,30 +309,6 @@ WASM_COMPILED_EXEC_TEST(WasmDebugEvaluate_LinearMemory) {
|
||||
CHECK_EQ(result.result.ToChecked(), "A");
|
||||
}
|
||||
|
||||
WASM_COMPILED_EXEC_TEST(WasmDebugEvaluate_Locals) {
|
||||
WasmRunner<int> runner(execution_tier);
|
||||
runner.builder().AddMemoryElems<int32_t>(64);
|
||||
|
||||
TestCode<int> code(
|
||||
&runner,
|
||||
{WASM_SET_LOCAL(0, WASM_I32V_2('A')), WASM_RETURN1(WASM_GET_LOCAL(0))},
|
||||
{ValueType::kI32});
|
||||
code.BreakOnReturn(&runner);
|
||||
|
||||
WasmEvaluatorBuilder evaluator(execution_tier);
|
||||
evaluator.CallGetLocal({WASM_I32V_1(0), WASM_I32V_1(33)});
|
||||
evaluator.push_back({WASM_RETURN1(WASM_I32V_1(33)), WASM_END});
|
||||
|
||||
Isolate* isolate = runner.main_isolate();
|
||||
WasmBreakHandler break_handler(isolate, evaluator.bytes());
|
||||
CHECK(!code.Run(&runner).is_null());
|
||||
|
||||
WasmBreakHandler::EvaluationResult result =
|
||||
break_handler.result().ToChecked();
|
||||
CHECK(result.error.IsNothing());
|
||||
CHECK_EQ(result.result.ToChecked(), "A");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace wasm
|
||||
} // namespace internal
|
||||
|
Loading…
Reference in New Issue
Block a user