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

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

Issue 2583543002: Revert of [wasm] Make WasmRunner the central test structure (Closed)
Patch Set: 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 e2b8d057a9625d56afee3b029bd16343a03e72bf..ed8e893a7fcf7921340766d8ac0352e35aa704a3 100644
--- a/test/cctest/wasm/wasm-run-utils.h
+++ b/test/cctest/wasm/wasm-run-utils.h
@@ -9,7 +9,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include <array>
#include <memory>
#include "src/base/utils/random-number-generator.h"
@@ -52,6 +51,7 @@
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 @@
// {WasmInstance}.
class TestingModule : public ModuleEnv {
public:
- explicit TestingModule(Zone* zone, WasmExecutionMode mode = kExecuteCompiled)
+ explicit TestingModule(WasmExecutionMode mode = kExecuteCompiled)
: ModuleEnv(&module_, &instance_),
execution_mode_(mode),
instance_(&module_),
@@ -83,7 +83,7 @@
? new WasmInterpreter(
ModuleBytesEnv(&module_, &instance_,
Vector<const byte>::empty()),
- zone->allocator())
+ &allocator_)
: nullptr) {
instance->module = &module_;
instance->globals_start = global_data;
@@ -104,7 +104,7 @@
byte* AddMemory(uint32_t size) {
CHECK_NULL(instance->mem_start);
- CHECK_EQ(0, instance->mem_size);
+ CHECK_EQ(0u, instance->mem_size);
instance->mem_start = reinterpret_cast<byte*>(malloc(size));
CHECK(instance->mem_start);
memset(instance->mem_start, 0, size);
@@ -119,8 +119,7 @@
}
template <typename T>
- T* AddGlobal(
- LocalType type = WasmOpcodes::LocalTypeFor(MachineTypeForC<T>())) {
+ T* AddGlobal(LocalType type) {
const WasmGlobal* global = AddGlobal(type);
return reinterpret_cast<T*>(instance->globals_start + global->offset);
}
@@ -245,7 +244,6 @@
}
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];
@@ -264,13 +262,13 @@
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_;
@@ -316,29 +314,36 @@
}
}
-class WasmFunctionWrapper : private GraphAndBuilders {
+template <typename ReturnType>
+class WasmFunctionWrapper : public HandleAndZoneScope,
+ private GraphAndBuilders {
public:
- explicit WasmFunctionWrapper(Zone* zone, int num_params)
- : GraphAndBuilders(zone), inner_code_node_(nullptr), signature_(nullptr) {
+ WasmFunctionWrapper()
+ : GraphAndBuilders(main_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, num_params + 1);
+ Signature<MachineType>::Builder sig_builder(
+ zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
sig_builder.AddReturn(MachineType::Int32());
- for (int i = 0; i < num_params + 1; i++) {
+ for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
sig_builder.AddParam(MachineType::Pointer());
}
signature_ = sig_builder.Build();
}
- 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.
+ 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.
// Function, effect, and control.
- Node** parameters = zone()->NewArray<Node*>(param_types.length() + 3);
+ Node** parameters =
+ zone()->template NewArray<Node*>(WASM_RUNNER_MAX_NUM_PARAMETERS + 3);
graph()->SetStart(graph()->NewNode(common()->Start(6)));
Node* effect = graph()->start();
int parameter_count = 0;
@@ -347,12 +352,34 @@
inner_code_node_ = graph()->NewNode(common()->Int32Constant(0));
parameters[parameter_count++] = inner_code_node_;
- int param_idx = 0;
- for (MachineType t : param_types) {
- DCHECK_NE(MachineType::None(), t);
+ if (p0 != MachineType::None()) {
parameters[parameter_count] = graph()->NewNode(
- machine()->Load(t),
- graph()->NewNode(common()->Parameter(param_idx++), graph()->start()),
+ 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()) {
+ 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()),
graph()->NewNode(common()->Int32Constant(0)), effect,
graph()->start());
effect = parameters[parameter_count++];
@@ -363,15 +390,14 @@
Node* call = graph()->NewNode(common()->Call(descriptor), parameter_count,
parameters);
- 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());
- }
+ 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());
Node* zero = graph()->NewNode(common()->Int32Constant(0));
Node* r = graph()->NewNode(
common()->Return(), zero,
@@ -380,15 +406,6 @@
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));
@@ -402,13 +419,12 @@
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,
- num_params + 1);
+ Signature<MachineRepresentation>::Builder rep_builder(
+ zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
rep_builder.AddReturn(MachineRepresentation::kWord32);
- for (size_t i = 0; i < num_params + 1; i++) {
+ for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
rep_builder.AddParam(MachineRepresentation::kWord32);
}
Int64Lowering r(graph(), machine(), common(), zone(),
@@ -440,60 +456,52 @@
Signature<MachineType>* signature_;
};
-// 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 {
+// 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 {
public:
- 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_; }
- CallDescriptor* descriptor() {
- if (descriptor_ == nullptr) {
- descriptor_ = testing_module_->GetWasmCallDescriptor(zone(), sig);
- }
- return descriptor_;
- }
- uint32_t function_index() { return function_->func_index; }
-
- void Build(const byte* start, const byte* 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) {
- uint32_t index = local_decls.AddLocals(1, type);
- byte result = static_cast<byte>(index);
- DCHECK_EQ(index, result);
- 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,
+ 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),
- local_decls(zone, sig),
+ 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.
@@ -501,41 +509,13 @@
function_ = testing_module_->GetFunctionAt(index);
}
- Handle<Code> Compile() {
- CallDescriptor* desc = descriptor();
- if (kPointerSize == 4) {
- desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
- }
- 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));
- if (job->ExecuteJob() != CompilationJob::SUCCEEDED ||
- job->FinalizeJob() != CompilationJob::SUCCEEDED)
- return Handle<Code>::null();
-
- 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.
- 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(static_cast<int>(function_index())));
- deopt_data->set_length(2);
- code->set_deoptimization_data(*deopt_data);
-
-#ifdef ENABLE_DISASSEMBLER
- if (FLAG_print_opt_code) {
- OFStream os(stdout);
- code->Disassemble("wasm code", os);
- }
-#endif
-
- return code;
- }
-
+ ~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.
@@ -546,16 +526,150 @@
LocalDeclEncoder local_decls;
SourcePositionTable source_position_table_;
WasmInterpreter* interpreter_;
+
+ Isolate* isolate() { return main_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() {
+ if (descriptor_ == nullptr) {
+ descriptor_ = testing_module_->GetWasmCallDescriptor(main_zone(), sig);
+ }
+ }
+ 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);
+ if (interpreter_) {
+ // Add the code to the interpreter.
+ CHECK(interpreter_->SetFunctionCodeForTesting(function_, start, end));
+ }
+ }
+
+ byte AllocateLocal(LocalType type) {
+ uint32_t index = local_decls.AddLocals(1, type);
+ byte result = static_cast<byte>(index);
+ DCHECK_EQ(index, result);
+ return result;
+ }
+
+ Handle<Code> Compile() {
+ InitializeDescriptor();
+ CallDescriptor* desc = descriptor_;
+ if (kPointerSize == 4) {
+ desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
+ }
+ CompilationInfo info(debug_name_, this->isolate(), this->zone(),
+ Code::ComputeFlags(Code::WASM_FUNCTION));
+ std::unique_ptr<CompilationJob> job(Pipeline::NewWasmCompilationJob(
+ &info, &jsgraph, desc, &source_position_table_, nullptr));
+ if (job->ExecuteJob() != CompilationJob::SUCCEEDED ||
+ job->FinalizeJob() != CompilationJob::SUCCEEDED)
+ return Handle<Code>::null();
+
+ 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.
+ 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(static_cast<int>(function_index())));
+ deopt_data->set_length(2);
+ code->set_deoptimization_data(*deopt_data);
+
+#ifdef ENABLE_DISASSEMBLER
+ if (FLAG_print_opt_code) {
+ OFStream os(stdout);
+ code->Disassemble("wasm code", os);
+ }
+#endif
+
+ 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();
+ }
};
-// A helper class to build a module around Wasm bytecode, generate machine
+template <typename ReturnType>
+union ReturnTypeUnion {
+ ReturnType value;
+ uint64_t trap;
+};
+
+// A helper class to build graphs from Wasm bytecode, generate machine
// code, and run that code.
-class WasmRunnerBase : public HandleAndZoneScope {
+template <typename ReturnType>
+class WasmRunner {
public:
- explicit WasmRunnerBase(WasmExecutionMode execution_mode, int num_params)
- : zone_(&allocator_, ZONE_NAME),
- module_(&zone_, execution_mode),
- wrapper_(&zone_, num_params) {}
+ 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);
+ }
// 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
@@ -563,118 +677,102 @@
void Build(const byte* start, const byte* end) {
CHECK(!compiled_);
compiled_ = true;
- functions_[0]->Build(start, end);
- }
-
- // 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...>());
- }
-
- // 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();
- }
-
- byte AllocateLocal(LocalType type) {
- return functions_[0]->AllocateLocal(type);
- }
-
- 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();
- }
-
- 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 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.
+ compiler_.Build(start, end);
+
+ 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);
+ }
+ }
+
+ ReturnType Call() {
+ if (interpret()) {
+ return CallInterpreter(Vector<WasmVal>(nullptr, 0));
+ } else {
+ return Call(0, 0, 0, 0);
+ }
+ }
+
+ template <typename P0>
+ ReturnType Call(P0 p0) {
+ 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) {
+ 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) {
+ if (interpret()) {
+ WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2)};
+ return CallInterpreter(ArrayVector(args));
+ } else {
+ return Call(p0, p1, p2, 0);
+ }
+ }
+
static jmp_buf jump_buffer;
-};
-
-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());
- }
- }
-
- ReturnType Call(ParamTypes... p) {
- DCHECK(compiled_);
- if (interpret()) return CallInterpreter(p...);
-
- // Use setjmp/longjmp to deal with traps in WebAssembly code.
- int jump_value = setjmp(WasmRunnerBase::jump_buffer);
- // jump_value == 0 --> first return; jump_value == 1 --> longjmp happened.
- return jump_value ? static_cast<ReturnType>(0xdeadbeefdeadbeef)
- : DoCall(p...);
- }
-
- ReturnType CallInterpreter(ParamTypes... p) {
+ 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 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 CallInterpreter(Vector<WasmVal> args) {
+ CHECK_EQ(args.length(),
+ static_cast<int>(compiler_.function_->sig->parameter_count()));
WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
thread->Reset();
- std::array<WasmVal, sizeof...(p)> args{{WasmVal(p)...}};
- thread->PushFrame(function(), args.data());
+ thread->PushFrame(compiler_.function_, args.start());
if (thread->Run() == WasmInterpreter::FINISHED) {
WasmVal val = thread->GetReturnValue();
possible_nondeterminism_ |= thread->PossibleNondeterminism();
@@ -685,33 +783,45 @@
return static_cast<ReturnType>(result);
} else {
// TODO(titzer): falling off end
- return ReturnType{0};
- }
- }
-
- private:
- ReturnType DoCall(ParamTypes... p) {
- auto trap_callback = []() -> void {
- set_trap_callback_for_testing(nullptr);
- longjmp(WasmRunnerBase::jump_buffer, 1);
- };
- set_trap_callback_for_testing(trap_callback);
-
- wrapper_.SetInnerCode(
- module_.GetFunctionCode(functions_[0]->function_index()));
- CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
- wrapper_.GetWrapperCode(), wrapper_.signature());
- ReturnType return_value;
- int32_t result = runner.Call(static_cast<void*>(&p)...,
- static_cast<void*>(&return_value));
- // If we arrive here, no trap happened.
- CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
- return return_value;
+ ReturnType val = 0;
+ return val;
+ }
+ }
+
+ byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); }
+
+ WasmFunction* function() { return compiler_.function_; }
+ WasmInterpreter* interpreter() { return compiler_.interpreter_; }
+ bool possible_nondeterminism() { return possible_nondeterminism_; }
+
+ 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;
}
};
-// Declare static variable.
-jmp_buf WasmRunnerBase::jump_buffer;
+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;
// 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