OLD | NEW |
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> |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 byte code[] = {__VA_ARGS__}; \ | 56 byte code[] = {__VA_ARGS__}; \ |
57 r.Build(code, code + arraysize(code)); \ | 57 r.Build(code, code + arraysize(code)); \ |
58 } while (false) | 58 } while (false) |
59 | 59 |
60 namespace { | 60 namespace { |
61 using namespace v8::base; | 61 using namespace v8::base; |
62 using namespace v8::internal; | 62 using namespace v8::internal; |
63 using namespace v8::internal::compiler; | 63 using namespace v8::internal::compiler; |
64 using namespace v8::internal::wasm; | 64 using namespace v8::internal::wasm; |
65 | 65 |
66 inline void init_env(FunctionEnv* env, FunctionSig* sig) { | |
67 env->module = nullptr; | |
68 env->sig = sig; | |
69 env->local_i32_count = 0; | |
70 env->local_i64_count = 0; | |
71 env->local_f32_count = 0; | |
72 env->local_f64_count = 0; | |
73 env->SumLocals(); | |
74 } | |
75 | |
76 const uint32_t kMaxGlobalsSize = 128; | 66 const uint32_t kMaxGlobalsSize = 128; |
77 | 67 |
78 // A helper for module environments that adds the ability to allocate memory | 68 // A helper for module environments that adds the ability to allocate memory |
79 // and global variables. Contains a built-in {WasmModule} and | 69 // and global variables. Contains a built-in {WasmModule} and |
80 // {WasmModuleInstance}. | 70 // {WasmModuleInstance}. |
81 class TestingModule : public ModuleEnv { | 71 class TestingModule : public ModuleEnv { |
82 public: | 72 public: |
83 TestingModule() : instance_(&module_), global_offset(0) { | 73 TestingModule() : instance_(&module_), global_offset(0) { |
84 module_.shared_isolate = CcTest::InitIsolateOnce(); | 74 module_.shared_isolate = CcTest::InitIsolateOnce(); |
85 module = &module_; | 75 module = &module_; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 byte size = WasmOpcodes::MemSize(mem_type); | 210 byte size = WasmOpcodes::MemSize(mem_type); |
221 global_offset = (global_offset + size - 1) & ~(size - 1); // align | 211 global_offset = (global_offset + size - 1) & ~(size - 1); // align |
222 module->globals.push_back({0, mem_type, global_offset, false}); | 212 module->globals.push_back({0, mem_type, global_offset, false}); |
223 global_offset += size; | 213 global_offset += size; |
224 // limit number of globals. | 214 // limit number of globals. |
225 CHECK_LT(global_offset, kMaxGlobalsSize); | 215 CHECK_LT(global_offset, kMaxGlobalsSize); |
226 return &module->globals.back(); | 216 return &module->globals.back(); |
227 } | 217 } |
228 }; | 218 }; |
229 | 219 |
230 | 220 inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module, |
231 inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, FunctionEnv* env, | 221 FunctionSig* sig, const byte* start, |
232 const byte* start, const byte* end) { | 222 const byte* end) { |
233 compiler::WasmGraphBuilder builder(zone, jsgraph, env->sig); | 223 compiler::WasmGraphBuilder builder(zone, jsgraph, sig); |
234 TreeResult result = BuildTFGraph(&builder, env, start, end); | 224 TreeResult result = BuildTFGraph(&builder, module, sig, start, end); |
235 if (result.failed()) { | 225 if (result.failed()) { |
236 ptrdiff_t pc = result.error_pc - result.start; | 226 ptrdiff_t pc = result.error_pc - result.start; |
237 ptrdiff_t pt = result.error_pt - result.start; | 227 ptrdiff_t pt = result.error_pt - result.start; |
238 std::ostringstream str; | 228 std::ostringstream str; |
239 str << "Verification failed: " << result.error_code << " pc = +" << pc; | 229 str << "Verification failed: " << result.error_code << " pc = +" << pc; |
240 if (result.error_pt) str << ", pt = +" << pt; | 230 if (result.error_pt) str << ", pt = +" << pt; |
241 str << ", msg = " << result.error_msg.get(); | 231 str << ", msg = " << result.error_msg.get(); |
242 FATAL(str.str().c_str()); | 232 FATAL(str.str().c_str()); |
243 } | 233 } |
244 builder.Int64LoweringForTesting(); | 234 builder.Int64LoweringForTesting(); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 // standalone function if {module} is NULL or a function within a | 382 // standalone function if {module} is NULL or a function within a |
393 // {TestingModule}. It contains the internal state for compilation (i.e. | 383 // {TestingModule}. It contains the internal state for compilation (i.e. |
394 // TurboFan graph) and, later, interpretation. | 384 // TurboFan graph) and, later, interpretation. |
395 class WasmFunctionCompiler : public HandleAndZoneScope, | 385 class WasmFunctionCompiler : public HandleAndZoneScope, |
396 private GraphAndBuilders { | 386 private GraphAndBuilders { |
397 public: | 387 public: |
398 explicit WasmFunctionCompiler(FunctionSig* sig, TestingModule* module) | 388 explicit WasmFunctionCompiler(FunctionSig* sig, TestingModule* module) |
399 : GraphAndBuilders(main_zone()), | 389 : GraphAndBuilders(main_zone()), |
400 jsgraph(this->isolate(), this->graph(), this->common(), nullptr, | 390 jsgraph(this->isolate(), this->graph(), this->common(), nullptr, |
401 nullptr, this->machine()), | 391 nullptr, this->machine()), |
| 392 sig(sig), |
402 descriptor_(nullptr), | 393 descriptor_(nullptr), |
403 testing_module_(module) { | 394 testing_module_(module) { |
404 init_env(&env, sig); | |
405 env.module = module; | |
406 if (module) { | 395 if (module) { |
407 // Get a new function from the testing module. | 396 // Get a new function from the testing module. |
408 function_ = nullptr; | 397 function_ = nullptr; |
409 function_index_ = module->AddFunction(sig, Handle<Code>::null()); | 398 function_index_ = module->AddFunction(sig, Handle<Code>::null()); |
410 } else { | 399 } else { |
411 // Create our own function. | 400 // Create our own function. |
412 function_ = new WasmFunction(); | 401 function_ = new WasmFunction(); |
413 function_->sig = sig; | 402 function_->sig = sig; |
414 function_index_ = 0; | 403 function_index_ = 0; |
415 } | 404 } |
416 } | 405 } |
417 | 406 |
418 ~WasmFunctionCompiler() { | 407 ~WasmFunctionCompiler() { |
419 if (function_) delete function_; | 408 if (function_) delete function_; |
420 } | 409 } |
421 | 410 |
422 JSGraph jsgraph; | 411 JSGraph jsgraph; |
423 FunctionEnv env; | 412 FunctionSig* sig; |
424 // The call descriptor is initialized when the function is compiled. | 413 // The call descriptor is initialized when the function is compiled. |
425 CallDescriptor* descriptor_; | 414 CallDescriptor* descriptor_; |
426 TestingModule* testing_module_; | 415 TestingModule* testing_module_; |
427 WasmFunction* function_; | 416 WasmFunction* function_; |
428 int function_index_; | 417 int function_index_; |
| 418 LocalDeclEncoder local_decls; |
429 | 419 |
430 Isolate* isolate() { return main_isolate(); } | 420 Isolate* isolate() { return main_isolate(); } |
431 Graph* graph() const { return main_graph_; } | 421 Graph* graph() const { return main_graph_; } |
432 Zone* zone() const { return graph()->zone(); } | 422 Zone* zone() const { return graph()->zone(); } |
433 CommonOperatorBuilder* common() { return &main_common_; } | 423 CommonOperatorBuilder* common() { return &main_common_; } |
434 MachineOperatorBuilder* machine() { return &main_machine_; } | 424 MachineOperatorBuilder* machine() { return &main_machine_; } |
435 void InitializeDescriptor() { | 425 void InitializeDescriptor() { |
436 if (descriptor_ == nullptr) { | 426 if (descriptor_ == nullptr) { |
437 descriptor_ = env.module->GetWasmCallDescriptor(main_zone(), env.sig); | 427 descriptor_ = testing_module_->GetWasmCallDescriptor(main_zone(), sig); |
438 } | 428 } |
439 } | 429 } |
440 CallDescriptor* descriptor() { return descriptor_; } | 430 CallDescriptor* descriptor() { return descriptor_; } |
441 | 431 |
442 void Build(const byte* start, const byte* end) { | 432 void Build(const byte* start, const byte* end) { |
443 // Transfer local counts before compiling. | |
444 function()->local_i32_count = env.local_i32_count; | |
445 function()->local_i64_count = env.local_i64_count; | |
446 function()->local_f32_count = env.local_f32_count; | |
447 function()->local_f64_count = env.local_f64_count; | |
448 | |
449 // Build the TurboFan graph. | 433 // Build the TurboFan graph. |
450 TestBuildingGraph(main_zone(), &jsgraph, &env, start, end); | 434 local_decls.Prepend(&start, &end); |
| 435 TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig, start, end); |
| 436 delete[] start; |
451 } | 437 } |
452 | 438 |
453 byte AllocateLocal(LocalType type) { | 439 byte AllocateLocal(LocalType type) { |
454 int result = static_cast<int>(env.total_locals); | 440 uint32_t index = local_decls.AddLocals(1, type, sig); |
455 env.AddLocals(type, 1); | 441 byte result = static_cast<byte>(index); |
456 byte b = static_cast<byte>(result); | 442 DCHECK_EQ(index, result); |
457 CHECK_EQ(result, b); | 443 return result; |
458 return b; | |
459 } | 444 } |
460 | 445 |
461 // TODO(titzer): remove me. | 446 // TODO(titzer): remove me. |
462 Handle<Code> Compile() { | 447 Handle<Code> Compile() { |
463 InitializeDescriptor(); | 448 InitializeDescriptor(); |
464 CallDescriptor* desc = descriptor_; | 449 CallDescriptor* desc = descriptor_; |
465 if (kPointerSize == 4) { | 450 if (kPointerSize == 4) { |
466 desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc); | 451 desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc); |
467 } | 452 } |
468 CompilationInfo info("wasm compile", this->isolate(), this->zone()); | 453 CompilationInfo info("wasm compile", this->isolate(), this->zone()); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 storage_[index++] = WasmOpcodes::LocalTypeFor(p1); | 520 storage_[index++] = WasmOpcodes::LocalTypeFor(p1); |
536 if (p2 != MachineType::None()) | 521 if (p2 != MachineType::None()) |
537 storage_[index++] = WasmOpcodes::LocalTypeFor(p2); | 522 storage_[index++] = WasmOpcodes::LocalTypeFor(p2); |
538 if (p3 != MachineType::None()) | 523 if (p3 != MachineType::None()) |
539 storage_[index++] = WasmOpcodes::LocalTypeFor(p3); | 524 storage_[index++] = WasmOpcodes::LocalTypeFor(p3); |
540 | 525 |
541 compiler_.InitializeDescriptor(); | 526 compiler_.InitializeDescriptor(); |
542 wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3); | 527 wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3); |
543 } | 528 } |
544 | 529 |
545 FunctionEnv* env() { return &compiler_.env; } | |
546 | |
547 // Builds a graph from the given Wasm code and generates the machine | 530 // Builds a graph from the given Wasm code and generates the machine |
548 // code and call wrapper for that graph. This method must not be called | 531 // code and call wrapper for that graph. This method must not be called |
549 // more than once. | 532 // more than once. |
550 void Build(const byte* start, const byte* end) { | 533 void Build(const byte* start, const byte* end) { |
551 CHECK(!compiled_); | 534 CHECK(!compiled_); |
552 compiled_ = true; | 535 compiled_ = true; |
553 | 536 |
554 // Build the TF graph within the compiler. | 537 // Build the TF graph within the compiler. |
555 compiler_.Build(start, end); | 538 compiler_.Build(start, end); |
556 // Generate code. | 539 // Generate code. |
(...skipping 29 matching lines...) Expand all Loading... |
586 ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) { | 569 ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) { |
587 CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(), | 570 CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(), |
588 wrapper_.GetWrapperCode(), wrapper_.signature()); | 571 wrapper_.GetWrapperCode(), wrapper_.signature()); |
589 ReturnType return_value; | 572 ReturnType return_value; |
590 int32_t result = runner.Call<void*, void*, void*, void*, void*>( | 573 int32_t result = runner.Call<void*, void*, void*, void*, void*>( |
591 &p0, &p1, &p2, &p3, &return_value); | 574 &p0, &p1, &p2, &p3, &return_value); |
592 CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result); | 575 CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result); |
593 return return_value; | 576 return return_value; |
594 } | 577 } |
595 | 578 |
596 byte AllocateLocal(LocalType type) { | 579 byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); } |
597 int result = static_cast<int>(env()->total_locals); | |
598 env()->AddLocals(type, 1); | |
599 byte b = static_cast<byte>(result); | |
600 CHECK_EQ(result, b); | |
601 return b; | |
602 } | |
603 | 580 |
604 protected: | 581 protected: |
605 Zone zone; | 582 Zone zone; |
606 bool compiled_; | 583 bool compiled_; |
607 LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS]; | 584 LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS]; |
608 FunctionSig signature_; | 585 FunctionSig signature_; |
609 WasmFunctionCompiler compiler_; | 586 WasmFunctionCompiler compiler_; |
610 WasmFunctionWrapper<ReturnType> wrapper_; | 587 WasmFunctionWrapper<ReturnType> wrapper_; |
611 | 588 |
612 static size_t GetParameterCount(MachineType p0, MachineType p1, | 589 static size_t GetParameterCount(MachineType p0, MachineType p1, |
613 MachineType p2, MachineType p3) { | 590 MachineType p2, MachineType p3) { |
614 if (p0 == MachineType::None()) return 0; | 591 if (p0 == MachineType::None()) return 0; |
615 if (p1 == MachineType::None()) return 1; | 592 if (p1 == MachineType::None()) return 1; |
616 if (p2 == MachineType::None()) return 2; | 593 if (p2 == MachineType::None()) return 2; |
617 if (p3 == MachineType::None()) return 3; | 594 if (p3 == MachineType::None()) return 3; |
618 return 4; | 595 return 4; |
619 } | 596 } |
620 }; | 597 }; |
621 | 598 |
622 } // namespace | 599 } // namespace |
623 | 600 |
624 #endif | 601 #endif |
OLD | NEW |