| 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 |