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

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

Issue 2551043002: [wasm] Make WasmRunner the central test structure (Closed)
Patch Set: Make DoCall return void - quickfix Created 4 years 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-wasm-trap-position.cc ('k') | no next file » | 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 ed8e893a7fcf7921340766d8ac0352e35aa704a3..13f37738e649ba9d4197eb79e12ea48c9ff3b959 100644
--- a/test/cctest/wasm/wasm-run-utils.h
+++ b/test/cctest/wasm/wasm-run-utils.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <array>
#include <memory>
#include "src/base/utils/random-number-generator.h"
@@ -51,7 +52,6 @@ enum WasmExecutionMode { kExecuteInterpreted, kExecuteCompiled };
CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
#define CHECK_TRAP(x) CHECK_TRAP32(x)
-#define WASM_RUNNER_MAX_NUM_PARAMETERS 4
#define WASM_WRAPPER_RETURN_VALUE 8754
#define BUILD(r, ...) \
@@ -73,7 +73,7 @@ const uint32_t kMaxGlobalsSize = 128;
// {WasmInstance}.
class TestingModule : public ModuleEnv {
public:
- explicit TestingModule(WasmExecutionMode mode = kExecuteCompiled)
+ explicit TestingModule(Zone* zone, WasmExecutionMode mode = kExecuteCompiled)
: ModuleEnv(&module_, &instance_),
execution_mode_(mode),
instance_(&module_),
@@ -83,7 +83,7 @@ class TestingModule : public ModuleEnv {
? new WasmInterpreter(
ModuleBytesEnv(&module_, &instance_,
Vector<const byte>::empty()),
- &allocator_)
+ zone->allocator())
: nullptr) {
instance->module = &module_;
instance->globals_start = global_data;
@@ -104,7 +104,7 @@ class TestingModule : public ModuleEnv {
byte* AddMemory(uint32_t size) {
CHECK_NULL(instance->mem_start);
- CHECK_EQ(0u, instance->mem_size);
+ CHECK_EQ(0, instance->mem_size);
instance->mem_start = reinterpret_cast<byte*>(malloc(size));
CHECK(instance->mem_start);
memset(instance->mem_start, 0, size);
@@ -119,7 +119,8 @@ class TestingModule : public ModuleEnv {
}
template <typename T>
- T* AddGlobal(LocalType type) {
+ T* AddGlobal(
+ LocalType type = WasmOpcodes::LocalTypeFor(MachineTypeForC<T>())) {
const WasmGlobal* global = AddGlobal(type);
return reinterpret_cast<T*>(instance->globals_start + global->offset);
}
@@ -244,6 +245,7 @@ class TestingModule : public ModuleEnv {
}
void PopulateIndirectFunctionTable() {
+ if (execution_mode_ == kExecuteInterpreted) return;
// Initialize the fixed arrays in instance->function_tables.
for (uint32_t i = 0; i < instance->function_tables.size(); i++) {
WasmIndirectFunctionTable& table = module_.function_tables[i];
@@ -262,13 +264,13 @@ class TestingModule : public ModuleEnv {
WasmInterpreter* interpreter() { return interpreter_; }
WasmExecutionMode execution_mode() { return execution_mode_; }
+ Isolate* isolate() { return isolate_; }
private:
WasmExecutionMode execution_mode_;
WasmModule module_;
WasmInstance instance_;
Isolate* isolate_;
- v8::internal::AccountingAllocator allocator_;
uint32_t global_offset;
V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data.
WasmInterpreter* interpreter_;
@@ -314,36 +316,29 @@ inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module,
}
}
-template <typename ReturnType>
-class WasmFunctionWrapper : public HandleAndZoneScope,
- private GraphAndBuilders {
+class WasmFunctionWrapper : private GraphAndBuilders {
public:
- WasmFunctionWrapper()
- : GraphAndBuilders(main_zone()),
- inner_code_node_(nullptr),
- signature_(nullptr) {
+ explicit WasmFunctionWrapper(Zone* zone, int num_params)
+ : GraphAndBuilders(zone), inner_code_node_(nullptr), signature_(nullptr) {
// One additional parameter for the pointer to the return value memory.
- Signature<MachineType>::Builder sig_builder(
- zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
+ Signature<MachineType>::Builder sig_builder(zone, 1, num_params + 1);
sig_builder.AddReturn(MachineType::Int32());
- for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
+ for (int i = 0; i < num_params + 1; i++) {
sig_builder.AddParam(MachineType::Pointer());
}
signature_ = sig_builder.Build();
}
- void Init(CallDescriptor* descriptor, MachineType p0 = MachineType::None(),
- MachineType p1 = MachineType::None(),
- MachineType p2 = MachineType::None(),
- MachineType p3 = MachineType::None()) {
- // Create the TF graph for the wrapper. The wrapper always takes four
- // pointers as parameters, but may not pass the values of all pointers to
- // the actual test function.
+ void Init(CallDescriptor* descriptor, MachineType return_type,
+ Vector<MachineType> param_types) {
+ DCHECK_NOT_NULL(descriptor);
+ DCHECK_EQ(signature_->parameter_count(), param_types.length() + 1);
+
+ // Create the TF graph for the wrapper.
// Function, effect, and control.
- Node** parameters =
- zone()->template NewArray<Node*>(WASM_RUNNER_MAX_NUM_PARAMETERS + 3);
+ Node** parameters = zone()->NewArray<Node*>(param_types.length() + 3);
graph()->SetStart(graph()->NewNode(common()->Start(6)));
Node* effect = graph()->start();
int parameter_count = 0;
@@ -352,34 +347,12 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
inner_code_node_ = graph()->NewNode(common()->Int32Constant(0));
parameters[parameter_count++] = inner_code_node_;
- if (p0 != MachineType::None()) {
- parameters[parameter_count] = graph()->NewNode(
- machine()->Load(p0),
- graph()->NewNode(common()->Parameter(0), graph()->start()),
- graph()->NewNode(common()->Int32Constant(0)), effect,
- graph()->start());
- effect = parameters[parameter_count++];
- }
- if (p1 != MachineType::None()) {
+ int param_idx = 0;
+ for (MachineType t : param_types) {
+ DCHECK_NE(MachineType::None(), t);
parameters[parameter_count] = graph()->NewNode(
- machine()->Load(p1),
- graph()->NewNode(common()->Parameter(1), graph()->start()),
- graph()->NewNode(common()->Int32Constant(0)), effect,
- graph()->start());
- effect = parameters[parameter_count++];
- }
- if (p2 != MachineType::None()) {
- parameters[parameter_count] = graph()->NewNode(
- machine()->Load(p2),
- graph()->NewNode(common()->Parameter(2), graph()->start()),
- graph()->NewNode(common()->Int32Constant(0)), effect,
- graph()->start());
- effect = parameters[parameter_count++];
- }
- if (p3 != MachineType::None()) {
- parameters[parameter_count] = graph()->NewNode(
- machine()->Load(p3),
- graph()->NewNode(common()->Parameter(3), graph()->start()),
+ machine()->Load(t),
+ graph()->NewNode(common()->Parameter(param_idx++), graph()->start()),
graph()->NewNode(common()->Int32Constant(0)), effect,
graph()->start());
effect = parameters[parameter_count++];
@@ -390,14 +363,15 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
Node* call = graph()->NewNode(common()->Call(descriptor), parameter_count,
parameters);
- effect = graph()->NewNode(
- machine()->Store(
- StoreRepresentation(MachineTypeForC<ReturnType>().representation(),
- WriteBarrierKind::kNoWriteBarrier)),
- graph()->NewNode(common()->Parameter(WASM_RUNNER_MAX_NUM_PARAMETERS),
- graph()->start()),
- graph()->NewNode(common()->Int32Constant(0)), call, effect,
- graph()->start());
+ if (!return_type.IsNone()) {
+ effect = graph()->NewNode(
+ machine()->Store(StoreRepresentation(
+ return_type.representation(), WriteBarrierKind::kNoWriteBarrier)),
+ graph()->NewNode(common()->Parameter(param_types.length()),
+ graph()->start()),
+ graph()->NewNode(common()->Int32Constant(0)), call, effect,
+ graph()->start());
+ }
Node* zero = graph()->NewNode(common()->Int32Constant(0));
Node* r = graph()->NewNode(
common()->Return(), zero,
@@ -406,6 +380,15 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
graph()->SetEnd(graph()->NewNode(common()->End(2), r, graph()->start()));
}
+ template <typename ReturnType, typename... ParamTypes>
+ void Init(CallDescriptor* descriptor) {
+ std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{
+ {MachineTypeForC<ParamTypes>()...}};
+ Vector<MachineType> param_vec(param_machine_types.data(),
+ param_machine_types.size());
+ Init(descriptor, MachineTypeForC<ReturnType>(), param_vec);
+ }
+
void SetInnerCode(Handle<Code> code_handle) {
NodeProperties::ChangeOp(inner_code_node_,
common()->HeapConstant(code_handle));
@@ -419,12 +402,13 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
Linkage::GetSimplifiedCDescriptor(zone(), signature_, true);
if (kPointerSize == 4) {
+ size_t num_params = signature_->parameter_count();
// One additional parameter for the pointer of the return value.
- Signature<MachineRepresentation>::Builder rep_builder(
- zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
+ Signature<MachineRepresentation>::Builder rep_builder(zone(), 1,
+ num_params + 1);
rep_builder.AddReturn(MachineRepresentation::kWord32);
- for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
+ for (size_t i = 0; i < num_params + 1; i++) {
rep_builder.AddParam(MachineRepresentation::kWord32);
}
Int64Lowering r(graph(), machine(), common(), zone(),
@@ -456,99 +440,37 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
Signature<MachineType>* signature_;
};
-// 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 interpretation (by adding to the interpreter manually).
-class WasmFunctionCompiler : public HandleAndZoneScope,
- private GraphAndBuilders {
+// A helper for compiling WASM functions for testing.
+// It contains the internal state for compilation (i.e. TurboFan graph) and
+// interpretation (by adding to the interpreter manually).
+class WasmFunctionCompiler : 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) {
- ModuleBytesEnv empty_env(nullptr, nullptr, Vector<const byte>::empty());
- interpreter_ = new WasmInterpreter(empty_env, 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),
- descriptor_(nullptr),
- testing_module_(module),
- debug_name_(debug_name),
- local_decls(main_zone(), sig),
- 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 (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.
- CallDescriptor* descriptor_;
- TestingModule* testing_module_;
- Vector<const char> debug_name_;
- WasmFunction* function_;
- LocalDeclEncoder local_decls;
- SourcePositionTable source_position_table_;
- WasmInterpreter* interpreter_;
-
- Isolate* isolate() { return main_isolate(); }
+ Isolate* isolate() { return testing_module_->isolate(); }
Graph* graph() const { return main_graph_; }
Zone* zone() const { return graph()->zone(); }
CommonOperatorBuilder* common() { return &main_common_; }
MachineOperatorBuilder* machine() { return &main_machine_; }
- void InitializeDescriptor() {
+ CallDescriptor* descriptor() {
if (descriptor_ == nullptr) {
- descriptor_ = testing_module_->GetWasmCallDescriptor(main_zone(), sig);
+ descriptor_ = testing_module_->GetWasmCallDescriptor(zone(), sig);
}
+ return descriptor_;
}
- 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(main_zone(), &start, &end);
- TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig,
- &source_position_table_, start, end);
+ local_decls.Prepend(zone(), &start, &end);
if (interpreter_) {
// Add the code to the interpreter.
CHECK(interpreter_->SetFunctionCodeForTesting(function_, start, end));
+ return;
}
+
+ // Build the TurboFan graph.
+ TestBuildingGraph(zone(), &jsgraph, testing_module_, sig,
+ &source_position_table_, start, end);
+ Handle<Code> code = Compile();
+ testing_module_->SetFunctionCode(function_index(), code);
}
byte AllocateLocal(LocalType type) {
@@ -558,13 +480,33 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
return result;
}
+ void SetSigIndex(int sig_index) { function_->sig_index = sig_index; }
+
+ private:
+ friend class WasmRunnerBase;
+
+ explicit WasmFunctionCompiler(Zone* zone, FunctionSig* sig,
+ TestingModule* module)
+ : GraphAndBuilders(zone),
+ jsgraph(module->isolate(), this->graph(), this->common(), nullptr,
+ nullptr, this->machine()),
+ sig(sig),
+ descriptor_(nullptr),
+ testing_module_(module),
+ local_decls(zone, sig),
+ 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);
+ }
+
Handle<Code> Compile() {
- InitializeDescriptor();
- CallDescriptor* desc = descriptor_;
+ CallDescriptor* desc = descriptor();
if (kPointerSize == 4) {
desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
}
- CompilationInfo info(debug_name_, this->isolate(), this->zone(),
+ CompilationInfo info(CStrVector("wasm"), this->isolate(), this->zone(),
Code::ComputeFlags(Code::WASM_FUNCTION));
std::unique_ptr<CompilationJob> job(Pipeline::NewWasmCompilationJob(
&info, &jsgraph, desc, &source_position_table_, nullptr));
@@ -594,82 +536,26 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
return code;
}
- uint32_t CompileAndAdd(uint16_t sig_index = 0) {
- CHECK(testing_module_);
- function_->sig_index = sig_index;
- Handle<Code> code = Compile();
- testing_module_->SetFunctionCode(function_index(), code);
- return function_index();
- }
-
- // Set the context, such that e.g. runtime functions can be called.
- void SetModuleContext() {
- if (!testing_module_->instance->context.is_null()) {
- CHECK(testing_module_->instance->context.is_identical_to(
- main_isolate()->native_context()));
- return;
- }
- testing_module_->instance->context = main_isolate()->native_context();
- }
-};
-
-template <typename ReturnType>
-union ReturnTypeUnion {
- ReturnType value;
- uint64_t trap;
+ JSGraph jsgraph;
+ FunctionSig* sig;
+ // The call descriptor is initialized when the function is compiled.
+ CallDescriptor* descriptor_;
+ TestingModule* testing_module_;
+ Vector<const char> debug_name_;
+ WasmFunction* function_;
+ LocalDeclEncoder local_decls;
+ SourcePositionTable source_position_table_;
+ WasmInterpreter* interpreter_;
};
-// A helper class to build graphs from Wasm bytecode, generate machine
+// A helper class to build a module around Wasm bytecode, generate machine
// code, and run that code.
-template <typename ReturnType>
-class WasmRunner {
+class WasmRunnerBase : public HandleAndZoneScope {
public:
- WasmRunner(WasmExecutionMode execution_mode,
- MachineType p0 = MachineType::None(),
- MachineType p1 = MachineType::None(),
- MachineType p2 = MachineType::None(),
- MachineType p3 = MachineType::None())
- : zone(&allocator_, ZONE_NAME),
- compiled_(false),
- signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
- GetParameterCount(p0, p1, p2, p3), storage_),
- compiler_(&signature_, execution_mode) {
- InitSigStorage(p0, p1, p2, p3);
- }
-
- WasmRunner(TestingModule* module, MachineType p0 = MachineType::None(),
- MachineType p1 = MachineType::None(),
- MachineType p2 = MachineType::None(),
- MachineType p3 = MachineType::None())
- : zone(&allocator_, ZONE_NAME),
- compiled_(false),
- signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
- GetParameterCount(p0, p1, p2, p3), storage_),
- compiler_(&signature_, module),
- possible_nondeterminism_(false) {
- DCHECK(module);
- InitSigStorage(p0, p1, p2, p3);
- }
-
- void InitSigStorage(MachineType p0, MachineType p1, MachineType p2,
- MachineType p3) {
- int index = 0;
- MachineType ret = MachineTypeForC<ReturnType>();
- if (ret != MachineType::None()) {
- storage_[index++] = WasmOpcodes::LocalTypeFor(ret);
- }
- if (p0 != MachineType::None())
- storage_[index++] = WasmOpcodes::LocalTypeFor(p0);
- if (p1 != MachineType::None())
- storage_[index++] = WasmOpcodes::LocalTypeFor(p1);
- if (p2 != MachineType::None())
- storage_[index++] = WasmOpcodes::LocalTypeFor(p2);
- if (p3 != MachineType::None())
- storage_[index++] = WasmOpcodes::LocalTypeFor(p3);
-
- compiler_.InitializeDescriptor();
- wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3);
- }
+ explicit WasmRunnerBase(WasmExecutionMode execution_mode, int num_params)
+ : zone_(&allocator_, ZONE_NAME),
+ module_(&zone_, execution_mode),
+ wrapper_(&zone_, num_params) {}
// Builds a graph from the given Wasm code and generates the machine
// code and call wrapper for that graph. This method must not be called
@@ -677,102 +563,122 @@ class WasmRunner {
void Build(const byte* start, const byte* end) {
CHECK(!compiled_);
compiled_ = true;
- compiler_.Build(start, end);
-
- if (!interpret()) {
- // Compile machine code and install it into the module.
- Handle<Code> code = compiler_.Compile();
+ functions_[0]->Build(start, end);
+ }
- if (compiler_.testing_module_) {
- // Update the table of function code in the module.
- compiler_.testing_module_->SetFunctionCode(
- compiler_.function_->func_index, code);
- }
+ // Resets the state for building the next function.
+ // The main function called will always be the first function.
+ template <typename ReturnType, typename... ParamTypes>
+ WasmFunctionCompiler& NewFunction() {
+ return NewFunction(CreateSig<ReturnType, ParamTypes...>());
+ }
- wrapper_.SetInnerCode(code);
- }
+ // Resets the state for building the next function.
+ // The main function called will be the last generated function.
+ // Returns the index of the previously built function.
+ WasmFunctionCompiler& NewFunction(FunctionSig* sig) {
+ functions_.emplace_back(new WasmFunctionCompiler(&zone_, sig, &module_));
+ return *functions_.back();
}
- ReturnType Call() {
- if (interpret()) {
- return CallInterpreter(Vector<WasmVal>(nullptr, 0));
- } else {
- return Call(0, 0, 0, 0);
- }
+ byte AllocateLocal(LocalType type) {
+ return functions_[0]->AllocateLocal(type);
}
- template <typename P0>
- ReturnType Call(P0 p0) {
- if (interpret()) {
- WasmVal args[] = {WasmVal(p0)};
- return CallInterpreter(ArrayVector(args));
- } else {
- return Call(p0, 0, 0, 0);
+ WasmFunction* function() { return functions_[0]->function_; }
+ WasmInterpreter* interpreter() { return functions_[0]->interpreter_; }
+ bool possible_nondeterminism() { return possible_nondeterminism_; }
+ TestingModule& module() { return module_; }
+ Zone* zone() { return &zone_; }
+
+ // Set the context, such that e.g. runtime functions can be called.
+ void SetModuleContext() {
+ if (!module_.instance->context.is_null()) {
+ CHECK(module_.instance->context.is_identical_to(
+ main_isolate()->native_context()));
+ return;
}
+ module_.instance->context = main_isolate()->native_context();
}
- template <typename P0, typename P1>
- ReturnType Call(P0 p0, P1 p1) {
- if (interpret()) {
- WasmVal args[] = {WasmVal(p0), WasmVal(p1)};
- return CallInterpreter(ArrayVector(args));
- } else {
- return Call(p0, p1, 0, 0);
+ private:
+ FunctionSig* CreateSig(MachineType return_type,
+ Vector<MachineType> param_types) {
+ int return_count = return_type.IsNone() ? 0 : 1;
+ int param_count = param_types.length();
+
+ // Allocate storage array in zone.
+ LocalType* sig_types =
+ zone_.NewArray<LocalType>(return_count + param_count);
+
+ // Convert machine types to local types, and check that there are no
+ // MachineType::None()'s in the parameters.
+ int idx = 0;
+ if (return_count) sig_types[idx++] = WasmOpcodes::LocalTypeFor(return_type);
+ for (MachineType param : param_types) {
+ CHECK_NE(MachineType::None(), param);
+ sig_types[idx++] = WasmOpcodes::LocalTypeFor(param);
}
+ return new (&zone_) FunctionSig(return_count, param_count, sig_types);
}
- template <typename P0, typename P1, typename P2>
- ReturnType Call(P0 p0, P1 p1, P2 p2) {
- if (interpret()) {
- WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2)};
- return CallInterpreter(ArrayVector(args));
- } else {
- return Call(p0, p1, p2, 0);
- }
+ template <typename ReturnType, typename... ParamTypes>
+ FunctionSig* CreateSig() {
+ std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{
+ {MachineTypeForC<ParamTypes>()...}};
+ Vector<MachineType> param_vec(param_machine_types.data(),
+ param_machine_types.size());
+ return CreateSig(MachineTypeForC<ReturnType>(), param_vec);
}
+ protected:
+ v8::internal::AccountingAllocator allocator_;
+ Zone zone_;
+ TestingModule module_;
+ std::vector<std::unique_ptr<WasmFunctionCompiler>> functions_;
+ WasmFunctionWrapper wrapper_;
+ bool compiled_ = false;
+ bool possible_nondeterminism_ = false;
+
+ bool interpret() { return module_.execution_mode() == kExecuteInterpreted; }
+
+ public:
+ // This field has to be static. Otherwise, gcc complains about the using in
+ // the lambda context below.
static jmp_buf jump_buffer;
- static int jump_value;
- static ReturnTypeUnion<ReturnType> return_value;
-
- template <typename P0, typename P1, typename P2, typename P3>
- void DoCall(P0 p0, P1 p1, P2 p2, P3 p3) {
- auto trap_callback = []() {
- WasmRunner<ReturnType>::return_value.trap = 0xdeadbeefdeadbeef;
- longjmp(WasmRunner<ReturnType>::jump_buffer, 1);
- };
- set_trap_callback_for_testing(trap_callback);
- CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
- wrapper_.GetWrapperCode(), wrapper_.signature());
+};
- int32_t result = runner.Call<void*, void*, void*, void*, void*>(
- &p0, &p1, &p2, &p3, &WasmRunner<ReturnType>::return_value.value);
- CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
+template <typename ReturnType, typename... ParamTypes>
+class WasmRunner : public WasmRunnerBase {
+ public:
+ explicit WasmRunner(WasmExecutionMode execution_mode)
+ : WasmRunnerBase(execution_mode, sizeof...(ParamTypes)) {
+ NewFunction<ReturnType, ParamTypes...>();
+ if (!interpret()) {
+ wrapper_.Init<ReturnType, ParamTypes...>(functions_[0]->descriptor());
+ }
}
- template <typename P0, typename P1, typename P2, typename P3>
- ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
- if (interpret()) {
- WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2), WasmVal(p3)};
- return CallInterpreter(ArrayVector(args));
- } else {
- // Use setjmp/longjmp to deal with traps in WebAssembly code.
- WasmRunner<ReturnType>::jump_value =
- setjmp(WasmRunner<ReturnType>::jump_buffer);
- if (!WasmRunner<ReturnType>::jump_value) {
- DoCall(p0, p1, p2, p3);
- }
- set_trap_callback_for_testing(nullptr);
- return WasmRunner<ReturnType>::return_value.value;
- }
+ ReturnType Call(ParamTypes... p) {
+ DCHECK(compiled_);
+ if (interpret()) return CallInterpreter(p...);
+
+ // Use setjmp/longjmp to deal with traps in WebAssembly code.
+ // Make the return value volatile, to give defined semantics if accessed
+ // after setjmp.
+ volatile ReturnType return_value =
+ static_cast<ReturnType>(0xdeadbeefdeadbeef);
+ int jump_value = setjmp(WasmRunnerBase::jump_buffer);
+ // jump_value == 0 --> first return; jump_value == 1 --> longjmp happened.
+ if (!jump_value) DoCall(&return_value, p...);
+ return return_value;
}
- ReturnType CallInterpreter(Vector<WasmVal> args) {
- CHECK_EQ(args.length(),
- static_cast<int>(compiler_.function_->sig->parameter_count()));
+ ReturnType CallInterpreter(ParamTypes... p) {
WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
thread->Reset();
- thread->PushFrame(compiler_.function_, args.start());
+ std::array<WasmVal, sizeof...(p)> args{{WasmVal(p)...}};
+ thread->PushFrame(function(), args.data());
if (thread->Run() == WasmInterpreter::FINISHED) {
WasmVal val = thread->GetReturnValue();
possible_nondeterminism_ |= thread->PossibleNondeterminism();
@@ -783,45 +689,35 @@ class WasmRunner {
return static_cast<ReturnType>(result);
} else {
// TODO(titzer): falling off end
- ReturnType val = 0;
- return val;
+ return ReturnType{0};
}
}
- byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); }
-
- WasmFunction* function() { return compiler_.function_; }
- WasmInterpreter* interpreter() { return compiler_.interpreter_; }
- bool possible_nondeterminism() { return possible_nondeterminism_; }
+ private:
+ // Don't inline this function. The setjmp above should be followed immediately
+ // by a call.
+ V8_NOINLINE void DoCall(volatile ReturnType* return_value, ParamTypes... p) {
+ auto trap_callback = []() -> void {
+ set_trap_callback_for_testing(nullptr);
+ longjmp(WasmRunnerBase::jump_buffer, 1);
+ };
+ set_trap_callback_for_testing(trap_callback);
- protected:
- v8::internal::AccountingAllocator allocator_;
- Zone zone;
- bool compiled_;
- LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS];
- FunctionSig signature_;
- WasmFunctionCompiler compiler_;
- WasmFunctionWrapper<ReturnType> wrapper_;
- bool possible_nondeterminism_;
-
- 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;
- if (p1 == MachineType::None()) return 1;
- if (p2 == MachineType::None()) return 2;
- if (p3 == MachineType::None()) return 3;
- return 4;
+ wrapper_.SetInnerCode(
+ module_.GetFunctionCode(functions_[0]->function_index()));
+ CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
+ wrapper_.GetWrapperCode(), wrapper_.signature());
+ ReturnType return_value_local;
+ int32_t result = runner.Call(static_cast<void*>(&p)...,
+ static_cast<void*>(&return_value_local));
+ *return_value = return_value_local;
+ // If we arrive here, no trap happened.
+ CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
}
};
-template <typename ReturnType>
-jmp_buf WasmRunner<ReturnType>::jump_buffer;
-template <typename ReturnType>
-int WasmRunner<ReturnType>::jump_value;
-template <typename ReturnType>
-ReturnTypeUnion<ReturnType> WasmRunner<ReturnType>::return_value;
+// Declare static variable.
+jmp_buf WasmRunnerBase::jump_buffer;
// A macro to define tests that run in different engine configurations.
#define WASM_EXEC_TEST(name) \
« no previous file with comments | « test/cctest/wasm/test-wasm-trap-position.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698