Chromium Code Reviews| 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 4c26465baa29c324a0c49a4d0bd51d9457d92931..3fa417eb90263118c451b20bf9f746d48a6cf003 100644 |
| --- a/test/cctest/wasm/wasm-run-utils.h |
| +++ b/test/cctest/wasm/wasm-run-utils.h |
| @@ -8,6 +8,7 @@ |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include <string.h> |
| +#include <array> |
| #include <memory> |
| #include "src/base/utils/random-number-generator.h" |
| @@ -71,7 +72,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_), |
| @@ -81,7 +82,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; |
| @@ -102,7 +103,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); |
| @@ -117,7 +118,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); |
| } |
| @@ -243,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]; |
| @@ -261,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,35 +317,30 @@ 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()), |
| + explicit WasmFunctionWrapper(Zone* zone, int num_params) |
| + : GraphAndBuilders(zone), |
| inner_code_node_(nullptr), |
| - signature_(nullptr) { |
| + signature_(nullptr), |
| + num_params_(num_params) { |
| // 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. |
| + template <typename... ParamTypes> |
| + void Init(CallDescriptor* descriptor) { |
| + DCHECK_NOT_NULL(descriptor); |
| + // 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()->template NewArray<Node*>(num_params_ + 3); |
| graph()->SetStart(graph()->NewNode(common()->Start(6))); |
| Node* effect = graph()->start(); |
| int parameter_count = 0; |
| @@ -351,34 +349,14 @@ 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()) { |
| - 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()) { |
| + std::array<MachineType, sizeof...(ParamTypes)> mach_types{ |
|
titzer
2016/12/14 17:31:14
Can you factor this std::array creation into a met
Clemens Hammacher
2016/12/14 20:41:38
Done. It turned out that also the ReturnType was o
|
| + {MachineTypeForC<ParamTypes>()...}}; |
| + int param_idx = 0; |
| + for (MachineType t : mach_types) { |
| + DCHECK_NE(MachineType::None(), t); |
| 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++]; |
| @@ -393,8 +371,7 @@ class WasmFunctionWrapper : public HandleAndZoneScope, |
| machine()->Store( |
| StoreRepresentation(MachineTypeForC<ReturnType>().representation(), |
| WriteBarrierKind::kNoWriteBarrier)), |
| - graph()->NewNode(common()->Parameter(WASM_RUNNER_MAX_NUM_PARAMETERS), |
| - graph()->start()), |
| + graph()->NewNode(common()->Parameter(num_params_), graph()->start()), |
| graph()->NewNode(common()->Int32Constant(0)), call, effect, |
| graph()->start()); |
| Node* zero = graph()->NewNode(common()->Int32Constant(0)); |
| @@ -453,101 +430,40 @@ class WasmFunctionWrapper : public HandleAndZoneScope, |
| Node* inner_code_node_; |
| Handle<Code> code_; |
| Signature<MachineType>* signature_; |
| + int num_params_; |
| }; |
| -// 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() { |
| if (descriptor_ == nullptr) { |
| - descriptor_ = testing_module_->GetWasmCallDescriptor(main_zone(), sig); |
| + descriptor_ = testing_module_->GetWasmCallDescriptor(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); |
| + 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) { |
| @@ -557,13 +473,35 @@ class WasmFunctionCompiler : public HandleAndZoneScope, |
| return result; |
| } |
| + void SetSigIndex(int sig_index) { function_->sig_index = sig_index; } |
| + |
| + private: |
| + template <typename ReturnType, typename... ParamTypes> |
| + friend class WasmRunner; |
| + |
| + 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_; |
| 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)); |
| @@ -593,75 +531,28 @@ 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(); |
| - } |
| + 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 { |
| +template <typename MainReturnType, typename... MainParamTypes> |
| +class WasmRunner : public HandleAndZoneScope { |
|
titzer
2016/12/14 17:31:14
Can you factor out a base class to avoid duplicati
Clemens Hammacher
2016/12/14 20:41:38
Done.
|
| 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 WasmRunner(WasmExecutionMode execution_mode) |
| + : zone_(&allocator_, ZONE_NAME), |
| + module_(&zone_, execution_mode), |
| + wrapper_(&zone_, sizeof...(MainParamTypes)) { |
| + NewFunction<MainReturnType, MainParamTypes...>(); |
| } |
| // Builds a graph from the given Wasm code and generates the machine |
| @@ -670,124 +561,112 @@ 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(); |
| - |
| - 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); |
| - } |
| + functions_[0]->Build(start, end); |
| } |
| - ReturnType Call() { |
| - if (interpret()) { |
| - return CallInterpreter(Vector<WasmVal>(nullptr, 0)); |
| - } else { |
| - return Call(0, 0, 0, 0); |
| - } |
| + // Resets the state for building the next function. |
| + // The main function called will always be the first function. |
| + template <typename NextReturnType, typename... NextParamTypes> |
| + WasmFunctionCompiler& NewFunction() { |
| + return NewFunction(CreateSig<NextReturnType, NextParamTypes...>()); |
| } |
| - template <typename P0> |
| - ReturnType Call(P0 p0) { |
| - if (interpret()) { |
| - WasmVal args[] = {WasmVal(p0)}; |
| - return CallInterpreter(ArrayVector(args)); |
| - } else { |
| - return Call(p0, 0, 0, 0); |
| - } |
| + // 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(); |
| } |
| - 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); |
| - } |
| - } |
| + MainReturnType Call(MainParamTypes... p) { |
| + DCHECK(compiled_); |
| + if (interpret()) return CallInterpreter(p...); |
| - 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); |
| - } |
| + wrapper_.template Init<MainParamTypes...>(functions_[0]->descriptor()); |
| + wrapper_.SetInnerCode( |
| + module_.GetFunctionCode(functions_[0]->function_index())); |
| + CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(), |
| + wrapper_.GetWrapperCode(), wrapper_.signature()); |
| + MainReturnType return_value; |
| + int32_t result = runner.Call(static_cast<void*>(&p)..., |
| + static_cast<void*>(&return_value)); |
| + CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result); |
| + return return_value; |
| } |
| - 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 { |
| - 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())); |
| + MainReturnType CallInterpreter(MainParamTypes... 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(functions_[0]->function_, args.data()); |
| if (thread->Run() == WasmInterpreter::FINISHED) { |
| WasmVal val = thread->GetReturnValue(); |
| possible_nondeterminism_ |= thread->PossibleNondeterminism(); |
| - return val.to<ReturnType>(); |
| + return val.to<MainReturnType>(); |
| } else if (thread->state() == WasmInterpreter::TRAPPED) { |
| // TODO(titzer): return the correct trap code |
| int64_t result = 0xdeadbeefdeadbeef; |
| - return static_cast<ReturnType>(result); |
| + return static_cast<MainReturnType>(result); |
| } else { |
| // TODO(titzer): falling off end |
| - ReturnType val = 0; |
| + MainReturnType val = 0; |
| return val; |
| } |
| } |
| - byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); } |
| + byte AllocateLocal(LocalType type) { |
| + return functions_[0]->AllocateLocal(type); |
| + } |
| - WasmFunction* function() { return compiler_.function_; } |
| - WasmInterpreter* interpreter() { return compiler_.interpreter_; } |
| + 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_; } |
| - 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; |
| + // 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: |
| + template <typename ReturnType, typename... ParamTypes> |
| + FunctionSig* CreateSig() { |
| + MachineType ret_and_params[] = {MachineTypeForC<ReturnType>(), |
| + MachineTypeForC<ParamTypes>()...}; |
| + size_t return_count = ret_and_params[0] == MachineType::None() ? 0 : 1; |
|
titzer
2016/12/14 17:31:14
Same here. Can you factor this out to be an entryp
Clemens Hammacher
2016/12/14 20:41:38
Done.
|
| + size_t param_count = sizeof...(ParamTypes); |
| + |
| + // 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. |
| + if (return_count) |
| + sig_types[0] = WasmOpcodes::LocalTypeFor(ret_and_params[0]); |
| + for (size_t i = 0; i < param_count; ++i) { |
| + CHECK_NE(MachineType::None(), ret_and_params[i + 1]); |
| + sig_types[i + return_count] = |
| + WasmOpcodes::LocalTypeFor(ret_and_params[i + 1]); |
| + } |
| + return new (&zone_) FunctionSig(return_count, param_count, sig_types); |
| + } |
| + v8::internal::AccountingAllocator allocator_; |
| + Zone zone_; |
| + TestingModule module_; |
| + std::vector<std::unique_ptr<WasmFunctionCompiler>> functions_; |
| + WasmFunctionWrapper<MainReturnType> wrapper_; |
| + bool compiled_ = false; |
| + bool possible_nondeterminism_ = false; |
| + |
| + bool interpret() { return module_.execution_mode() == kExecuteInterpreted; } |
| }; |
| // A macro to define tests that run in different engine configurations. |