Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(719)

Unified Diff: test/cctest/wasm/wasm-run-utils.h

Issue 1972153002: [wasm] Implement an interpreter for WASM. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/cctest/wasm/test-run-wasm-interpreter.cc ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/wasm/wasm-run-utils.h
diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h
index 23c92f3c61cfc5bdbc217d9123fe99847935110b..4bbbac326d406d27214e4636a6a304f1a8a6a353 100644
--- a/test/cctest/wasm/wasm-run-utils.h
+++ b/test/cctest/wasm/wasm-run-utils.h
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <string.h>
+#include "src/base/accounting-allocator.h"
#include "src/base/utils/random-number-generator.h"
#include "src/compiler/graph-visualizer.h"
@@ -20,6 +21,7 @@
#include "src/compiler/zone-pool.h"
#include "src/wasm/ast-decoder.h"
+#include "src/wasm/wasm-interpreter.h"
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-module.h"
@@ -40,6 +42,8 @@
static const uint32_t kMaxFunctions = 10;
+enum WasmExecutionMode { kExecuteInterpreted, kExecuteCompiled };
+
// TODO(titzer): check traps more robustly in tests.
// Currently, in tests, we just return 0xdeadbeef from the function in which
// the trap occurs if the runtime context is not available to throw a JavaScript
@@ -72,10 +76,14 @@ const uint32_t kMaxGlobalsSize = 128;
// {WasmModuleInstance}.
class TestingModule : public ModuleEnv {
public:
- TestingModule()
- : instance_(&module_),
+ explicit TestingModule(WasmExecutionMode mode = kExecuteCompiled)
+ : execution_mode_(mode),
+ instance_(&module_),
isolate_(CcTest::InitIsolateOnce()),
- global_offset(0) {
+ global_offset(0),
+ interpreter_(mode == kExecuteInterpreted
+ ? new WasmInterpreter(&instance_, &allocator_)
+ : nullptr) {
module = &module_;
instance = &instance_;
instance->module = &module_;
@@ -92,6 +100,7 @@ class TestingModule : public ModuleEnv {
if (instance->mem_start) {
free(instance->mem_start);
}
+ if (interpreter_) delete interpreter_;
}
byte* AddMemory(size_t size) {
@@ -172,6 +181,11 @@ class TestingModule : public ModuleEnv {
uint32_t index = static_cast<uint32_t>(module->functions.size());
module_.functions.push_back({sig, index, 0, 0, 0, 0, 0, false});
instance->function_code.push_back(code);
+ if (interpreter_) {
+ const WasmFunction* function = &module->functions.back();
+ int interpreter_index = interpreter_->AddFunctionForTesting(function);
+ CHECK_EQ(index, static_cast<uint32_t>(interpreter_index));
+ }
DCHECK_LT(index, kMaxFunctions); // limited for testing.
return index;
}
@@ -225,12 +239,18 @@ class TestingModule : public ModuleEnv {
}
WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; }
+ WasmInterpreter* interpreter() { return interpreter_; }
+ WasmExecutionMode execution_mode() { return execution_mode_; }
+
private:
+ WasmExecutionMode execution_mode_;
WasmModule module_;
WasmModuleInstance instance_;
Isolate* isolate_;
+ v8::base::AccountingAllocator allocator_;
uint32_t global_offset;
V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data.
+ WasmInterpreter* interpreter_;
const WasmGlobal* AddGlobal(MachineType mem_type) {
byte size = WasmOpcodes::MemSize(mem_type);
@@ -409,14 +429,41 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
// A helper for compiling WASM functions for testing. This class can create a
// standalone function if {module} is NULL or a function within a
// {TestingModule}. It contains the internal state for compilation (i.e.
-// TurboFan graph) and, later, interpretation.
+// TurboFan graph) and interpretation (by adding to the interpreter manually).
class WasmFunctionCompiler : public HandleAndZoneScope,
private GraphAndBuilders {
public:
explicit WasmFunctionCompiler(
+ FunctionSig* sig, WasmExecutionMode mode,
+ Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
+ : GraphAndBuilders(main_zone()),
+ execution_mode_(mode),
+ jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
+ nullptr, this->machine()),
+ sig(sig),
+ descriptor_(nullptr),
+ testing_module_(nullptr),
+ debug_name_(debug_name),
+ local_decls(main_zone(), sig),
+ source_position_table_(this->graph()),
+ interpreter_(nullptr) {
+ // Create our own function.
+ function_ = new WasmFunction();
+ function_->sig = sig;
+ function_->func_index = 0;
+ function_->sig_index = 0;
+ if (mode == kExecuteInterpreted) {
+ interpreter_ = new WasmInterpreter(nullptr, zone()->allocator());
+ int index = interpreter_->AddFunctionForTesting(function_);
+ CHECK_EQ(0, index);
+ }
+ }
+
+ explicit WasmFunctionCompiler(
FunctionSig* sig, TestingModule* module,
Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
: GraphAndBuilders(main_zone()),
+ execution_mode_(module->execution_mode()),
jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
nullptr, this->machine()),
sig(sig),
@@ -424,23 +471,20 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
testing_module_(module),
debug_name_(debug_name),
local_decls(main_zone(), sig),
- source_position_table_(this->graph()) {
- if (module) {
- // Get a new function from the testing module.
- function_ = nullptr;
- function_index_ = module->AddFunction(sig, Handle<Code>::null());
- } else {
- // Create our own function.
- function_ = new WasmFunction();
- function_->sig = sig;
- function_index_ = 0;
- }
+ source_position_table_(this->graph()),
+ interpreter_(module->interpreter()) {
+ // Get a new function from the testing module.
+ int index = module->AddFunction(sig, Handle<Code>::null());
+ function_ = testing_module_->GetFunctionAt(index);
}
~WasmFunctionCompiler() {
- if (function_) delete function_;
+ if (testing_module_) return; // testing module owns the below things.
+ delete function_;
+ if (interpreter_) delete interpreter_;
}
+ WasmExecutionMode execution_mode_;
JSGraph jsgraph;
FunctionSig* sig;
// The call descriptor is initialized when the function is compiled.
@@ -448,9 +492,9 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
TestingModule* testing_module_;
Vector<const char> debug_name_;
WasmFunction* function_;
- int function_index_;
LocalDeclEncoder local_decls;
SourcePositionTable source_position_table_;
+ WasmInterpreter* interpreter_;
Isolate* isolate() { return main_isolate(); }
Graph* graph() const { return main_graph_; }
@@ -463,13 +507,17 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
}
}
CallDescriptor* descriptor() { return descriptor_; }
+ uint32_t function_index() { return function_->func_index; }
void Build(const byte* start, const byte* end) {
// Build the TurboFan graph.
- local_decls.Prepend(&start, &end);
+ local_decls.Prepend(main_zone(), &start, &end);
TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig,
&source_position_table_, start, end);
- delete[] start;
+ if (interpreter_) {
+ // Add the code to the interpreter.
+ CHECK(interpreter_->SetFunctionCodeForTesting(function_, start, end));
+ }
}
byte AllocateLocal(LocalType type) {
@@ -495,13 +543,13 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
Handle<Code> code = info.code();
- // Length is always 2, since usually <wasm_obj, func_index> is stored in the
- // deopt data. Here, we only store the function index.
+ // Length is always 2, since usually <wasm_obj, func_index> is stored in
+ // the deopt data. Here, we only store the function index.
DCHECK(code->deoptimization_data() == nullptr ||
code->deoptimization_data()->length() == 0);
Handle<FixedArray> deopt_data =
isolate()->factory()->NewFixedArray(2, TENURED);
- deopt_data->set(1, Smi::FromInt(function_index_));
+ deopt_data->set(1, Smi::FromInt(static_cast<int>(function_index())));
deopt_data->set_length(2);
code->set_deoptimization_data(*deopt_data);
@@ -517,15 +565,10 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
uint32_t CompileAndAdd(uint16_t sig_index = 0) {
CHECK(testing_module_);
- function()->sig_index = sig_index;
+ function_->sig_index = sig_index;
Handle<Code> code = Compile();
- testing_module_->SetFunctionCode(function_index_, code);
- return static_cast<uint32_t>(function_index_);
- }
-
- WasmFunction* function() {
- if (function_) return function_;
- return testing_module_->GetFunctionAt(function_index_);
+ testing_module_->SetFunctionCode(function_index(), code);
+ return function_index();
}
// Set the context, such that e.g. runtime functions can be called.
@@ -544,7 +587,8 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
template <typename ReturnType>
class WasmRunner {
public:
- WasmRunner(MachineType p0 = MachineType::None(),
+ WasmRunner(WasmExecutionMode execution_mode,
+ MachineType p0 = MachineType::None(),
MachineType p1 = MachineType::None(),
MachineType p2 = MachineType::None(),
MachineType p3 = MachineType::None())
@@ -552,7 +596,7 @@ class WasmRunner {
compiled_(false),
signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
GetParameterCount(p0, p1, p2, p3), storage_),
- compiler_(&signature_, nullptr) {
+ compiler_(&signature_, execution_mode) {
InitSigStorage(p0, p1, p2, p3);
}
@@ -595,51 +639,102 @@ class WasmRunner {
void Build(const byte* start, const byte* end) {
CHECK(!compiled_);
compiled_ = true;
-
- // Build the TF graph within the compiler.
compiler_.Build(start, end);
- // Generate code.
- Handle<Code> code = compiler_.Compile();
- if (compiler_.testing_module_) {
- // Update the table of function code in the module.
- compiler_.testing_module_->SetFunctionCode(compiler_.function_index_,
- code);
- }
+ if (!interpret()) {
+ // Compile machine code and install it into the module.
+ Handle<Code> code = compiler_.Compile();
+
+ if (compiler_.testing_module_) {
+ // Update the table of function code in the module.
+ compiler_.testing_module_->SetFunctionCode(
+ compiler_.function_->func_index, code);
+ }
- wrapper_.SetInnerCode(code);
+ wrapper_.SetInnerCode(code);
+ }
}
- ReturnType Call() { return Call(0, 0, 0, 0); }
+ ReturnType Call() {
+ if (interpret()) {
+ return CallInterpreter(Vector<WasmVal>(nullptr, 0));
+ } else {
+ return Call(0, 0, 0, 0);
+ }
+ }
template <typename P0>
ReturnType Call(P0 p0) {
- return Call(p0, 0, 0, 0);
+ if (interpret()) {
+ WasmVal args[] = {WasmVal(p0)};
+ return CallInterpreter(ArrayVector(args));
+ } else {
+ return Call(p0, 0, 0, 0);
+ }
}
template <typename P0, typename P1>
ReturnType Call(P0 p0, P1 p1) {
- return Call(p0, p1, 0, 0);
+ if (interpret()) {
+ WasmVal args[] = {WasmVal(p0), WasmVal(p1)};
+ return CallInterpreter(ArrayVector(args));
+ } else {
+ return Call(p0, p1, 0, 0);
+ }
}
template <typename P0, typename P1, typename P2>
ReturnType Call(P0 p0, P1 p1, P2 p2) {
- return Call(p0, p1, p2, 0);
+ if (interpret()) {
+ WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2)};
+ return CallInterpreter(ArrayVector(args));
+ } else {
+ return Call(p0, p1, p2, 0);
+ }
}
template <typename P0, typename P1, typename P2, typename P3>
ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
- CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
- wrapper_.GetWrapperCode(), wrapper_.signature());
- ReturnType return_value;
- int32_t result = runner.Call<void*, void*, void*, void*, void*>(
- &p0, &p1, &p2, &p3, &return_value);
- CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
- return return_value;
+ if (interpret()) {
+ WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2), WasmVal(p3)};
+ return CallInterpreter(ArrayVector(args));
+ } else {
+ CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
+ wrapper_.GetWrapperCode(),
+ wrapper_.signature());
+ ReturnType return_value;
+ int32_t result = runner.Call<void*, void*, void*, void*, void*>(
+ &p0, &p1, &p2, &p3, &return_value);
+ CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
+ return return_value;
+ }
+ }
+
+ ReturnType CallInterpreter(Vector<WasmVal> args) {
+ CHECK_EQ(args.length(),
+ static_cast<int>(compiler_.function_->sig->parameter_count()));
+ WasmInterpreter::Thread& thread = interpreter()->GetThread(0);
+ thread.Reset();
+ thread.PushFrame(compiler_.function_, args.start());
+ if (thread.Run() == WasmInterpreter::FINISHED) {
+ WasmVal val = thread.GetReturnValue();
+ return val.to<ReturnType>();
+ } else if (thread.state() == WasmInterpreter::TRAPPED) {
+ // TODO(titzer): return the correct trap code
+ int64_t result = 0xdeadbeefdeadbeef;
+ return static_cast<ReturnType>(result);
+ } else {
+ // TODO(titzer): falling off end
+ ReturnType val = 0;
+ return val;
+ }
}
byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); }
+ WasmFunction* function() { return compiler_.function_; }
+ WasmInterpreter* interpreter() { return compiler_.interpreter_; }
+
protected:
v8::base::AccountingAllocator allocator_;
Zone zone;
@@ -649,6 +744,8 @@ class WasmRunner {
WasmFunctionCompiler compiler_;
WasmFunctionWrapper<ReturnType> wrapper_;
+ bool interpret() { return compiler_.execution_mode_ == kExecuteInterpreted; }
+
static size_t GetParameterCount(MachineType p0, MachineType p1,
MachineType p2, MachineType p3) {
if (p0 == MachineType::None()) return 0;
@@ -663,10 +760,11 @@ class WasmRunner {
// Currently only supports compiled tests, but a future
// RunWasmInterpreted_##name version will allow each test to also run in the
// interpreter.
-#define WASM_EXEC_TEST(name) \
- void RunWasm_##name(); \
- TEST(RunWasmCompiled_##name) { RunWasm_##name(); } \
- void RunWasm_##name()
+#define WASM_EXEC_TEST(name) \
+ void RunWasm_##name(WasmExecutionMode execution_mode); \
+ TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \
+ TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \
+ void RunWasm_##name(WasmExecutionMode execution_mode)
} // namespace
« no previous file with comments | « test/cctest/wasm/test-run-wasm-interpreter.cc ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698