OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 #include "src/compiler/interpreter-assembler.h" | 5 #include "src/compiler/interpreter-assembler.h" |
6 | 6 |
7 #include <ostream> | 7 #include <ostream> |
8 | 8 |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
11 #include "src/compiler/instruction-selector.h" | 11 #include "src/compiler/instruction-selector.h" |
12 #include "src/compiler/linkage.h" | 12 #include "src/compiler/linkage.h" |
13 #include "src/compiler/pipeline.h" | 13 #include "src/compiler/pipeline.h" |
14 #include "src/compiler/raw-machine-assembler.h" | 14 #include "src/compiler/raw-machine-assembler.h" |
15 #include "src/compiler/schedule.h" | 15 #include "src/compiler/schedule.h" |
16 #include "src/frames.h" | 16 #include "src/frames.h" |
17 #include "src/interface-descriptors.h" | 17 #include "src/interface-descriptors.h" |
18 #include "src/interpreter/bytecodes.h" | 18 #include "src/interpreter/bytecodes.h" |
19 #include "src/machine-type.h" | 19 #include "src/machine-type.h" |
20 #include "src/macro-assembler.h" | 20 #include "src/macro-assembler.h" |
21 #include "src/zone.h" | 21 #include "src/zone.h" |
22 | 22 |
23 namespace v8 { | 23 namespace v8 { |
24 namespace internal { | 24 namespace internal { |
25 namespace compiler { | 25 namespace compiler { |
26 | 26 |
27 | |
28 InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, | 27 InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, |
29 interpreter::Bytecode bytecode) | 28 interpreter::Bytecode bytecode) |
30 : bytecode_(bytecode), | 29 : bytecode_(bytecode), |
31 raw_assembler_(new RawMachineAssembler( | 30 raw_assembler_(new RawMachineAssembler( |
32 isolate, new (zone) Graph(zone), | 31 isolate, new (zone) Graph(zone), |
33 Linkage::GetInterpreterDispatchDescriptor(zone), | 32 Linkage::GetInterpreterDispatchDescriptor(zone), |
34 MachineType::PointerRepresentation(), | 33 MachineType::PointerRepresentation(), |
35 InstructionSelector::SupportedMachineOperatorFlags())), | 34 InstructionSelector::SupportedMachineOperatorFlags())), |
36 accumulator_( | 35 accumulator_( |
37 raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)), | 36 raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)), |
38 bytecode_offset_(raw_assembler_->Parameter( | 37 bytecode_offset_(raw_assembler_->Parameter( |
39 Linkage::kInterpreterBytecodeOffsetParameter)), | 38 Linkage::kInterpreterBytecodeOffsetParameter)), |
40 context_( | 39 context_( |
41 raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)), | 40 raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)), |
42 code_generated_(false) {} | 41 code_generated_(false) { |
43 | 42 if (FLAG_trace_ignition) { |
| 43 TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry); |
| 44 } |
| 45 } |
44 | 46 |
45 InterpreterAssembler::~InterpreterAssembler() {} | 47 InterpreterAssembler::~InterpreterAssembler() {} |
46 | 48 |
47 | 49 |
48 Handle<Code> InterpreterAssembler::GenerateCode() { | 50 Handle<Code> InterpreterAssembler::GenerateCode() { |
49 DCHECK(!code_generated_); | 51 DCHECK(!code_generated_); |
50 | 52 |
51 // Disallow empty handlers that never return. | 53 // Disallow empty handlers that never return. |
52 DCHECK_NE(0, graph()->end()->InputCount()); | 54 DCHECK_NE(0, graph()->end()->InputCount()); |
53 | 55 |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 return CallN(descriptor, code_target, args); | 464 return CallN(descriptor, code_target, args); |
463 } | 465 } |
464 | 466 |
465 | 467 |
466 void InterpreterAssembler::CallPrologue() { | 468 void InterpreterAssembler::CallPrologue() { |
467 StoreRegister(SmiTag(bytecode_offset_), | 469 StoreRegister(SmiTag(bytecode_offset_), |
468 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer); | 470 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer); |
469 } | 471 } |
470 | 472 |
471 | 473 |
472 void InterpreterAssembler::CallEpilogue() { | |
473 // Restore the bytecode offset from the stack frame. | |
474 bytecode_offset_ = SmiUntag(LoadRegister( | |
475 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer)); | |
476 } | |
477 | |
478 | |
479 Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target, | 474 Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target, |
480 Node** args) { | 475 Node** args) { |
481 CallPrologue(); | 476 CallPrologue(); |
482 | 477 |
483 Node* stack_pointer_before_call = nullptr; | 478 Node* stack_pointer_before_call = nullptr; |
484 if (FLAG_debug_code) { | 479 if (FLAG_debug_code) { |
485 stack_pointer_before_call = raw_assembler_->LoadStackPointer(); | 480 stack_pointer_before_call = raw_assembler_->LoadStackPointer(); |
486 } | 481 } |
487 Node* return_val = raw_assembler_->CallN(descriptor, code_target, args); | 482 Node* return_val = raw_assembler_->CallN(descriptor, code_target, args); |
488 if (FLAG_debug_code) { | 483 if (FLAG_debug_code) { |
489 Node* stack_pointer_after_call = raw_assembler_->LoadStackPointer(); | 484 Node* stack_pointer_after_call = raw_assembler_->LoadStackPointer(); |
490 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, | 485 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, |
491 kUnexpectedStackPointer); | 486 kUnexpectedStackPointer); |
492 } | 487 } |
493 | 488 |
494 CallEpilogue(); | |
495 return return_val; | 489 return return_val; |
496 } | 490 } |
497 | 491 |
498 | 492 |
499 Node* InterpreterAssembler::CallJS(Node* function, Node* first_arg, | 493 Node* InterpreterAssembler::CallJS(Node* function, Node* first_arg, |
500 Node* arg_count) { | 494 Node* arg_count) { |
501 Callable callable = CodeFactory::InterpreterPushArgsAndCall(isolate()); | 495 Callable callable = CodeFactory::InterpreterPushArgsAndCall(isolate()); |
502 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( | 496 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( |
503 isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags); | 497 isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags); |
504 | 498 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 | 581 |
588 return CallN(descriptor, code_target, args); | 582 return CallN(descriptor, code_target, args); |
589 } | 583 } |
590 | 584 |
591 | 585 |
592 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, | 586 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, |
593 Node* arg1) { | 587 Node* arg1) { |
594 CallPrologue(); | 588 CallPrologue(); |
595 Node* return_val = | 589 Node* return_val = |
596 raw_assembler_->CallRuntime1(function_id, arg1, GetContext()); | 590 raw_assembler_->CallRuntime1(function_id, arg1, GetContext()); |
597 CallEpilogue(); | |
598 return return_val; | 591 return return_val; |
599 } | 592 } |
600 | 593 |
601 | 594 |
602 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, | 595 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, |
603 Node* arg1, Node* arg2) { | 596 Node* arg1, Node* arg2) { |
604 CallPrologue(); | 597 CallPrologue(); |
605 Node* return_val = | 598 Node* return_val = |
606 raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext()); | 599 raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext()); |
607 CallEpilogue(); | |
608 return return_val; | 600 return return_val; |
609 } | 601 } |
610 | 602 |
| 603 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, |
| 604 Node* arg1, Node* arg2, Node* arg3) { |
| 605 CallPrologue(); |
| 606 Node* return_val = |
| 607 raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, GetContext()); |
| 608 return return_val; |
| 609 } |
611 | 610 |
612 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, | 611 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, |
613 Node* arg1, Node* arg2, Node* arg3, | 612 Node* arg1, Node* arg2, Node* arg3, |
614 Node* arg4) { | 613 Node* arg4) { |
615 CallPrologue(); | 614 CallPrologue(); |
616 Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3, | 615 Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3, |
617 arg4, GetContext()); | 616 arg4, GetContext()); |
618 CallEpilogue(); | |
619 return return_val; | 617 return return_val; |
620 } | 618 } |
621 | 619 |
622 | 620 |
623 void InterpreterAssembler::Return() { | 621 void InterpreterAssembler::Return() { |
| 622 if (FLAG_trace_ignition) { |
| 623 TraceBytecode(Runtime::kInterpreterTraceBytecodeExit); |
| 624 } |
| 625 |
624 Node* exit_trampoline_code_object = | 626 Node* exit_trampoline_code_object = |
625 HeapConstant(isolate()->builtins()->InterpreterExitTrampoline()); | 627 HeapConstant(isolate()->builtins()->InterpreterExitTrampoline()); |
626 // If the order of the parameters you need to change the call signature below. | 628 // If the order of the parameters you need to change the call signature below. |
627 STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter); | 629 STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter); |
628 STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter); | 630 STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter); |
629 STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter); | 631 STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter); |
630 STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter); | 632 STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter); |
631 STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter); | 633 STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter); |
632 STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter); | 634 STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter); |
633 Node* args[] = { GetAccumulator(), | 635 Node* args[] = { GetAccumulator(), |
634 RegisterFileRawPointer(), | 636 RegisterFileRawPointer(), |
635 BytecodeOffset(), | 637 BytecodeOffset(), |
636 BytecodeArrayTaggedPointer(), | 638 BytecodeArrayTaggedPointer(), |
637 DispatchTableRawPointer(), | 639 DispatchTableRawPointer(), |
638 GetContext() }; | 640 GetContext() }; |
639 raw_assembler_->TailCallN(call_descriptor(), exit_trampoline_code_object, | 641 raw_assembler_->TailCallN(call_descriptor(), exit_trampoline_code_object, |
640 args); | 642 args); |
641 } | 643 } |
642 | 644 |
643 | 645 |
644 Node* InterpreterAssembler::Advance(int delta) { | 646 Node* InterpreterAssembler::Advance(int delta) { |
645 return IntPtrAdd(BytecodeOffset(), Int32Constant(delta)); | 647 return IntPtrAdd(BytecodeOffset(), Int32Constant(delta)); |
646 } | 648 } |
647 | 649 |
648 | 650 |
649 Node* InterpreterAssembler::Advance(Node* delta) { | 651 Node* InterpreterAssembler::Advance(Node* delta) { |
650 return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta); | 652 return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta); |
651 } | 653 } |
652 | 654 |
653 | |
654 void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); } | 655 void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); } |
655 | 656 |
656 | |
657 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { | 657 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { |
658 RawMachineLabel match, no_match; | 658 RawMachineLabel match, no_match; |
659 Node* condition = raw_assembler_->WordEqual(lhs, rhs); | 659 Node* condition = raw_assembler_->WordEqual(lhs, rhs); |
660 raw_assembler_->Branch(condition, &match, &no_match); | 660 raw_assembler_->Branch(condition, &match, &no_match); |
661 raw_assembler_->Bind(&match); | 661 raw_assembler_->Bind(&match); |
662 DispatchTo(Advance(delta)); | 662 DispatchTo(Advance(delta)); |
663 raw_assembler_->Bind(&no_match); | 663 raw_assembler_->Bind(&no_match); |
664 Dispatch(); | 664 Dispatch(); |
665 } | 665 } |
666 | 666 |
667 | 667 |
668 void InterpreterAssembler::Dispatch() { | 668 void InterpreterAssembler::Dispatch() { |
669 DispatchTo(Advance(interpreter::Bytecodes::Size(bytecode_))); | 669 DispatchTo(Advance(interpreter::Bytecodes::Size(bytecode_))); |
670 } | 670 } |
671 | 671 |
672 | 672 |
673 void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) { | 673 void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) { |
| 674 if (FLAG_trace_ignition) { |
| 675 TraceBytecode(Runtime::kInterpreterTraceBytecodeExit); |
| 676 } |
674 Node* target_bytecode = raw_assembler_->Load( | 677 Node* target_bytecode = raw_assembler_->Load( |
675 MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset); | 678 MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset); |
676 | 679 |
677 // TODO(rmcilroy): Create a code target dispatch table to avoid conversion | 680 // TODO(rmcilroy): Create a code target dispatch table to avoid conversion |
678 // from code object on every dispatch. | 681 // from code object on every dispatch. |
679 Node* target_code_object = raw_assembler_->Load( | 682 Node* target_code_object = raw_assembler_->Load( |
680 MachineType::Pointer(), DispatchTableRawPointer(), | 683 MachineType::Pointer(), DispatchTableRawPointer(), |
681 raw_assembler_->Word32Shl(target_bytecode, | 684 raw_assembler_->Word32Shl(target_bytecode, |
682 Int32Constant(kPointerSizeLog2))); | 685 Int32Constant(kPointerSizeLog2))); |
683 | 686 |
(...skipping 25 matching lines...) Expand all Loading... |
709 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, | 712 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, |
710 BailoutReason bailout_reason) { | 713 BailoutReason bailout_reason) { |
711 RawMachineLabel match, no_match; | 714 RawMachineLabel match, no_match; |
712 Node* condition = raw_assembler_->WordEqual(lhs, rhs); | 715 Node* condition = raw_assembler_->WordEqual(lhs, rhs); |
713 raw_assembler_->Branch(condition, &match, &no_match); | 716 raw_assembler_->Branch(condition, &match, &no_match); |
714 raw_assembler_->Bind(&no_match); | 717 raw_assembler_->Bind(&no_match); |
715 Abort(bailout_reason); | 718 Abort(bailout_reason); |
716 raw_assembler_->Bind(&match); | 719 raw_assembler_->Bind(&match); |
717 } | 720 } |
718 | 721 |
| 722 void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) { |
| 723 CallRuntime(function_id, BytecodeArrayTaggedPointer(), |
| 724 SmiTag(BytecodeOffset()), GetAccumulator()); |
| 725 } |
719 | 726 |
720 // static | 727 // static |
721 bool InterpreterAssembler::TargetSupportsUnalignedAccess() { | 728 bool InterpreterAssembler::TargetSupportsUnalignedAccess() { |
722 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 | 729 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 |
723 return false; | 730 return false; |
724 #elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC | 731 #elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC |
725 return CpuFeatures::IsSupported(UNALIGNED_ACCESSES); | 732 return CpuFeatures::IsSupported(UNALIGNED_ACCESSES); |
726 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87 | 733 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87 |
727 return true; | 734 return true; |
728 #else | 735 #else |
(...skipping 13 matching lines...) Expand all Loading... |
742 return raw_assembler_->call_descriptor(); | 749 return raw_assembler_->call_descriptor(); |
743 } | 750 } |
744 | 751 |
745 | 752 |
746 Zone* InterpreterAssembler::zone() { return raw_assembler_->zone(); } | 753 Zone* InterpreterAssembler::zone() { return raw_assembler_->zone(); } |
747 | 754 |
748 | 755 |
749 } // namespace compiler | 756 } // namespace compiler |
750 } // namespace internal | 757 } // namespace internal |
751 } // namespace v8 | 758 } // namespace v8 |
OLD | NEW |