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

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

Issue 2551043002: [wasm] Make WasmRunner the central test structure (Closed)
Patch Set: Make DoCall return void - quickfix Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/wasm/test-wasm-trap-position.cc ('k') | no next file » | 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 <setjmp.h> 8 #include <setjmp.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 #include <stdlib.h> 10 #include <stdlib.h>
11 #include <string.h> 11 #include <string.h>
12 #include <array>
12 #include <memory> 13 #include <memory>
13 14
14 #include "src/base/utils/random-number-generator.h" 15 #include "src/base/utils/random-number-generator.h"
15 #include "src/zone/accounting-allocator.h" 16 #include "src/zone/accounting-allocator.h"
16 17
17 #include "src/compiler/compiler-source-position-table.h" 18 #include "src/compiler/compiler-source-position-table.h"
18 #include "src/compiler/graph-visualizer.h" 19 #include "src/compiler/graph-visualizer.h"
19 #include "src/compiler/int64-lowering.h" 20 #include "src/compiler/int64-lowering.h"
20 #include "src/compiler/js-graph.h" 21 #include "src/compiler/js-graph.h"
21 #include "src/compiler/node.h" 22 #include "src/compiler/node.h"
(...skipping 22 matching lines...) Expand all
44 // TODO(titzer): check traps more robustly in tests. 45 // TODO(titzer): check traps more robustly in tests.
45 // Currently, in tests, we just return 0xdeadbeef from the function in which 46 // Currently, in tests, we just return 0xdeadbeef from the function in which
46 // the trap occurs if the runtime context is not available to throw a JavaScript 47 // the trap occurs if the runtime context is not available to throw a JavaScript
47 // exception. 48 // exception.
48 #define CHECK_TRAP32(x) \ 49 #define CHECK_TRAP32(x) \
49 CHECK_EQ(0xdeadbeef, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF) 50 CHECK_EQ(0xdeadbeef, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF)
50 #define CHECK_TRAP64(x) \ 51 #define CHECK_TRAP64(x) \
51 CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF) 52 CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
52 #define CHECK_TRAP(x) CHECK_TRAP32(x) 53 #define CHECK_TRAP(x) CHECK_TRAP32(x)
53 54
54 #define WASM_RUNNER_MAX_NUM_PARAMETERS 4
55 #define WASM_WRAPPER_RETURN_VALUE 8754 55 #define WASM_WRAPPER_RETURN_VALUE 8754
56 56
57 #define BUILD(r, ...) \ 57 #define BUILD(r, ...) \
58 do { \ 58 do { \
59 byte code[] = {__VA_ARGS__}; \ 59 byte code[] = {__VA_ARGS__}; \
60 r.Build(code, code + arraysize(code)); \ 60 r.Build(code, code + arraysize(code)); \
61 } while (false) 61 } while (false)
62 62
63 namespace { 63 namespace {
64 using namespace v8::base; 64 using namespace v8::base;
65 using namespace v8::internal; 65 using namespace v8::internal;
66 using namespace v8::internal::compiler; 66 using namespace v8::internal::compiler;
67 using namespace v8::internal::wasm; 67 using namespace v8::internal::wasm;
68 68
69 const uint32_t kMaxGlobalsSize = 128; 69 const uint32_t kMaxGlobalsSize = 128;
70 70
71 // A helper for module environments that adds the ability to allocate memory 71 // A helper for module environments that adds the ability to allocate memory
72 // and global variables. Contains a built-in {WasmModule} and 72 // and global variables. Contains a built-in {WasmModule} and
73 // {WasmInstance}. 73 // {WasmInstance}.
74 class TestingModule : public ModuleEnv { 74 class TestingModule : public ModuleEnv {
75 public: 75 public:
76 explicit TestingModule(WasmExecutionMode mode = kExecuteCompiled) 76 explicit TestingModule(Zone* zone, WasmExecutionMode mode = kExecuteCompiled)
77 : ModuleEnv(&module_, &instance_), 77 : ModuleEnv(&module_, &instance_),
78 execution_mode_(mode), 78 execution_mode_(mode),
79 instance_(&module_), 79 instance_(&module_),
80 isolate_(CcTest::InitIsolateOnce()), 80 isolate_(CcTest::InitIsolateOnce()),
81 global_offset(0), 81 global_offset(0),
82 interpreter_(mode == kExecuteInterpreted 82 interpreter_(mode == kExecuteInterpreted
83 ? new WasmInterpreter( 83 ? new WasmInterpreter(
84 ModuleBytesEnv(&module_, &instance_, 84 ModuleBytesEnv(&module_, &instance_,
85 Vector<const byte>::empty()), 85 Vector<const byte>::empty()),
86 &allocator_) 86 zone->allocator())
87 : nullptr) { 87 : nullptr) {
88 instance->module = &module_; 88 instance->module = &module_;
89 instance->globals_start = global_data; 89 instance->globals_start = global_data;
90 module_.globals_size = kMaxGlobalsSize; 90 module_.globals_size = kMaxGlobalsSize;
91 instance->mem_start = nullptr; 91 instance->mem_start = nullptr;
92 instance->mem_size = 0; 92 instance->mem_size = 0;
93 memset(global_data, 0, sizeof(global_data)); 93 memset(global_data, 0, sizeof(global_data));
94 } 94 }
95 95
96 ~TestingModule() { 96 ~TestingModule() {
97 if (instance->mem_start) { 97 if (instance->mem_start) {
98 free(instance->mem_start); 98 free(instance->mem_start);
99 } 99 }
100 if (interpreter_) delete interpreter_; 100 if (interpreter_) delete interpreter_;
101 } 101 }
102 102
103 void ChangeOriginToAsmjs() { module_.origin = kAsmJsOrigin; } 103 void ChangeOriginToAsmjs() { module_.origin = kAsmJsOrigin; }
104 104
105 byte* AddMemory(uint32_t size) { 105 byte* AddMemory(uint32_t size) {
106 CHECK_NULL(instance->mem_start); 106 CHECK_NULL(instance->mem_start);
107 CHECK_EQ(0u, instance->mem_size); 107 CHECK_EQ(0, instance->mem_size);
108 instance->mem_start = reinterpret_cast<byte*>(malloc(size)); 108 instance->mem_start = reinterpret_cast<byte*>(malloc(size));
109 CHECK(instance->mem_start); 109 CHECK(instance->mem_start);
110 memset(instance->mem_start, 0, size); 110 memset(instance->mem_start, 0, size);
111 instance->mem_size = size; 111 instance->mem_size = size;
112 return raw_mem_start<byte>(); 112 return raw_mem_start<byte>();
113 } 113 }
114 114
115 template <typename T> 115 template <typename T>
116 T* AddMemoryElems(uint32_t count) { 116 T* AddMemoryElems(uint32_t count) {
117 AddMemory(count * sizeof(T)); 117 AddMemory(count * sizeof(T));
118 return raw_mem_start<T>(); 118 return raw_mem_start<T>();
119 } 119 }
120 120
121 template <typename T> 121 template <typename T>
122 T* AddGlobal(LocalType type) { 122 T* AddGlobal(
123 LocalType type = WasmOpcodes::LocalTypeFor(MachineTypeForC<T>())) {
123 const WasmGlobal* global = AddGlobal(type); 124 const WasmGlobal* global = AddGlobal(type);
124 return reinterpret_cast<T*>(instance->globals_start + global->offset); 125 return reinterpret_cast<T*>(instance->globals_start + global->offset);
125 } 126 }
126 127
127 byte AddSignature(FunctionSig* sig) { 128 byte AddSignature(FunctionSig* sig) {
128 module_.signatures.push_back(sig); 129 module_.signatures.push_back(sig);
129 size_t size = module->signatures.size(); 130 size_t size = module->signatures.size();
130 CHECK(size < 127); 131 CHECK(size < 127);
131 return static_cast<byte>(size - 1); 132 return static_cast<byte>(size - 1);
132 } 133 }
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 for (uint32_t i = 0; i < table_size; ++i) { 238 for (uint32_t i = 0; i < table_size; ++i) {
238 table.values.push_back(function_indexes[i]); 239 table.values.push_back(function_indexes[i]);
239 table.map.FindOrInsert(module_.functions[function_indexes[i]].sig); 240 table.map.FindOrInsert(module_.functions[function_indexes[i]].sig);
240 } 241 }
241 242
242 instance->function_tables.push_back( 243 instance->function_tables.push_back(
243 isolate_->factory()->NewFixedArray(table_size * 2)); 244 isolate_->factory()->NewFixedArray(table_size * 2));
244 } 245 }
245 246
246 void PopulateIndirectFunctionTable() { 247 void PopulateIndirectFunctionTable() {
248 if (execution_mode_ == kExecuteInterpreted) return;
247 // Initialize the fixed arrays in instance->function_tables. 249 // Initialize the fixed arrays in instance->function_tables.
248 for (uint32_t i = 0; i < instance->function_tables.size(); i++) { 250 for (uint32_t i = 0; i < instance->function_tables.size(); i++) {
249 WasmIndirectFunctionTable& table = module_.function_tables[i]; 251 WasmIndirectFunctionTable& table = module_.function_tables[i];
250 Handle<FixedArray> array = instance->function_tables[i]; 252 Handle<FixedArray> array = instance->function_tables[i];
251 int table_size = static_cast<int>(table.values.size()); 253 int table_size = static_cast<int>(table.values.size());
252 for (int j = 0; j < table_size; j++) { 254 for (int j = 0; j < table_size; j++) {
253 WasmFunction& function = module_.functions[table.values[j]]; 255 WasmFunction& function = module_.functions[table.values[j]];
254 array->set(j, Smi::FromInt(table.map.Find(function.sig))); 256 array->set(j, Smi::FromInt(table.map.Find(function.sig)));
255 array->set(j + table_size, 257 array->set(j + table_size,
256 *instance->function_code[function.func_index]); 258 *instance->function_code[function.func_index]);
257 } 259 }
258 } 260 }
259 } 261 }
260 262
261 WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; } 263 WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; }
262 264
263 WasmInterpreter* interpreter() { return interpreter_; } 265 WasmInterpreter* interpreter() { return interpreter_; }
264 WasmExecutionMode execution_mode() { return execution_mode_; } 266 WasmExecutionMode execution_mode() { return execution_mode_; }
267 Isolate* isolate() { return isolate_; }
265 268
266 private: 269 private:
267 WasmExecutionMode execution_mode_; 270 WasmExecutionMode execution_mode_;
268 WasmModule module_; 271 WasmModule module_;
269 WasmInstance instance_; 272 WasmInstance instance_;
270 Isolate* isolate_; 273 Isolate* isolate_;
271 v8::internal::AccountingAllocator allocator_;
272 uint32_t global_offset; 274 uint32_t global_offset;
273 V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data. 275 V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data.
274 WasmInterpreter* interpreter_; 276 WasmInterpreter* interpreter_;
275 277
276 const WasmGlobal* AddGlobal(LocalType type) { 278 const WasmGlobal* AddGlobal(LocalType type) {
277 byte size = WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(type)); 279 byte size = WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(type));
278 global_offset = (global_offset + size - 1) & ~(size - 1); // align 280 global_offset = (global_offset + size - 1) & ~(size - 1); // align
279 module_.globals.push_back( 281 module_.globals.push_back(
280 {type, true, WasmInitExpr(), global_offset, false, false}); 282 {type, true, WasmInitExpr(), global_offset, false, false});
281 global_offset += size; 283 global_offset += size;
(...skipping 25 matching lines...) Expand all
307 if (result.error_pt) str << ", pt = +" << pt; 309 if (result.error_pt) str << ", pt = +" << pt;
308 str << ", msg = " << result.error_msg.get(); 310 str << ", msg = " << result.error_msg.get();
309 FATAL(str.str().c_str()); 311 FATAL(str.str().c_str());
310 } 312 }
311 builder.Int64LoweringForTesting(); 313 builder.Int64LoweringForTesting();
312 if (!CpuFeatures::SupportsSimd128()) { 314 if (!CpuFeatures::SupportsSimd128()) {
313 builder.SimdScalarLoweringForTesting(); 315 builder.SimdScalarLoweringForTesting();
314 } 316 }
315 } 317 }
316 318
317 template <typename ReturnType> 319 class WasmFunctionWrapper : private GraphAndBuilders {
318 class WasmFunctionWrapper : public HandleAndZoneScope,
319 private GraphAndBuilders {
320 public: 320 public:
321 WasmFunctionWrapper() 321 explicit WasmFunctionWrapper(Zone* zone, int num_params)
322 : GraphAndBuilders(main_zone()), 322 : GraphAndBuilders(zone), inner_code_node_(nullptr), signature_(nullptr) {
323 inner_code_node_(nullptr),
324 signature_(nullptr) {
325 // One additional parameter for the pointer to the return value memory. 323 // One additional parameter for the pointer to the return value memory.
326 Signature<MachineType>::Builder sig_builder( 324 Signature<MachineType>::Builder sig_builder(zone, 1, num_params + 1);
327 zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
328 325
329 sig_builder.AddReturn(MachineType::Int32()); 326 sig_builder.AddReturn(MachineType::Int32());
330 for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) { 327 for (int i = 0; i < num_params + 1; i++) {
331 sig_builder.AddParam(MachineType::Pointer()); 328 sig_builder.AddParam(MachineType::Pointer());
332 } 329 }
333 signature_ = sig_builder.Build(); 330 signature_ = sig_builder.Build();
334 } 331 }
335 332
336 void Init(CallDescriptor* descriptor, MachineType p0 = MachineType::None(), 333 void Init(CallDescriptor* descriptor, MachineType return_type,
337 MachineType p1 = MachineType::None(), 334 Vector<MachineType> param_types) {
338 MachineType p2 = MachineType::None(), 335 DCHECK_NOT_NULL(descriptor);
339 MachineType p3 = MachineType::None()) { 336 DCHECK_EQ(signature_->parameter_count(), param_types.length() + 1);
340 // Create the TF graph for the wrapper. The wrapper always takes four 337
341 // pointers as parameters, but may not pass the values of all pointers to 338 // Create the TF graph for the wrapper.
342 // the actual test function.
343 339
344 // Function, effect, and control. 340 // Function, effect, and control.
345 Node** parameters = 341 Node** parameters = zone()->NewArray<Node*>(param_types.length() + 3);
346 zone()->template NewArray<Node*>(WASM_RUNNER_MAX_NUM_PARAMETERS + 3);
347 graph()->SetStart(graph()->NewNode(common()->Start(6))); 342 graph()->SetStart(graph()->NewNode(common()->Start(6)));
348 Node* effect = graph()->start(); 343 Node* effect = graph()->start();
349 int parameter_count = 0; 344 int parameter_count = 0;
350 345
351 // Dummy node which gets replaced in SetInnerCode. 346 // Dummy node which gets replaced in SetInnerCode.
352 inner_code_node_ = graph()->NewNode(common()->Int32Constant(0)); 347 inner_code_node_ = graph()->NewNode(common()->Int32Constant(0));
353 parameters[parameter_count++] = inner_code_node_; 348 parameters[parameter_count++] = inner_code_node_;
354 349
355 if (p0 != MachineType::None()) { 350 int param_idx = 0;
351 for (MachineType t : param_types) {
352 DCHECK_NE(MachineType::None(), t);
356 parameters[parameter_count] = graph()->NewNode( 353 parameters[parameter_count] = graph()->NewNode(
357 machine()->Load(p0), 354 machine()->Load(t),
358 graph()->NewNode(common()->Parameter(0), graph()->start()), 355 graph()->NewNode(common()->Parameter(param_idx++), graph()->start()),
359 graph()->NewNode(common()->Int32Constant(0)), effect, 356 graph()->NewNode(common()->Int32Constant(0)), effect,
360 graph()->start()); 357 graph()->start());
361 effect = parameters[parameter_count++]; 358 effect = parameters[parameter_count++];
362 }
363 if (p1 != MachineType::None()) {
364 parameters[parameter_count] = graph()->NewNode(
365 machine()->Load(p1),
366 graph()->NewNode(common()->Parameter(1), graph()->start()),
367 graph()->NewNode(common()->Int32Constant(0)), effect,
368 graph()->start());
369 effect = parameters[parameter_count++];
370 }
371 if (p2 != MachineType::None()) {
372 parameters[parameter_count] = graph()->NewNode(
373 machine()->Load(p2),
374 graph()->NewNode(common()->Parameter(2), graph()->start()),
375 graph()->NewNode(common()->Int32Constant(0)), effect,
376 graph()->start());
377 effect = parameters[parameter_count++];
378 }
379 if (p3 != MachineType::None()) {
380 parameters[parameter_count] = graph()->NewNode(
381 machine()->Load(p3),
382 graph()->NewNode(common()->Parameter(3), graph()->start()),
383 graph()->NewNode(common()->Int32Constant(0)), effect,
384 graph()->start());
385 effect = parameters[parameter_count++];
386 } 359 }
387 360
388 parameters[parameter_count++] = effect; 361 parameters[parameter_count++] = effect;
389 parameters[parameter_count++] = graph()->start(); 362 parameters[parameter_count++] = graph()->start();
390 Node* call = graph()->NewNode(common()->Call(descriptor), parameter_count, 363 Node* call = graph()->NewNode(common()->Call(descriptor), parameter_count,
391 parameters); 364 parameters);
392 365
393 effect = graph()->NewNode( 366 if (!return_type.IsNone()) {
394 machine()->Store( 367 effect = graph()->NewNode(
395 StoreRepresentation(MachineTypeForC<ReturnType>().representation(), 368 machine()->Store(StoreRepresentation(
396 WriteBarrierKind::kNoWriteBarrier)), 369 return_type.representation(), WriteBarrierKind::kNoWriteBarrier)),
397 graph()->NewNode(common()->Parameter(WASM_RUNNER_MAX_NUM_PARAMETERS), 370 graph()->NewNode(common()->Parameter(param_types.length()),
398 graph()->start()), 371 graph()->start()),
399 graph()->NewNode(common()->Int32Constant(0)), call, effect, 372 graph()->NewNode(common()->Int32Constant(0)), call, effect,
400 graph()->start()); 373 graph()->start());
374 }
401 Node* zero = graph()->NewNode(common()->Int32Constant(0)); 375 Node* zero = graph()->NewNode(common()->Int32Constant(0));
402 Node* r = graph()->NewNode( 376 Node* r = graph()->NewNode(
403 common()->Return(), zero, 377 common()->Return(), zero,
404 graph()->NewNode(common()->Int32Constant(WASM_WRAPPER_RETURN_VALUE)), 378 graph()->NewNode(common()->Int32Constant(WASM_WRAPPER_RETURN_VALUE)),
405 effect, graph()->start()); 379 effect, graph()->start());
406 graph()->SetEnd(graph()->NewNode(common()->End(2), r, graph()->start())); 380 graph()->SetEnd(graph()->NewNode(common()->End(2), r, graph()->start()));
407 } 381 }
408 382
383 template <typename ReturnType, typename... ParamTypes>
384 void Init(CallDescriptor* descriptor) {
385 std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{
386 {MachineTypeForC<ParamTypes>()...}};
387 Vector<MachineType> param_vec(param_machine_types.data(),
388 param_machine_types.size());
389 Init(descriptor, MachineTypeForC<ReturnType>(), param_vec);
390 }
391
409 void SetInnerCode(Handle<Code> code_handle) { 392 void SetInnerCode(Handle<Code> code_handle) {
410 NodeProperties::ChangeOp(inner_code_node_, 393 NodeProperties::ChangeOp(inner_code_node_,
411 common()->HeapConstant(code_handle)); 394 common()->HeapConstant(code_handle));
412 } 395 }
413 396
414 Handle<Code> GetWrapperCode() { 397 Handle<Code> GetWrapperCode() {
415 if (code_.is_null()) { 398 if (code_.is_null()) {
416 Isolate* isolate = CcTest::InitIsolateOnce(); 399 Isolate* isolate = CcTest::InitIsolateOnce();
417 400
418 CallDescriptor* descriptor = 401 CallDescriptor* descriptor =
419 Linkage::GetSimplifiedCDescriptor(zone(), signature_, true); 402 Linkage::GetSimplifiedCDescriptor(zone(), signature_, true);
420 403
421 if (kPointerSize == 4) { 404 if (kPointerSize == 4) {
405 size_t num_params = signature_->parameter_count();
422 // One additional parameter for the pointer of the return value. 406 // One additional parameter for the pointer of the return value.
423 Signature<MachineRepresentation>::Builder rep_builder( 407 Signature<MachineRepresentation>::Builder rep_builder(zone(), 1,
424 zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1); 408 num_params + 1);
425 409
426 rep_builder.AddReturn(MachineRepresentation::kWord32); 410 rep_builder.AddReturn(MachineRepresentation::kWord32);
427 for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) { 411 for (size_t i = 0; i < num_params + 1; i++) {
428 rep_builder.AddParam(MachineRepresentation::kWord32); 412 rep_builder.AddParam(MachineRepresentation::kWord32);
429 } 413 }
430 Int64Lowering r(graph(), machine(), common(), zone(), 414 Int64Lowering r(graph(), machine(), common(), zone(),
431 rep_builder.Build()); 415 rep_builder.Build());
432 r.LowerGraph(); 416 r.LowerGraph();
433 } 417 }
434 418
435 CompilationInfo info(ArrayVector("testing"), isolate, graph()->zone(), 419 CompilationInfo info(ArrayVector("testing"), isolate, graph()->zone(),
436 Code::ComputeFlags(Code::STUB)); 420 Code::ComputeFlags(Code::STUB));
437 code_ = 421 code_ =
(...skipping 11 matching lines...) Expand all
449 } 433 }
450 434
451 Signature<MachineType>* signature() const { return signature_; } 435 Signature<MachineType>* signature() const { return signature_; }
452 436
453 private: 437 private:
454 Node* inner_code_node_; 438 Node* inner_code_node_;
455 Handle<Code> code_; 439 Handle<Code> code_;
456 Signature<MachineType>* signature_; 440 Signature<MachineType>* signature_;
457 }; 441 };
458 442
459 // A helper for compiling WASM functions for testing. This class can create a 443 // A helper for compiling WASM functions for testing.
460 // standalone function if {module} is NULL or a function within a 444 // It contains the internal state for compilation (i.e. TurboFan graph) and
461 // {TestingModule}. It contains the internal state for compilation (i.e. 445 // interpretation (by adding to the interpreter manually).
462 // TurboFan graph) and interpretation (by adding to the interpreter manually). 446 class WasmFunctionCompiler : private GraphAndBuilders {
463 class WasmFunctionCompiler : public HandleAndZoneScope,
464 private GraphAndBuilders {
465 public: 447 public:
466 explicit WasmFunctionCompiler( 448 Isolate* isolate() { return testing_module_->isolate(); }
467 FunctionSig* sig, WasmExecutionMode mode,
468 Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
469 : GraphAndBuilders(main_zone()),
470 execution_mode_(mode),
471 jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
472 nullptr, this->machine()),
473 sig(sig),
474 descriptor_(nullptr),
475 testing_module_(nullptr),
476 debug_name_(debug_name),
477 local_decls(main_zone(), sig),
478 source_position_table_(this->graph()),
479 interpreter_(nullptr) {
480 // Create our own function.
481 function_ = new WasmFunction();
482 function_->sig = sig;
483 function_->func_index = 0;
484 function_->sig_index = 0;
485 if (mode == kExecuteInterpreted) {
486 ModuleBytesEnv empty_env(nullptr, nullptr, Vector<const byte>::empty());
487 interpreter_ = new WasmInterpreter(empty_env, zone()->allocator());
488 int index = interpreter_->AddFunctionForTesting(function_);
489 CHECK_EQ(0, index);
490 }
491 }
492
493 explicit WasmFunctionCompiler(
494 FunctionSig* sig, TestingModule* module,
495 Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
496 : GraphAndBuilders(main_zone()),
497 execution_mode_(module->execution_mode()),
498 jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
499 nullptr, this->machine()),
500 sig(sig),
501 descriptor_(nullptr),
502 testing_module_(module),
503 debug_name_(debug_name),
504 local_decls(main_zone(), sig),
505 source_position_table_(this->graph()),
506 interpreter_(module->interpreter()) {
507 // Get a new function from the testing module.
508 int index = module->AddFunction(sig, Handle<Code>::null());
509 function_ = testing_module_->GetFunctionAt(index);
510 }
511
512 ~WasmFunctionCompiler() {
513 if (testing_module_) return; // testing module owns the below things.
514 delete function_;
515 if (interpreter_) delete interpreter_;
516 }
517
518 WasmExecutionMode execution_mode_;
519 JSGraph jsgraph;
520 FunctionSig* sig;
521 // The call descriptor is initialized when the function is compiled.
522 CallDescriptor* descriptor_;
523 TestingModule* testing_module_;
524 Vector<const char> debug_name_;
525 WasmFunction* function_;
526 LocalDeclEncoder local_decls;
527 SourcePositionTable source_position_table_;
528 WasmInterpreter* interpreter_;
529
530 Isolate* isolate() { return main_isolate(); }
531 Graph* graph() const { return main_graph_; } 449 Graph* graph() const { return main_graph_; }
532 Zone* zone() const { return graph()->zone(); } 450 Zone* zone() const { return graph()->zone(); }
533 CommonOperatorBuilder* common() { return &main_common_; } 451 CommonOperatorBuilder* common() { return &main_common_; }
534 MachineOperatorBuilder* machine() { return &main_machine_; } 452 MachineOperatorBuilder* machine() { return &main_machine_; }
535 void InitializeDescriptor() { 453 CallDescriptor* descriptor() {
536 if (descriptor_ == nullptr) { 454 if (descriptor_ == nullptr) {
537 descriptor_ = testing_module_->GetWasmCallDescriptor(main_zone(), sig); 455 descriptor_ = testing_module_->GetWasmCallDescriptor(zone(), sig);
538 } 456 }
457 return descriptor_;
539 } 458 }
540 CallDescriptor* descriptor() { return descriptor_; }
541 uint32_t function_index() { return function_->func_index; } 459 uint32_t function_index() { return function_->func_index; }
542 460
543 void Build(const byte* start, const byte* end) { 461 void Build(const byte* start, const byte* end) {
544 // Build the TurboFan graph. 462 local_decls.Prepend(zone(), &start, &end);
545 local_decls.Prepend(main_zone(), &start, &end);
546 TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig,
547 &source_position_table_, start, end);
548 if (interpreter_) { 463 if (interpreter_) {
549 // Add the code to the interpreter. 464 // Add the code to the interpreter.
550 CHECK(interpreter_->SetFunctionCodeForTesting(function_, start, end)); 465 CHECK(interpreter_->SetFunctionCodeForTesting(function_, start, end));
466 return;
551 } 467 }
468
469 // Build the TurboFan graph.
470 TestBuildingGraph(zone(), &jsgraph, testing_module_, sig,
471 &source_position_table_, start, end);
472 Handle<Code> code = Compile();
473 testing_module_->SetFunctionCode(function_index(), code);
552 } 474 }
553 475
554 byte AllocateLocal(LocalType type) { 476 byte AllocateLocal(LocalType type) {
555 uint32_t index = local_decls.AddLocals(1, type); 477 uint32_t index = local_decls.AddLocals(1, type);
556 byte result = static_cast<byte>(index); 478 byte result = static_cast<byte>(index);
557 DCHECK_EQ(index, result); 479 DCHECK_EQ(index, result);
558 return result; 480 return result;
559 } 481 }
560 482
483 void SetSigIndex(int sig_index) { function_->sig_index = sig_index; }
484
485 private:
486 friend class WasmRunnerBase;
487
488 explicit WasmFunctionCompiler(Zone* zone, FunctionSig* sig,
489 TestingModule* module)
490 : GraphAndBuilders(zone),
491 jsgraph(module->isolate(), this->graph(), this->common(), nullptr,
492 nullptr, this->machine()),
493 sig(sig),
494 descriptor_(nullptr),
495 testing_module_(module),
496 local_decls(zone, sig),
497 source_position_table_(this->graph()),
498 interpreter_(module->interpreter()) {
499 // Get a new function from the testing module.
500 int index = module->AddFunction(sig, Handle<Code>::null());
501 function_ = testing_module_->GetFunctionAt(index);
502 }
503
561 Handle<Code> Compile() { 504 Handle<Code> Compile() {
562 InitializeDescriptor(); 505 CallDescriptor* desc = descriptor();
563 CallDescriptor* desc = descriptor_;
564 if (kPointerSize == 4) { 506 if (kPointerSize == 4) {
565 desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc); 507 desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
566 } 508 }
567 CompilationInfo info(debug_name_, this->isolate(), this->zone(), 509 CompilationInfo info(CStrVector("wasm"), this->isolate(), this->zone(),
568 Code::ComputeFlags(Code::WASM_FUNCTION)); 510 Code::ComputeFlags(Code::WASM_FUNCTION));
569 std::unique_ptr<CompilationJob> job(Pipeline::NewWasmCompilationJob( 511 std::unique_ptr<CompilationJob> job(Pipeline::NewWasmCompilationJob(
570 &info, &jsgraph, desc, &source_position_table_, nullptr)); 512 &info, &jsgraph, desc, &source_position_table_, nullptr));
571 if (job->ExecuteJob() != CompilationJob::SUCCEEDED || 513 if (job->ExecuteJob() != CompilationJob::SUCCEEDED ||
572 job->FinalizeJob() != CompilationJob::SUCCEEDED) 514 job->FinalizeJob() != CompilationJob::SUCCEEDED)
573 return Handle<Code>::null(); 515 return Handle<Code>::null();
574 516
575 Handle<Code> code = info.code(); 517 Handle<Code> code = info.code();
576 518
577 // Length is always 2, since usually <wasm_obj, func_index> is stored in 519 // Length is always 2, since usually <wasm_obj, func_index> is stored in
578 // the deopt data. Here, we only store the function index. 520 // the deopt data. Here, we only store the function index.
579 DCHECK(code->deoptimization_data() == nullptr || 521 DCHECK(code->deoptimization_data() == nullptr ||
580 code->deoptimization_data()->length() == 0); 522 code->deoptimization_data()->length() == 0);
581 Handle<FixedArray> deopt_data = 523 Handle<FixedArray> deopt_data =
582 isolate()->factory()->NewFixedArray(2, TENURED); 524 isolate()->factory()->NewFixedArray(2, TENURED);
583 deopt_data->set(1, Smi::FromInt(static_cast<int>(function_index()))); 525 deopt_data->set(1, Smi::FromInt(static_cast<int>(function_index())));
584 deopt_data->set_length(2); 526 deopt_data->set_length(2);
585 code->set_deoptimization_data(*deopt_data); 527 code->set_deoptimization_data(*deopt_data);
586 528
587 #ifdef ENABLE_DISASSEMBLER 529 #ifdef ENABLE_DISASSEMBLER
588 if (FLAG_print_opt_code) { 530 if (FLAG_print_opt_code) {
589 OFStream os(stdout); 531 OFStream os(stdout);
590 code->Disassemble("wasm code", os); 532 code->Disassemble("wasm code", os);
591 } 533 }
592 #endif 534 #endif
593 535
594 return code; 536 return code;
595 } 537 }
596 538
597 uint32_t CompileAndAdd(uint16_t sig_index = 0) { 539 JSGraph jsgraph;
598 CHECK(testing_module_); 540 FunctionSig* sig;
599 function_->sig_index = sig_index; 541 // The call descriptor is initialized when the function is compiled.
600 Handle<Code> code = Compile(); 542 CallDescriptor* descriptor_;
601 testing_module_->SetFunctionCode(function_index(), code); 543 TestingModule* testing_module_;
602 return function_index(); 544 Vector<const char> debug_name_;
603 } 545 WasmFunction* function_;
604 546 LocalDeclEncoder local_decls;
605 // Set the context, such that e.g. runtime functions can be called. 547 SourcePositionTable source_position_table_;
606 void SetModuleContext() { 548 WasmInterpreter* interpreter_;
607 if (!testing_module_->instance->context.is_null()) {
608 CHECK(testing_module_->instance->context.is_identical_to(
609 main_isolate()->native_context()));
610 return;
611 }
612 testing_module_->instance->context = main_isolate()->native_context();
613 }
614 }; 549 };
615 550
616 template <typename ReturnType> 551 // A helper class to build a module around Wasm bytecode, generate machine
617 union ReturnTypeUnion {
618 ReturnType value;
619 uint64_t trap;
620 };
621
622 // A helper class to build graphs from Wasm bytecode, generate machine
623 // code, and run that code. 552 // code, and run that code.
624 template <typename ReturnType> 553 class WasmRunnerBase : public HandleAndZoneScope {
625 class WasmRunner {
626 public: 554 public:
627 WasmRunner(WasmExecutionMode execution_mode, 555 explicit WasmRunnerBase(WasmExecutionMode execution_mode, int num_params)
628 MachineType p0 = MachineType::None(), 556 : zone_(&allocator_, ZONE_NAME),
629 MachineType p1 = MachineType::None(), 557 module_(&zone_, execution_mode),
630 MachineType p2 = MachineType::None(), 558 wrapper_(&zone_, num_params) {}
631 MachineType p3 = MachineType::None())
632 : zone(&allocator_, ZONE_NAME),
633 compiled_(false),
634 signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
635 GetParameterCount(p0, p1, p2, p3), storage_),
636 compiler_(&signature_, execution_mode) {
637 InitSigStorage(p0, p1, p2, p3);
638 }
639
640 WasmRunner(TestingModule* module, MachineType p0 = MachineType::None(),
641 MachineType p1 = MachineType::None(),
642 MachineType p2 = MachineType::None(),
643 MachineType p3 = MachineType::None())
644 : zone(&allocator_, ZONE_NAME),
645 compiled_(false),
646 signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
647 GetParameterCount(p0, p1, p2, p3), storage_),
648 compiler_(&signature_, module),
649 possible_nondeterminism_(false) {
650 DCHECK(module);
651 InitSigStorage(p0, p1, p2, p3);
652 }
653
654 void InitSigStorage(MachineType p0, MachineType p1, MachineType p2,
655 MachineType p3) {
656 int index = 0;
657 MachineType ret = MachineTypeForC<ReturnType>();
658 if (ret != MachineType::None()) {
659 storage_[index++] = WasmOpcodes::LocalTypeFor(ret);
660 }
661 if (p0 != MachineType::None())
662 storage_[index++] = WasmOpcodes::LocalTypeFor(p0);
663 if (p1 != MachineType::None())
664 storage_[index++] = WasmOpcodes::LocalTypeFor(p1);
665 if (p2 != MachineType::None())
666 storage_[index++] = WasmOpcodes::LocalTypeFor(p2);
667 if (p3 != MachineType::None())
668 storage_[index++] = WasmOpcodes::LocalTypeFor(p3);
669
670 compiler_.InitializeDescriptor();
671 wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3);
672 }
673 559
674 // Builds a graph from the given Wasm code and generates the machine 560 // Builds a graph from the given Wasm code and generates the machine
675 // code and call wrapper for that graph. This method must not be called 561 // code and call wrapper for that graph. This method must not be called
676 // more than once. 562 // more than once.
677 void Build(const byte* start, const byte* end) { 563 void Build(const byte* start, const byte* end) {
678 CHECK(!compiled_); 564 CHECK(!compiled_);
679 compiled_ = true; 565 compiled_ = true;
680 compiler_.Build(start, end); 566 functions_[0]->Build(start, end);
567 }
681 568
569 // Resets the state for building the next function.
570 // The main function called will always be the first function.
571 template <typename ReturnType, typename... ParamTypes>
572 WasmFunctionCompiler& NewFunction() {
573 return NewFunction(CreateSig<ReturnType, ParamTypes...>());
574 }
575
576 // Resets the state for building the next function.
577 // The main function called will be the last generated function.
578 // Returns the index of the previously built function.
579 WasmFunctionCompiler& NewFunction(FunctionSig* sig) {
580 functions_.emplace_back(new WasmFunctionCompiler(&zone_, sig, &module_));
581 return *functions_.back();
582 }
583
584 byte AllocateLocal(LocalType type) {
585 return functions_[0]->AllocateLocal(type);
586 }
587
588 WasmFunction* function() { return functions_[0]->function_; }
589 WasmInterpreter* interpreter() { return functions_[0]->interpreter_; }
590 bool possible_nondeterminism() { return possible_nondeterminism_; }
591 TestingModule& module() { return module_; }
592 Zone* zone() { return &zone_; }
593
594 // Set the context, such that e.g. runtime functions can be called.
595 void SetModuleContext() {
596 if (!module_.instance->context.is_null()) {
597 CHECK(module_.instance->context.is_identical_to(
598 main_isolate()->native_context()));
599 return;
600 }
601 module_.instance->context = main_isolate()->native_context();
602 }
603
604 private:
605 FunctionSig* CreateSig(MachineType return_type,
606 Vector<MachineType> param_types) {
607 int return_count = return_type.IsNone() ? 0 : 1;
608 int param_count = param_types.length();
609
610 // Allocate storage array in zone.
611 LocalType* sig_types =
612 zone_.NewArray<LocalType>(return_count + param_count);
613
614 // Convert machine types to local types, and check that there are no
615 // MachineType::None()'s in the parameters.
616 int idx = 0;
617 if (return_count) sig_types[idx++] = WasmOpcodes::LocalTypeFor(return_type);
618 for (MachineType param : param_types) {
619 CHECK_NE(MachineType::None(), param);
620 sig_types[idx++] = WasmOpcodes::LocalTypeFor(param);
621 }
622 return new (&zone_) FunctionSig(return_count, param_count, sig_types);
623 }
624
625 template <typename ReturnType, typename... ParamTypes>
626 FunctionSig* CreateSig() {
627 std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{
628 {MachineTypeForC<ParamTypes>()...}};
629 Vector<MachineType> param_vec(param_machine_types.data(),
630 param_machine_types.size());
631 return CreateSig(MachineTypeForC<ReturnType>(), param_vec);
632 }
633
634 protected:
635 v8::internal::AccountingAllocator allocator_;
636 Zone zone_;
637 TestingModule module_;
638 std::vector<std::unique_ptr<WasmFunctionCompiler>> functions_;
639 WasmFunctionWrapper wrapper_;
640 bool compiled_ = false;
641 bool possible_nondeterminism_ = false;
642
643 bool interpret() { return module_.execution_mode() == kExecuteInterpreted; }
644
645 public:
646 // This field has to be static. Otherwise, gcc complains about the using in
647 // the lambda context below.
648 static jmp_buf jump_buffer;
649 };
650
651 template <typename ReturnType, typename... ParamTypes>
652 class WasmRunner : public WasmRunnerBase {
653 public:
654 explicit WasmRunner(WasmExecutionMode execution_mode)
655 : WasmRunnerBase(execution_mode, sizeof...(ParamTypes)) {
656 NewFunction<ReturnType, ParamTypes...>();
682 if (!interpret()) { 657 if (!interpret()) {
683 // Compile machine code and install it into the module. 658 wrapper_.Init<ReturnType, ParamTypes...>(functions_[0]->descriptor());
684 Handle<Code> code = compiler_.Compile();
685
686 if (compiler_.testing_module_) {
687 // Update the table of function code in the module.
688 compiler_.testing_module_->SetFunctionCode(
689 compiler_.function_->func_index, code);
690 }
691
692 wrapper_.SetInnerCode(code);
693 } 659 }
694 } 660 }
695 661
696 ReturnType Call() { 662 ReturnType Call(ParamTypes... p) {
697 if (interpret()) { 663 DCHECK(compiled_);
698 return CallInterpreter(Vector<WasmVal>(nullptr, 0)); 664 if (interpret()) return CallInterpreter(p...);
699 } else { 665
700 return Call(0, 0, 0, 0); 666 // Use setjmp/longjmp to deal with traps in WebAssembly code.
701 } 667 // Make the return value volatile, to give defined semantics if accessed
668 // after setjmp.
669 volatile ReturnType return_value =
670 static_cast<ReturnType>(0xdeadbeefdeadbeef);
671 int jump_value = setjmp(WasmRunnerBase::jump_buffer);
672 // jump_value == 0 --> first return; jump_value == 1 --> longjmp happened.
673 if (!jump_value) DoCall(&return_value, p...);
674 return return_value;
702 } 675 }
703 676
704 template <typename P0> 677 ReturnType CallInterpreter(ParamTypes... p) {
705 ReturnType Call(P0 p0) {
706 if (interpret()) {
707 WasmVal args[] = {WasmVal(p0)};
708 return CallInterpreter(ArrayVector(args));
709 } else {
710 return Call(p0, 0, 0, 0);
711 }
712 }
713
714 template <typename P0, typename P1>
715 ReturnType Call(P0 p0, P1 p1) {
716 if (interpret()) {
717 WasmVal args[] = {WasmVal(p0), WasmVal(p1)};
718 return CallInterpreter(ArrayVector(args));
719 } else {
720 return Call(p0, p1, 0, 0);
721 }
722 }
723
724 template <typename P0, typename P1, typename P2>
725 ReturnType Call(P0 p0, P1 p1, P2 p2) {
726 if (interpret()) {
727 WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2)};
728 return CallInterpreter(ArrayVector(args));
729 } else {
730 return Call(p0, p1, p2, 0);
731 }
732 }
733
734 static jmp_buf jump_buffer;
735 static int jump_value;
736 static ReturnTypeUnion<ReturnType> return_value;
737
738 template <typename P0, typename P1, typename P2, typename P3>
739 void DoCall(P0 p0, P1 p1, P2 p2, P3 p3) {
740 auto trap_callback = []() {
741 WasmRunner<ReturnType>::return_value.trap = 0xdeadbeefdeadbeef;
742 longjmp(WasmRunner<ReturnType>::jump_buffer, 1);
743 };
744 set_trap_callback_for_testing(trap_callback);
745 CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
746 wrapper_.GetWrapperCode(), wrapper_.signature());
747
748 int32_t result = runner.Call<void*, void*, void*, void*, void*>(
749 &p0, &p1, &p2, &p3, &WasmRunner<ReturnType>::return_value.value);
750 CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
751 }
752
753 template <typename P0, typename P1, typename P2, typename P3>
754 ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
755 if (interpret()) {
756 WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2), WasmVal(p3)};
757 return CallInterpreter(ArrayVector(args));
758 } else {
759 // Use setjmp/longjmp to deal with traps in WebAssembly code.
760 WasmRunner<ReturnType>::jump_value =
761 setjmp(WasmRunner<ReturnType>::jump_buffer);
762 if (!WasmRunner<ReturnType>::jump_value) {
763 DoCall(p0, p1, p2, p3);
764 }
765 set_trap_callback_for_testing(nullptr);
766 return WasmRunner<ReturnType>::return_value.value;
767 }
768 }
769
770 ReturnType CallInterpreter(Vector<WasmVal> args) {
771 CHECK_EQ(args.length(),
772 static_cast<int>(compiler_.function_->sig->parameter_count()));
773 WasmInterpreter::Thread* thread = interpreter()->GetThread(0); 678 WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
774 thread->Reset(); 679 thread->Reset();
775 thread->PushFrame(compiler_.function_, args.start()); 680 std::array<WasmVal, sizeof...(p)> args{{WasmVal(p)...}};
681 thread->PushFrame(function(), args.data());
776 if (thread->Run() == WasmInterpreter::FINISHED) { 682 if (thread->Run() == WasmInterpreter::FINISHED) {
777 WasmVal val = thread->GetReturnValue(); 683 WasmVal val = thread->GetReturnValue();
778 possible_nondeterminism_ |= thread->PossibleNondeterminism(); 684 possible_nondeterminism_ |= thread->PossibleNondeterminism();
779 return val.to<ReturnType>(); 685 return val.to<ReturnType>();
780 } else if (thread->state() == WasmInterpreter::TRAPPED) { 686 } else if (thread->state() == WasmInterpreter::TRAPPED) {
781 // TODO(titzer): return the correct trap code 687 // TODO(titzer): return the correct trap code
782 int64_t result = 0xdeadbeefdeadbeef; 688 int64_t result = 0xdeadbeefdeadbeef;
783 return static_cast<ReturnType>(result); 689 return static_cast<ReturnType>(result);
784 } else { 690 } else {
785 // TODO(titzer): falling off end 691 // TODO(titzer): falling off end
786 ReturnType val = 0; 692 return ReturnType{0};
787 return val;
788 } 693 }
789 } 694 }
790 695
791 byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); } 696 private:
697 // Don't inline this function. The setjmp above should be followed immediately
698 // by a call.
699 V8_NOINLINE void DoCall(volatile ReturnType* return_value, ParamTypes... p) {
700 auto trap_callback = []() -> void {
701 set_trap_callback_for_testing(nullptr);
702 longjmp(WasmRunnerBase::jump_buffer, 1);
703 };
704 set_trap_callback_for_testing(trap_callback);
792 705
793 WasmFunction* function() { return compiler_.function_; } 706 wrapper_.SetInnerCode(
794 WasmInterpreter* interpreter() { return compiler_.interpreter_; } 707 module_.GetFunctionCode(functions_[0]->function_index()));
795 bool possible_nondeterminism() { return possible_nondeterminism_; } 708 CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
796 709 wrapper_.GetWrapperCode(), wrapper_.signature());
797 protected: 710 ReturnType return_value_local;
798 v8::internal::AccountingAllocator allocator_; 711 int32_t result = runner.Call(static_cast<void*>(&p)...,
799 Zone zone; 712 static_cast<void*>(&return_value_local));
800 bool compiled_; 713 *return_value = return_value_local;
801 LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS]; 714 // If we arrive here, no trap happened.
802 FunctionSig signature_; 715 CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
803 WasmFunctionCompiler compiler_;
804 WasmFunctionWrapper<ReturnType> wrapper_;
805 bool possible_nondeterminism_;
806
807 bool interpret() { return compiler_.execution_mode_ == kExecuteInterpreted; }
808
809 static size_t GetParameterCount(MachineType p0, MachineType p1,
810 MachineType p2, MachineType p3) {
811 if (p0 == MachineType::None()) return 0;
812 if (p1 == MachineType::None()) return 1;
813 if (p2 == MachineType::None()) return 2;
814 if (p3 == MachineType::None()) return 3;
815 return 4;
816 } 716 }
817 }; 717 };
818 718
819 template <typename ReturnType> 719 // Declare static variable.
820 jmp_buf WasmRunner<ReturnType>::jump_buffer; 720 jmp_buf WasmRunnerBase::jump_buffer;
821 template <typename ReturnType>
822 int WasmRunner<ReturnType>::jump_value;
823 template <typename ReturnType>
824 ReturnTypeUnion<ReturnType> WasmRunner<ReturnType>::return_value;
825 721
826 // A macro to define tests that run in different engine configurations. 722 // A macro to define tests that run in different engine configurations.
827 #define WASM_EXEC_TEST(name) \ 723 #define WASM_EXEC_TEST(name) \
828 void RunWasm_##name(WasmExecutionMode execution_mode); \ 724 void RunWasm_##name(WasmExecutionMode execution_mode); \
829 TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \ 725 TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \
830 TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \ 726 TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \
831 void RunWasm_##name(WasmExecutionMode execution_mode) 727 void RunWasm_##name(WasmExecutionMode execution_mode)
832 728
833 #define WASM_EXEC_TEST_WITH_TRAP(name) \ 729 #define WASM_EXEC_TEST_WITH_TRAP(name) \
834 void RunWasm_##name(WasmExecutionMode execution_mode); \ 730 void RunWasm_##name(WasmExecutionMode execution_mode); \
835 TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \ 731 TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \
836 void RunWasm_##name(WasmExecutionMode execution_mode); \ 732 void RunWasm_##name(WasmExecutionMode execution_mode); \
837 TEST(RunWasmCompiledWithTrapIf_##name) { \ 733 TEST(RunWasmCompiledWithTrapIf_##name) { \
838 bool trap_if = FLAG_wasm_trap_if; \ 734 bool trap_if = FLAG_wasm_trap_if; \
839 FLAG_wasm_trap_if = true; \ 735 FLAG_wasm_trap_if = true; \
840 RunWasm_##name(kExecuteCompiled); \ 736 RunWasm_##name(kExecuteCompiled); \
841 FLAG_wasm_trap_if = trap_if; \ 737 FLAG_wasm_trap_if = trap_if; \
842 } \ 738 } \
843 TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \ 739 TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \
844 void RunWasm_##name(WasmExecutionMode execution_mode) 740 void RunWasm_##name(WasmExecutionMode execution_mode)
845 741
846 #define WASM_EXEC_COMPILED_TEST(name) \ 742 #define WASM_EXEC_COMPILED_TEST(name) \
847 void RunWasm_##name(WasmExecutionMode execution_mode); \ 743 void RunWasm_##name(WasmExecutionMode execution_mode); \
848 TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \ 744 TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \
849 void RunWasm_##name(WasmExecutionMode execution_mode) 745 void RunWasm_##name(WasmExecutionMode execution_mode)
850 746
851 } // namespace 747 } // namespace
852 748
853 #endif 749 #endif
OLDNEW
« 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