| 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 a90d9c615044574e69f8056ed783421d29a2bd5e..7ee39818853a078ddcaaf1ddc34569ba332fb0d0 100644
|
| --- a/test/cctest/wasm/wasm-run-utils.h
|
| +++ b/test/cctest/wasm/wasm-run-utils.h
|
| @@ -36,6 +36,8 @@
|
| #define WASM_64 0
|
| #endif
|
|
|
| +static const uint32_t kMaxFunctions = 10;
|
| +
|
| // 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
|
| @@ -68,17 +70,20 @@ inline void init_env(FunctionEnv* env, FunctionSig* sig) {
|
| const uint32_t kMaxGlobalsSize = 128;
|
|
|
| // A helper for module environments that adds the ability to allocate memory
|
| -// and global variables. Contains a built-in {WasmModuleInstance}.
|
| +// and global variables. Contains a built-in {WasmModule} and
|
| +// {WasmModuleInstance}.
|
| class TestingModule : public ModuleEnv {
|
| public:
|
| - TestingModule() : instance_(nullptr), global_offset(0) {
|
| + TestingModule() : instance_(&module_), global_offset(0) {
|
| + module_.shared_isolate = CcTest::InitIsolateOnce();
|
| + module = &module_;
|
| instance = &instance_;
|
| + instance->module = &module_;
|
| instance->globals_start = global_data;
|
| instance->globals_size = kMaxGlobalsSize;
|
| instance->mem_start = nullptr;
|
| instance->mem_size = 0;
|
| instance->function_code = nullptr;
|
| - module = nullptr;
|
| linker = nullptr;
|
| asm_js = false;
|
| memset(global_data, 0, sizeof(global_data));
|
| @@ -88,8 +93,9 @@ class TestingModule : public ModuleEnv {
|
| if (instance->mem_start) {
|
| free(instance->mem_start);
|
| }
|
| - if (instance->function_code) delete instance->function_code;
|
| - if (module) delete module;
|
| + if (instance->function_code) {
|
| + delete instance->function_code;
|
| + }
|
| }
|
|
|
| byte* AddMemory(size_t size) {
|
| @@ -115,7 +121,6 @@ class TestingModule : public ModuleEnv {
|
| }
|
|
|
| byte AddSignature(FunctionSig* sig) {
|
| - AllocModule();
|
| if (!module->signatures) {
|
| module->signatures = new std::vector<FunctionSig*>();
|
| }
|
| @@ -165,21 +170,27 @@ class TestingModule : public ModuleEnv {
|
| rng.NextBytes(raw, end - raw);
|
| }
|
|
|
| - WasmFunction* AddFunction(FunctionSig* sig, Handle<Code> code) {
|
| - AllocModule();
|
| + int AddFunction(FunctionSig* sig, Handle<Code> code) {
|
| if (module->functions == nullptr) {
|
| module->functions = new std::vector<WasmFunction>();
|
| + // TODO(titzer): Reserving space here to avoid the underlying WasmFunction
|
| + // structs from moving.
|
| + module->functions->reserve(kMaxFunctions);
|
| instance->function_code = new std::vector<Handle<Code>>();
|
| }
|
| uint32_t index = static_cast<uint32_t>(module->functions->size());
|
| module->functions->push_back(
|
| {sig, index, 0, 0, 0, 0, 0, 0, 0, false, false});
|
| instance->function_code->push_back(code);
|
| - return &module->functions->back();
|
| + DCHECK_LT(index, kMaxFunctions); // limited for testing.
|
| + return index;
|
| + }
|
| +
|
| + void SetFunctionCode(uint32_t index, Handle<Code> code) {
|
| + instance->function_code->at(index) = code;
|
| }
|
|
|
| void AddIndirectFunctionTable(int* functions, int table_size) {
|
| - AllocModule();
|
| Isolate* isolate = module->shared_isolate;
|
| Handle<FixedArray> fixed =
|
| isolate->factory()->NewFixedArray(2 * table_size);
|
| @@ -202,14 +213,13 @@ class TestingModule : public ModuleEnv {
|
| }
|
| }
|
|
|
| -
|
| private:
|
| + WasmModule module_;
|
| WasmModuleInstance instance_;
|
| uint32_t global_offset;
|
| V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data.
|
|
|
| WasmGlobal* AddGlobal(MachineType mem_type) {
|
| - AllocModule();
|
| if (!module->globals) {
|
| module->globals = new std::vector<WasmGlobal>();
|
| }
|
| @@ -221,15 +231,6 @@ class TestingModule : public ModuleEnv {
|
| CHECK_LT(global_offset, kMaxGlobalsSize);
|
| return &module->globals->back();
|
| }
|
| - void AllocModule() {
|
| - if (module == nullptr) {
|
| - module = new WasmModule();
|
| - module->shared_isolate = CcTest::InitIsolateOnce();
|
| - module->globals = nullptr;
|
| - module->functions = nullptr;
|
| - module->data_segments = nullptr;
|
| - }
|
| - }
|
| };
|
|
|
|
|
| @@ -393,23 +394,44 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
|
| Signature<MachineType>* signature_;
|
| };
|
|
|
| -// A helper for compiling functions that are only internally callable WASM code.
|
| +// 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.
|
| class WasmFunctionCompiler : public HandleAndZoneScope,
|
| private GraphAndBuilders {
|
| public:
|
| - explicit WasmFunctionCompiler(FunctionSig* sig, ModuleEnv* module = nullptr)
|
| + explicit WasmFunctionCompiler(FunctionSig* sig, TestingModule* module)
|
| : GraphAndBuilders(main_zone()),
|
| jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
|
| nullptr, this->machine()),
|
| - descriptor_(nullptr) {
|
| + descriptor_(nullptr),
|
| + testing_module_(module) {
|
| init_env(&env, sig);
|
| env.module = module;
|
| + 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;
|
| + }
|
| + }
|
| +
|
| + ~WasmFunctionCompiler() {
|
| + if (function_) delete function_;
|
| }
|
|
|
| JSGraph jsgraph;
|
| FunctionEnv env;
|
| // The call descriptor is initialized when the function is compiled.
|
| CallDescriptor* descriptor_;
|
| + TestingModule* testing_module_;
|
| + WasmFunction* function_;
|
| + int function_index_;
|
|
|
| Isolate* isolate() { return main_isolate(); }
|
| Graph* graph() const { return main_graph_; }
|
| @@ -424,6 +446,13 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
|
| CallDescriptor* descriptor() { return descriptor_; }
|
|
|
| void Build(const byte* start, const byte* end) {
|
| + // Transfer local counts before compiling.
|
| + function()->local_i32_count = env.local_i32_count;
|
| + function()->local_i64_count = env.local_i64_count;
|
| + function()->local_f32_count = env.local_f32_count;
|
| + function()->local_f64_count = env.local_f64_count;
|
| +
|
| + // Build the TurboFan graph.
|
| TestBuildingGraph(main_zone(), &jsgraph, &env, start, end);
|
| }
|
|
|
| @@ -435,11 +464,12 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
|
| return b;
|
| }
|
|
|
| - Handle<Code> Compile(ModuleEnv* module) {
|
| + // TODO(titzer): remove me.
|
| + Handle<Code> Compile() {
|
| InitializeDescriptor();
|
| CallDescriptor* desc = descriptor_;
|
| if (kPointerSize == 4) {
|
| - desc = module->GetI32WasmCallDescriptor(this->zone(), desc);
|
| + desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
|
| }
|
| CompilationInfo info("wasm compile", this->isolate(), this->zone());
|
| Handle<Code> result =
|
| @@ -454,17 +484,20 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
|
| return result;
|
| }
|
|
|
| - uint32_t CompileAndAdd(TestingModule* module, int sig_index = 0) {
|
| - uint32_t index = 0;
|
| - if (module->module && module->module->functions) {
|
| - index = static_cast<uint32_t>(module->module->functions->size());
|
| - }
|
| - WasmFunction* function = module->AddFunction(env.sig, Compile(module));
|
| - function->sig_index = sig_index;
|
| - return index;
|
| + // TODO(titzer): remove me.
|
| + 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 static_cast<uint32_t>(function_index_);
|
| }
|
| -};
|
|
|
| + WasmFunction* function() {
|
| + if (function_) return function_;
|
| + return &testing_module_->module->functions->at(function_index_);
|
| + }
|
| +};
|
|
|
| // A helper class to build graphs from Wasm bytecode, generate machine
|
| // code, and run that code.
|
| @@ -475,10 +508,28 @@ class WasmRunner {
|
| MachineType p1 = MachineType::None(),
|
| MachineType p2 = MachineType::None(),
|
| MachineType p3 = MachineType::None())
|
| - : signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
|
| + : compiled_(false),
|
| +
|
| + signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
|
| + GetParameterCount(p0, p1, p2, p3), storage_),
|
| + compiler_(&signature_, nullptr) {
|
| + InitSigStorage(p0, p1, p2, p3);
|
| + }
|
| +
|
| + WasmRunner(TestingModule* module, MachineType p0 = MachineType::None(),
|
| + MachineType p1 = MachineType::None(),
|
| + MachineType p2 = MachineType::None(),
|
| + MachineType p3 = MachineType::None())
|
| + : compiled_(false),
|
| + signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
|
| GetParameterCount(p0, p1, p2, p3), storage_),
|
| - compiler_(&signature_),
|
| - compilation_done_(false) {
|
| + compiler_(&signature_, module) {
|
| + 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()) {
|
| @@ -497,39 +548,44 @@ class WasmRunner {
|
| wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3);
|
| }
|
|
|
| -
|
| FunctionEnv* env() { return &compiler_.env; }
|
|
|
| -
|
| - // Builds a graph from the given Wasm code, and generates the machine
|
| + // 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
|
| // more than once.
|
| void Build(const byte* start, const byte* end) {
|
| - DCHECK(!compilation_done_);
|
| - compilation_done_ = true;
|
| - // Build the TF graph.
|
| + CHECK(!compiled_);
|
| + compiled_ = true;
|
| +
|
| + // Build the TF graph within the compiler.
|
| compiler_.Build(start, end);
|
| // Generate code.
|
| - Handle<Code> code = compiler_.Compile(env()->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_index_,
|
| + code);
|
| + }
|
|
|
| wrapper_.SetInnerCode(code);
|
| }
|
|
|
| - ReturnType Call() { return Call(nullptr, nullptr, nullptr, nullptr); }
|
| + ReturnType Call() { return Call(0, 0, 0, 0); }
|
|
|
| template <typename P0>
|
| ReturnType Call(P0 p0) {
|
| - return Call(p0, nullptr, nullptr, nullptr);
|
| + return Call(p0, 0, 0, 0);
|
| }
|
|
|
| template <typename P0, typename P1>
|
| ReturnType Call(P0 p0, P1 p1) {
|
| - return Call(p0, p1, nullptr, nullptr);
|
| + 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, nullptr);
|
| + return Call(p0, p1, p2, 0);
|
| }
|
|
|
| template <typename P0, typename P1, typename P2, typename P3>
|
| @@ -551,12 +607,13 @@ class WasmRunner {
|
| return b;
|
| }
|
|
|
| - private:
|
| + protected:
|
| + Zone zone;
|
| + bool compiled_;
|
| LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS];
|
| FunctionSig signature_;
|
| WasmFunctionCompiler compiler_;
|
| WasmFunctionWrapper<ReturnType> wrapper_;
|
| - bool compilation_done_;
|
|
|
| static size_t GetParameterCount(MachineType p0, MachineType p1,
|
| MachineType p2, MachineType p3) {
|
|
|