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

Side by Side Diff: test/cctest/wasm/wasm-run-utils.h

Issue 1972153002: [wasm] Implement an interpreter for WASM. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/wasm/test-run-wasm-interpreter.cc ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef WASM_RUN_UTILS_H 5 #ifndef WASM_RUN_UTILS_H
6 #define WASM_RUN_UTILS_H 6 #define WASM_RUN_UTILS_H
7 7
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <stdlib.h> 9 #include <stdlib.h>
10 #include <string.h> 10 #include <string.h>
11 11
12 #include "src/base/accounting-allocator.h"
12 #include "src/base/utils/random-number-generator.h" 13 #include "src/base/utils/random-number-generator.h"
13 14
14 #include "src/compiler/graph-visualizer.h" 15 #include "src/compiler/graph-visualizer.h"
15 #include "src/compiler/int64-lowering.h" 16 #include "src/compiler/int64-lowering.h"
16 #include "src/compiler/js-graph.h" 17 #include "src/compiler/js-graph.h"
17 #include "src/compiler/node.h" 18 #include "src/compiler/node.h"
18 #include "src/compiler/pipeline.h" 19 #include "src/compiler/pipeline.h"
19 #include "src/compiler/wasm-compiler.h" 20 #include "src/compiler/wasm-compiler.h"
20 #include "src/compiler/zone-pool.h" 21 #include "src/compiler/zone-pool.h"
21 22
22 #include "src/wasm/ast-decoder.h" 23 #include "src/wasm/ast-decoder.h"
24 #include "src/wasm/wasm-interpreter.h"
23 #include "src/wasm/wasm-js.h" 25 #include "src/wasm/wasm-js.h"
24 #include "src/wasm/wasm-macro-gen.h" 26 #include "src/wasm/wasm-macro-gen.h"
25 #include "src/wasm/wasm-module.h" 27 #include "src/wasm/wasm-module.h"
26 #include "src/wasm/wasm-opcodes.h" 28 #include "src/wasm/wasm-opcodes.h"
27 29
28 #include "src/zone.h" 30 #include "src/zone.h"
29 31
30 #include "test/cctest/cctest.h" 32 #include "test/cctest/cctest.h"
31 #include "test/cctest/compiler/call-tester.h" 33 #include "test/cctest/compiler/call-tester.h"
32 #include "test/cctest/compiler/graph-builder-tester.h" 34 #include "test/cctest/compiler/graph-builder-tester.h"
33 35
34 // TODO(titzer): pull WASM_64 up to a common header. 36 // TODO(titzer): pull WASM_64 up to a common header.
35 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 37 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
36 #define WASM_64 1 38 #define WASM_64 1
37 #else 39 #else
38 #define WASM_64 0 40 #define WASM_64 0
39 #endif 41 #endif
40 42
41 static const uint32_t kMaxFunctions = 10; 43 static const uint32_t kMaxFunctions = 10;
42 44
45 enum WasmExecutionMode { kExecuteInterpreted, kExecuteCompiled };
46
43 // TODO(titzer): check traps more robustly in tests. 47 // TODO(titzer): check traps more robustly in tests.
44 // Currently, in tests, we just return 0xdeadbeef from the function in which 48 // Currently, in tests, we just return 0xdeadbeef from the function in which
45 // the trap occurs if the runtime context is not available to throw a JavaScript 49 // the trap occurs if the runtime context is not available to throw a JavaScript
46 // exception. 50 // exception.
47 #define CHECK_TRAP32(x) \ 51 #define CHECK_TRAP32(x) \
48 CHECK_EQ(0xdeadbeef, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF) 52 CHECK_EQ(0xdeadbeef, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF)
49 #define CHECK_TRAP64(x) \ 53 #define CHECK_TRAP64(x) \
50 CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF) 54 CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
51 #define CHECK_TRAP(x) CHECK_TRAP32(x) 55 #define CHECK_TRAP(x) CHECK_TRAP32(x)
52 56
(...skipping 12 matching lines...) Expand all
65 using namespace v8::internal::compiler; 69 using namespace v8::internal::compiler;
66 using namespace v8::internal::wasm; 70 using namespace v8::internal::wasm;
67 71
68 const uint32_t kMaxGlobalsSize = 128; 72 const uint32_t kMaxGlobalsSize = 128;
69 73
70 // A helper for module environments that adds the ability to allocate memory 74 // A helper for module environments that adds the ability to allocate memory
71 // and global variables. Contains a built-in {WasmModule} and 75 // and global variables. Contains a built-in {WasmModule} and
72 // {WasmModuleInstance}. 76 // {WasmModuleInstance}.
73 class TestingModule : public ModuleEnv { 77 class TestingModule : public ModuleEnv {
74 public: 78 public:
75 TestingModule() 79 explicit TestingModule(WasmExecutionMode mode = kExecuteCompiled)
76 : instance_(&module_), 80 : execution_mode_(mode),
81 instance_(&module_),
77 isolate_(CcTest::InitIsolateOnce()), 82 isolate_(CcTest::InitIsolateOnce()),
78 global_offset(0) { 83 global_offset(0),
84 interpreter_(mode == kExecuteInterpreted
85 ? new WasmInterpreter(&instance_, &allocator_)
86 : nullptr) {
79 module = &module_; 87 module = &module_;
80 instance = &instance_; 88 instance = &instance_;
81 instance->module = &module_; 89 instance->module = &module_;
82 instance->globals_start = global_data; 90 instance->globals_start = global_data;
83 module_.globals_size = kMaxGlobalsSize; 91 module_.globals_size = kMaxGlobalsSize;
84 instance->mem_start = nullptr; 92 instance->mem_start = nullptr;
85 instance->mem_size = 0; 93 instance->mem_size = 0;
86 linker = nullptr; 94 linker = nullptr;
87 origin = kWasmOrigin; 95 origin = kWasmOrigin;
88 memset(global_data, 0, sizeof(global_data)); 96 memset(global_data, 0, sizeof(global_data));
89 } 97 }
90 98
91 ~TestingModule() { 99 ~TestingModule() {
92 if (instance->mem_start) { 100 if (instance->mem_start) {
93 free(instance->mem_start); 101 free(instance->mem_start);
94 } 102 }
103 if (interpreter_) delete interpreter_;
95 } 104 }
96 105
97 byte* AddMemory(size_t size) { 106 byte* AddMemory(size_t size) {
98 CHECK_NULL(instance->mem_start); 107 CHECK_NULL(instance->mem_start);
99 CHECK_EQ(0, instance->mem_size); 108 CHECK_EQ(0, instance->mem_size);
100 instance->mem_start = reinterpret_cast<byte*>(malloc(size)); 109 instance->mem_start = reinterpret_cast<byte*>(malloc(size));
101 CHECK(instance->mem_start); 110 CHECK(instance->mem_start);
102 memset(instance->mem_start, 0, size); 111 memset(instance->mem_start, 0, size);
103 instance->mem_size = size; 112 instance->mem_size = size;
104 return raw_mem_start<byte>(); 113 return raw_mem_start<byte>();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 174
166 uint32_t AddFunction(FunctionSig* sig, Handle<Code> code) { 175 uint32_t AddFunction(FunctionSig* sig, Handle<Code> code) {
167 if (module->functions.size() == 0) { 176 if (module->functions.size() == 0) {
168 // TODO(titzer): Reserving space here to avoid the underlying WasmFunction 177 // TODO(titzer): Reserving space here to avoid the underlying WasmFunction
169 // structs from moving. 178 // structs from moving.
170 module_.functions.reserve(kMaxFunctions); 179 module_.functions.reserve(kMaxFunctions);
171 } 180 }
172 uint32_t index = static_cast<uint32_t>(module->functions.size()); 181 uint32_t index = static_cast<uint32_t>(module->functions.size());
173 module_.functions.push_back({sig, index, 0, 0, 0, 0, 0, false}); 182 module_.functions.push_back({sig, index, 0, 0, 0, 0, 0, false});
174 instance->function_code.push_back(code); 183 instance->function_code.push_back(code);
184 if (interpreter_) {
185 const WasmFunction* function = &module->functions.back();
186 int interpreter_index = interpreter_->AddFunctionForTesting(function);
187 CHECK_EQ(index, static_cast<uint32_t>(interpreter_index));
188 }
175 DCHECK_LT(index, kMaxFunctions); // limited for testing. 189 DCHECK_LT(index, kMaxFunctions); // limited for testing.
176 return index; 190 return index;
177 } 191 }
178 192
179 uint32_t AddJsFunction(FunctionSig* sig, const char* source) { 193 uint32_t AddJsFunction(FunctionSig* sig, const char* source) {
180 Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle( 194 Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
181 *v8::Local<v8::Function>::Cast(CompileRun(source)))); 195 *v8::Local<v8::Function>::Cast(CompileRun(source))));
182 uint32_t index = AddFunction(sig, Handle<Code>::null()); 196 uint32_t index = AddFunction(sig, Handle<Code>::null());
183 WasmName module_name = ArrayVector("test"); 197 WasmName module_name = ArrayVector("test");
184 WasmName function_name; 198 WasmName function_name;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 for (int i = 0; i < table_size; i++) { 232 for (int i = 0; i < table_size; i++) {
219 int function_index = module->function_table[i]; 233 int function_index = module->function_table[i];
220 const WasmFunction* function = &module->functions[function_index]; 234 const WasmFunction* function = &module->functions[function_index];
221 instance->function_table->set(i, Smi::FromInt(function->sig_index)); 235 instance->function_table->set(i, Smi::FromInt(function->sig_index));
222 instance->function_table->set(i + table_size, 236 instance->function_table->set(i + table_size,
223 *instance->function_code[function_index]); 237 *instance->function_code[function_index]);
224 } 238 }
225 } 239 }
226 WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; } 240 WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; }
227 241
242 WasmInterpreter* interpreter() { return interpreter_; }
243 WasmExecutionMode execution_mode() { return execution_mode_; }
244
228 private: 245 private:
246 WasmExecutionMode execution_mode_;
229 WasmModule module_; 247 WasmModule module_;
230 WasmModuleInstance instance_; 248 WasmModuleInstance instance_;
231 Isolate* isolate_; 249 Isolate* isolate_;
250 v8::base::AccountingAllocator allocator_;
232 uint32_t global_offset; 251 uint32_t global_offset;
233 V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data. 252 V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data.
253 WasmInterpreter* interpreter_;
234 254
235 const WasmGlobal* AddGlobal(MachineType mem_type) { 255 const WasmGlobal* AddGlobal(MachineType mem_type) {
236 byte size = WasmOpcodes::MemSize(mem_type); 256 byte size = WasmOpcodes::MemSize(mem_type);
237 global_offset = (global_offset + size - 1) & ~(size - 1); // align 257 global_offset = (global_offset + size - 1) & ~(size - 1); // align
238 module_.globals.push_back({0, 0, mem_type, global_offset, false}); 258 module_.globals.push_back({0, 0, mem_type, global_offset, false});
239 global_offset += size; 259 global_offset += size;
240 // limit number of globals. 260 // limit number of globals.
241 CHECK_LT(global_offset, kMaxGlobalsSize); 261 CHECK_LT(global_offset, kMaxGlobalsSize);
242 return &module->globals.back(); 262 return &module->globals.back();
243 } 263 }
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 422
403 private: 423 private:
404 Node* inner_code_node_; 424 Node* inner_code_node_;
405 Handle<Code> code_; 425 Handle<Code> code_;
406 Signature<MachineType>* signature_; 426 Signature<MachineType>* signature_;
407 }; 427 };
408 428
409 // A helper for compiling WASM functions for testing. This class can create a 429 // A helper for compiling WASM functions for testing. This class can create a
410 // standalone function if {module} is NULL or a function within a 430 // standalone function if {module} is NULL or a function within a
411 // {TestingModule}. It contains the internal state for compilation (i.e. 431 // {TestingModule}. It contains the internal state for compilation (i.e.
412 // TurboFan graph) and, later, interpretation. 432 // TurboFan graph) and interpretation (by adding to the interpreter manually).
413 class WasmFunctionCompiler : public HandleAndZoneScope, 433 class WasmFunctionCompiler : public HandleAndZoneScope,
414 private GraphAndBuilders { 434 private GraphAndBuilders {
415 public: 435 public:
416 explicit WasmFunctionCompiler( 436 explicit WasmFunctionCompiler(
437 FunctionSig* sig, WasmExecutionMode mode,
438 Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
439 : GraphAndBuilders(main_zone()),
440 execution_mode_(mode),
441 jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
442 nullptr, this->machine()),
443 sig(sig),
444 descriptor_(nullptr),
445 testing_module_(nullptr),
446 debug_name_(debug_name),
447 local_decls(main_zone(), sig),
448 source_position_table_(this->graph()),
449 interpreter_(nullptr) {
450 // Create our own function.
451 function_ = new WasmFunction();
452 function_->sig = sig;
453 function_->func_index = 0;
454 function_->sig_index = 0;
455 if (mode == kExecuteInterpreted) {
456 interpreter_ = new WasmInterpreter(nullptr, zone()->allocator());
457 int index = interpreter_->AddFunctionForTesting(function_);
458 CHECK_EQ(0, index);
459 }
460 }
461
462 explicit WasmFunctionCompiler(
417 FunctionSig* sig, TestingModule* module, 463 FunctionSig* sig, TestingModule* module,
418 Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>")) 464 Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
419 : GraphAndBuilders(main_zone()), 465 : GraphAndBuilders(main_zone()),
466 execution_mode_(module->execution_mode()),
420 jsgraph(this->isolate(), this->graph(), this->common(), nullptr, 467 jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
421 nullptr, this->machine()), 468 nullptr, this->machine()),
422 sig(sig), 469 sig(sig),
423 descriptor_(nullptr), 470 descriptor_(nullptr),
424 testing_module_(module), 471 testing_module_(module),
425 debug_name_(debug_name), 472 debug_name_(debug_name),
426 local_decls(main_zone(), sig), 473 local_decls(main_zone(), sig),
427 source_position_table_(this->graph()) { 474 source_position_table_(this->graph()),
428 if (module) { 475 interpreter_(module->interpreter()) {
429 // Get a new function from the testing module. 476 // Get a new function from the testing module.
430 function_ = nullptr; 477 int index = module->AddFunction(sig, Handle<Code>::null());
431 function_index_ = module->AddFunction(sig, Handle<Code>::null()); 478 function_ = testing_module_->GetFunctionAt(index);
432 } else {
433 // Create our own function.
434 function_ = new WasmFunction();
435 function_->sig = sig;
436 function_index_ = 0;
437 }
438 } 479 }
439 480
440 ~WasmFunctionCompiler() { 481 ~WasmFunctionCompiler() {
441 if (function_) delete function_; 482 if (testing_module_) return; // testing module owns the below things.
483 delete function_;
484 if (interpreter_) delete interpreter_;
442 } 485 }
443 486
487 WasmExecutionMode execution_mode_;
444 JSGraph jsgraph; 488 JSGraph jsgraph;
445 FunctionSig* sig; 489 FunctionSig* sig;
446 // The call descriptor is initialized when the function is compiled. 490 // The call descriptor is initialized when the function is compiled.
447 CallDescriptor* descriptor_; 491 CallDescriptor* descriptor_;
448 TestingModule* testing_module_; 492 TestingModule* testing_module_;
449 Vector<const char> debug_name_; 493 Vector<const char> debug_name_;
450 WasmFunction* function_; 494 WasmFunction* function_;
451 int function_index_;
452 LocalDeclEncoder local_decls; 495 LocalDeclEncoder local_decls;
453 SourcePositionTable source_position_table_; 496 SourcePositionTable source_position_table_;
497 WasmInterpreter* interpreter_;
454 498
455 Isolate* isolate() { return main_isolate(); } 499 Isolate* isolate() { return main_isolate(); }
456 Graph* graph() const { return main_graph_; } 500 Graph* graph() const { return main_graph_; }
457 Zone* zone() const { return graph()->zone(); } 501 Zone* zone() const { return graph()->zone(); }
458 CommonOperatorBuilder* common() { return &main_common_; } 502 CommonOperatorBuilder* common() { return &main_common_; }
459 MachineOperatorBuilder* machine() { return &main_machine_; } 503 MachineOperatorBuilder* machine() { return &main_machine_; }
460 void InitializeDescriptor() { 504 void InitializeDescriptor() {
461 if (descriptor_ == nullptr) { 505 if (descriptor_ == nullptr) {
462 descriptor_ = testing_module_->GetWasmCallDescriptor(main_zone(), sig); 506 descriptor_ = testing_module_->GetWasmCallDescriptor(main_zone(), sig);
463 } 507 }
464 } 508 }
465 CallDescriptor* descriptor() { return descriptor_; } 509 CallDescriptor* descriptor() { return descriptor_; }
510 uint32_t function_index() { return function_->func_index; }
466 511
467 void Build(const byte* start, const byte* end) { 512 void Build(const byte* start, const byte* end) {
468 // Build the TurboFan graph. 513 // Build the TurboFan graph.
469 local_decls.Prepend(&start, &end); 514 local_decls.Prepend(main_zone(), &start, &end);
470 TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig, 515 TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig,
471 &source_position_table_, start, end); 516 &source_position_table_, start, end);
472 delete[] start; 517 if (interpreter_) {
518 // Add the code to the interpreter.
519 CHECK(interpreter_->SetFunctionCodeForTesting(function_, start, end));
520 }
473 } 521 }
474 522
475 byte AllocateLocal(LocalType type) { 523 byte AllocateLocal(LocalType type) {
476 uint32_t index = local_decls.AddLocals(1, type); 524 uint32_t index = local_decls.AddLocals(1, type);
477 byte result = static_cast<byte>(index); 525 byte result = static_cast<byte>(index);
478 DCHECK_EQ(index, result); 526 DCHECK_EQ(index, result);
479 return result; 527 return result;
480 } 528 }
481 529
482 Handle<Code> Compile() { 530 Handle<Code> Compile() {
483 InitializeDescriptor(); 531 InitializeDescriptor();
484 CallDescriptor* desc = descriptor_; 532 CallDescriptor* desc = descriptor_;
485 if (kPointerSize == 4) { 533 if (kPointerSize == 4) {
486 desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc); 534 desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
487 } 535 }
488 CompilationInfo info(debug_name_, this->isolate(), this->zone(), 536 CompilationInfo info(debug_name_, this->isolate(), this->zone(),
489 Code::ComputeFlags(Code::WASM_FUNCTION)); 537 Code::ComputeFlags(Code::WASM_FUNCTION));
490 v8::base::SmartPointer<CompilationJob> job(Pipeline::NewWasmCompilationJob( 538 v8::base::SmartPointer<CompilationJob> job(Pipeline::NewWasmCompilationJob(
491 &info, graph(), desc, &source_position_table_)); 539 &info, graph(), desc, &source_position_table_));
492 if (job->OptimizeGraph() != CompilationJob::SUCCEEDED || 540 if (job->OptimizeGraph() != CompilationJob::SUCCEEDED ||
493 job->GenerateCode() != CompilationJob::SUCCEEDED) 541 job->GenerateCode() != CompilationJob::SUCCEEDED)
494 return Handle<Code>::null(); 542 return Handle<Code>::null();
495 543
496 Handle<Code> code = info.code(); 544 Handle<Code> code = info.code();
497 545
498 // Length is always 2, since usually <wasm_obj, func_index> is stored in the 546 // Length is always 2, since usually <wasm_obj, func_index> is stored in
499 // deopt data. Here, we only store the function index. 547 // the deopt data. Here, we only store the function index.
500 DCHECK(code->deoptimization_data() == nullptr || 548 DCHECK(code->deoptimization_data() == nullptr ||
501 code->deoptimization_data()->length() == 0); 549 code->deoptimization_data()->length() == 0);
502 Handle<FixedArray> deopt_data = 550 Handle<FixedArray> deopt_data =
503 isolate()->factory()->NewFixedArray(2, TENURED); 551 isolate()->factory()->NewFixedArray(2, TENURED);
504 deopt_data->set(1, Smi::FromInt(function_index_)); 552 deopt_data->set(1, Smi::FromInt(static_cast<int>(function_index())));
505 deopt_data->set_length(2); 553 deopt_data->set_length(2);
506 code->set_deoptimization_data(*deopt_data); 554 code->set_deoptimization_data(*deopt_data);
507 555
508 #ifdef ENABLE_DISASSEMBLER 556 #ifdef ENABLE_DISASSEMBLER
509 if (FLAG_print_opt_code) { 557 if (FLAG_print_opt_code) {
510 OFStream os(stdout); 558 OFStream os(stdout);
511 code->Disassemble("wasm code", os); 559 code->Disassemble("wasm code", os);
512 } 560 }
513 #endif 561 #endif
514 562
515 return code; 563 return code;
516 } 564 }
517 565
518 uint32_t CompileAndAdd(uint16_t sig_index = 0) { 566 uint32_t CompileAndAdd(uint16_t sig_index = 0) {
519 CHECK(testing_module_); 567 CHECK(testing_module_);
520 function()->sig_index = sig_index; 568 function_->sig_index = sig_index;
521 Handle<Code> code = Compile(); 569 Handle<Code> code = Compile();
522 testing_module_->SetFunctionCode(function_index_, code); 570 testing_module_->SetFunctionCode(function_index(), code);
523 return static_cast<uint32_t>(function_index_); 571 return function_index();
524 }
525
526 WasmFunction* function() {
527 if (function_) return function_;
528 return testing_module_->GetFunctionAt(function_index_);
529 } 572 }
530 573
531 // Set the context, such that e.g. runtime functions can be called. 574 // Set the context, such that e.g. runtime functions can be called.
532 void SetModuleContext() { 575 void SetModuleContext() {
533 if (!testing_module_->instance->context.is_null()) { 576 if (!testing_module_->instance->context.is_null()) {
534 CHECK(testing_module_->instance->context.is_identical_to( 577 CHECK(testing_module_->instance->context.is_identical_to(
535 main_isolate()->native_context())); 578 main_isolate()->native_context()));
536 return; 579 return;
537 } 580 }
538 testing_module_->instance->context = main_isolate()->native_context(); 581 testing_module_->instance->context = main_isolate()->native_context();
539 } 582 }
540 }; 583 };
541 584
542 // A helper class to build graphs from Wasm bytecode, generate machine 585 // A helper class to build graphs from Wasm bytecode, generate machine
543 // code, and run that code. 586 // code, and run that code.
544 template <typename ReturnType> 587 template <typename ReturnType>
545 class WasmRunner { 588 class WasmRunner {
546 public: 589 public:
547 WasmRunner(MachineType p0 = MachineType::None(), 590 WasmRunner(WasmExecutionMode execution_mode,
591 MachineType p0 = MachineType::None(),
548 MachineType p1 = MachineType::None(), 592 MachineType p1 = MachineType::None(),
549 MachineType p2 = MachineType::None(), 593 MachineType p2 = MachineType::None(),
550 MachineType p3 = MachineType::None()) 594 MachineType p3 = MachineType::None())
551 : zone(&allocator_), 595 : zone(&allocator_),
552 compiled_(false), 596 compiled_(false),
553 signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1, 597 signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
554 GetParameterCount(p0, p1, p2, p3), storage_), 598 GetParameterCount(p0, p1, p2, p3), storage_),
555 compiler_(&signature_, nullptr) { 599 compiler_(&signature_, execution_mode) {
556 InitSigStorage(p0, p1, p2, p3); 600 InitSigStorage(p0, p1, p2, p3);
557 } 601 }
558 602
559 WasmRunner(TestingModule* module, MachineType p0 = MachineType::None(), 603 WasmRunner(TestingModule* module, MachineType p0 = MachineType::None(),
560 MachineType p1 = MachineType::None(), 604 MachineType p1 = MachineType::None(),
561 MachineType p2 = MachineType::None(), 605 MachineType p2 = MachineType::None(),
562 MachineType p3 = MachineType::None()) 606 MachineType p3 = MachineType::None())
563 : zone(&allocator_), 607 : zone(&allocator_),
564 compiled_(false), 608 compiled_(false),
565 signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1, 609 signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
(...skipping 22 matching lines...) Expand all
588 compiler_.InitializeDescriptor(); 632 compiler_.InitializeDescriptor();
589 wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3); 633 wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3);
590 } 634 }
591 635
592 // Builds a graph from the given Wasm code and generates the machine 636 // Builds a graph from the given Wasm code and generates the machine
593 // code and call wrapper for that graph. This method must not be called 637 // code and call wrapper for that graph. This method must not be called
594 // more than once. 638 // more than once.
595 void Build(const byte* start, const byte* end) { 639 void Build(const byte* start, const byte* end) {
596 CHECK(!compiled_); 640 CHECK(!compiled_);
597 compiled_ = true; 641 compiled_ = true;
642 compiler_.Build(start, end);
598 643
599 // Build the TF graph within the compiler. 644 if (!interpret()) {
600 compiler_.Build(start, end); 645 // Compile machine code and install it into the module.
601 // Generate code. 646 Handle<Code> code = compiler_.Compile();
602 Handle<Code> code = compiler_.Compile();
603 647
604 if (compiler_.testing_module_) { 648 if (compiler_.testing_module_) {
605 // Update the table of function code in the module. 649 // Update the table of function code in the module.
606 compiler_.testing_module_->SetFunctionCode(compiler_.function_index_, 650 compiler_.testing_module_->SetFunctionCode(
607 code); 651 compiler_.function_->func_index, code);
652 }
653
654 wrapper_.SetInnerCode(code);
608 } 655 }
609
610 wrapper_.SetInnerCode(code);
611 } 656 }
612 657
613 ReturnType Call() { return Call(0, 0, 0, 0); } 658 ReturnType Call() {
659 if (interpret()) {
660 return CallInterpreter(Vector<WasmVal>(nullptr, 0));
661 } else {
662 return Call(0, 0, 0, 0);
663 }
664 }
614 665
615 template <typename P0> 666 template <typename P0>
616 ReturnType Call(P0 p0) { 667 ReturnType Call(P0 p0) {
617 return Call(p0, 0, 0, 0); 668 if (interpret()) {
669 WasmVal args[] = {WasmVal(p0)};
670 return CallInterpreter(ArrayVector(args));
671 } else {
672 return Call(p0, 0, 0, 0);
673 }
618 } 674 }
619 675
620 template <typename P0, typename P1> 676 template <typename P0, typename P1>
621 ReturnType Call(P0 p0, P1 p1) { 677 ReturnType Call(P0 p0, P1 p1) {
622 return Call(p0, p1, 0, 0); 678 if (interpret()) {
679 WasmVal args[] = {WasmVal(p0), WasmVal(p1)};
680 return CallInterpreter(ArrayVector(args));
681 } else {
682 return Call(p0, p1, 0, 0);
683 }
623 } 684 }
624 685
625 template <typename P0, typename P1, typename P2> 686 template <typename P0, typename P1, typename P2>
626 ReturnType Call(P0 p0, P1 p1, P2 p2) { 687 ReturnType Call(P0 p0, P1 p1, P2 p2) {
627 return Call(p0, p1, p2, 0); 688 if (interpret()) {
689 WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2)};
690 return CallInterpreter(ArrayVector(args));
691 } else {
692 return Call(p0, p1, p2, 0);
693 }
628 } 694 }
629 695
630 template <typename P0, typename P1, typename P2, typename P3> 696 template <typename P0, typename P1, typename P2, typename P3>
631 ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) { 697 ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
632 CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(), 698 if (interpret()) {
633 wrapper_.GetWrapperCode(), wrapper_.signature()); 699 WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2), WasmVal(p3)};
634 ReturnType return_value; 700 return CallInterpreter(ArrayVector(args));
635 int32_t result = runner.Call<void*, void*, void*, void*, void*>( 701 } else {
636 &p0, &p1, &p2, &p3, &return_value); 702 CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
637 CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result); 703 wrapper_.GetWrapperCode(),
638 return return_value; 704 wrapper_.signature());
705 ReturnType return_value;
706 int32_t result = runner.Call<void*, void*, void*, void*, void*>(
707 &p0, &p1, &p2, &p3, &return_value);
708 CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
709 return return_value;
710 }
711 }
712
713 ReturnType CallInterpreter(Vector<WasmVal> args) {
714 CHECK_EQ(args.length(),
715 static_cast<int>(compiler_.function_->sig->parameter_count()));
716 WasmInterpreter::Thread& thread = interpreter()->GetThread(0);
717 thread.Reset();
718 thread.PushFrame(compiler_.function_, args.start());
719 if (thread.Run() == WasmInterpreter::FINISHED) {
720 WasmVal val = thread.GetReturnValue();
721 return val.to<ReturnType>();
722 } else if (thread.state() == WasmInterpreter::TRAPPED) {
723 // TODO(titzer): return the correct trap code
724 int64_t result = 0xdeadbeefdeadbeef;
725 return static_cast<ReturnType>(result);
726 } else {
727 // TODO(titzer): falling off end
728 ReturnType val = 0;
729 return val;
730 }
639 } 731 }
640 732
641 byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); } 733 byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); }
642 734
735 WasmFunction* function() { return compiler_.function_; }
736 WasmInterpreter* interpreter() { return compiler_.interpreter_; }
737
643 protected: 738 protected:
644 v8::base::AccountingAllocator allocator_; 739 v8::base::AccountingAllocator allocator_;
645 Zone zone; 740 Zone zone;
646 bool compiled_; 741 bool compiled_;
647 LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS]; 742 LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS];
648 FunctionSig signature_; 743 FunctionSig signature_;
649 WasmFunctionCompiler compiler_; 744 WasmFunctionCompiler compiler_;
650 WasmFunctionWrapper<ReturnType> wrapper_; 745 WasmFunctionWrapper<ReturnType> wrapper_;
651 746
747 bool interpret() { return compiler_.execution_mode_ == kExecuteInterpreted; }
748
652 static size_t GetParameterCount(MachineType p0, MachineType p1, 749 static size_t GetParameterCount(MachineType p0, MachineType p1,
653 MachineType p2, MachineType p3) { 750 MachineType p2, MachineType p3) {
654 if (p0 == MachineType::None()) return 0; 751 if (p0 == MachineType::None()) return 0;
655 if (p1 == MachineType::None()) return 1; 752 if (p1 == MachineType::None()) return 1;
656 if (p2 == MachineType::None()) return 2; 753 if (p2 == MachineType::None()) return 2;
657 if (p3 == MachineType::None()) return 3; 754 if (p3 == MachineType::None()) return 3;
658 return 4; 755 return 4;
659 } 756 }
660 }; 757 };
661 758
662 // A macro to define tests that run in different engine configurations. 759 // A macro to define tests that run in different engine configurations.
663 // Currently only supports compiled tests, but a future 760 // Currently only supports compiled tests, but a future
664 // RunWasmInterpreted_##name version will allow each test to also run in the 761 // RunWasmInterpreted_##name version will allow each test to also run in the
665 // interpreter. 762 // interpreter.
666 #define WASM_EXEC_TEST(name) \ 763 #define WASM_EXEC_TEST(name) \
667 void RunWasm_##name(); \ 764 void RunWasm_##name(WasmExecutionMode execution_mode); \
668 TEST(RunWasmCompiled_##name) { RunWasm_##name(); } \ 765 TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \
669 void RunWasm_##name() 766 TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \
767 void RunWasm_##name(WasmExecutionMode execution_mode)
670 768
671 } // namespace 769 } // namespace
672 770
673 #endif 771 #endif
OLDNEW
« no previous file with comments | « test/cctest/wasm/test-run-wasm-interpreter.cc ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698