OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "lithium-allocator-inl.h" | 7 #include "lithium-allocator-inl.h" |
8 #include "arm64/lithium-arm64.h" | 8 #include "arm64/lithium-arm64.h" |
9 #include "arm64/lithium-codegen-arm64.h" | 9 #include "arm64/lithium-codegen-arm64.h" |
10 #include "hydrogen-osr.h" | 10 #include "hydrogen-osr.h" |
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 chunk_->AddInstruction(dummy, current_block_); | 672 chunk_->AddInstruction(dummy, current_block_); |
673 } | 673 } |
674 } else { | 674 } else { |
675 instr = current->CompileToLithium(this); | 675 instr = current->CompileToLithium(this); |
676 } | 676 } |
677 | 677 |
678 argument_count_ += current->argument_delta(); | 678 argument_count_ += current->argument_delta(); |
679 ASSERT(argument_count_ >= 0); | 679 ASSERT(argument_count_ >= 0); |
680 | 680 |
681 if (instr != NULL) { | 681 if (instr != NULL) { |
682 // Associate the hydrogen instruction first, since we may need it for | 682 AddInstruction(instr, current); |
683 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. | 683 } |
684 instr->set_hydrogen_value(current); | |
685 | 684 |
686 #if DEBUG | |
687 // Make sure that the lithium instruction has either no fixed register | |
688 // constraints in temps or the result OR no uses that are only used at | |
689 // start. If this invariant doesn't hold, the register allocator can decide | |
690 // to insert a split of a range immediately before the instruction due to an | |
691 // already allocated register needing to be used for the instruction's fixed | |
692 // register constraint. In this case, the register allocator won't see an | |
693 // interference between the split child and the use-at-start (it would if | |
694 // the it was just a plain use), so it is free to move the split child into | |
695 // the same register that is used for the use-at-start. | |
696 // See https://code.google.com/p/chromium/issues/detail?id=201590 | |
697 if (!(instr->ClobbersRegisters() && | |
698 instr->ClobbersDoubleRegisters(isolate()))) { | |
699 int fixed = 0; | |
700 int used_at_start = 0; | |
701 for (UseIterator it(instr); !it.Done(); it.Advance()) { | |
702 LUnallocated* operand = LUnallocated::cast(it.Current()); | |
703 if (operand->IsUsedAtStart()) ++used_at_start; | |
704 } | |
705 if (instr->Output() != NULL) { | |
706 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed; | |
707 } | |
708 for (TempIterator it(instr); !it.Done(); it.Advance()) { | |
709 LUnallocated* operand = LUnallocated::cast(it.Current()); | |
710 if (operand->HasFixedPolicy()) ++fixed; | |
711 } | |
712 ASSERT(fixed == 0 || used_at_start == 0); | |
713 } | |
714 #endif | |
715 | |
716 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | |
717 instr = AssignPointerMap(instr); | |
718 } | |
719 if (FLAG_stress_environments && !instr->HasEnvironment()) { | |
720 instr = AssignEnvironment(instr); | |
721 } | |
722 chunk_->AddInstruction(instr, current_block_); | |
723 | |
724 if (instr->IsCall()) { | |
725 HValue* hydrogen_value_for_lazy_bailout = current; | |
726 LInstruction* instruction_needing_environment = NULL; | |
727 if (current->HasObservableSideEffects()) { | |
728 HSimulate* sim = HSimulate::cast(current->next()); | |
729 instruction_needing_environment = instr; | |
730 sim->ReplayEnvironment(current_block_->last_environment()); | |
731 hydrogen_value_for_lazy_bailout = sim; | |
732 } | |
733 LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout()); | |
734 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); | |
735 chunk_->AddInstruction(bailout, current_block_); | |
736 if (instruction_needing_environment != NULL) { | |
737 // Store the lazy deopt environment with the instruction if needed. | |
738 // Right now it is only used for LInstanceOfKnownGlobal. | |
739 instruction_needing_environment-> | |
740 SetDeferredLazyDeoptimizationEnvironment(bailout->environment()); | |
741 } | |
742 } | |
743 } | |
744 current_instruction_ = old_current; | 685 current_instruction_ = old_current; |
745 } | 686 } |
746 | 687 |
747 | 688 |
| 689 void LChunkBuilder::AddInstruction(LInstruction* instr, |
| 690 HInstruction* hydrogen_val) { |
| 691 // Associate the hydrogen instruction first, since we may need it for |
| 692 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. |
| 693 instr->set_hydrogen_value(hydrogen_val); |
| 694 |
| 695 #if DEBUG |
| 696 // Make sure that the lithium instruction has either no fixed register |
| 697 // constraints in temps or the result OR no uses that are only used at |
| 698 // start. If this invariant doesn't hold, the register allocator can decide |
| 699 // to insert a split of a range immediately before the instruction due to an |
| 700 // already allocated register needing to be used for the instruction's fixed |
| 701 // register constraint. In this case, the register allocator won't see an |
| 702 // interference between the split child and the use-at-start (it would if |
| 703 // the it was just a plain use), so it is free to move the split child into |
| 704 // the same register that is used for the use-at-start. |
| 705 // See https://code.google.com/p/chromium/issues/detail?id=201590 |
| 706 if (!(instr->ClobbersRegisters() && |
| 707 instr->ClobbersDoubleRegisters(isolate()))) { |
| 708 int fixed = 0; |
| 709 int used_at_start = 0; |
| 710 for (UseIterator it(instr); !it.Done(); it.Advance()) { |
| 711 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 712 if (operand->IsUsedAtStart()) ++used_at_start; |
| 713 } |
| 714 if (instr->Output() != NULL) { |
| 715 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed; |
| 716 } |
| 717 for (TempIterator it(instr); !it.Done(); it.Advance()) { |
| 718 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 719 if (operand->HasFixedPolicy()) ++fixed; |
| 720 } |
| 721 ASSERT(fixed == 0 || used_at_start == 0); |
| 722 } |
| 723 #endif |
| 724 |
| 725 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 726 instr = AssignPointerMap(instr); |
| 727 } |
| 728 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 729 instr = AssignEnvironment(instr); |
| 730 } |
| 731 chunk_->AddInstruction(instr, current_block_); |
| 732 |
| 733 if (instr->IsCall()) { |
| 734 HValue* hydrogen_value_for_lazy_bailout = hydrogen_val; |
| 735 LInstruction* instruction_needing_environment = NULL; |
| 736 if (hydrogen_val->HasObservableSideEffects()) { |
| 737 HSimulate* sim = HSimulate::cast(hydrogen_val->next()); |
| 738 instruction_needing_environment = instr; |
| 739 sim->ReplayEnvironment(current_block_->last_environment()); |
| 740 hydrogen_value_for_lazy_bailout = sim; |
| 741 } |
| 742 LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout()); |
| 743 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); |
| 744 chunk_->AddInstruction(bailout, current_block_); |
| 745 if (instruction_needing_environment != NULL) { |
| 746 // Store the lazy deopt environment with the instruction if needed. |
| 747 // Right now it is only used for LInstanceOfKnownGlobal. |
| 748 instruction_needing_environment-> |
| 749 SetDeferredLazyDeoptimizationEnvironment(bailout->environment()); |
| 750 } |
| 751 } |
| 752 } |
| 753 |
| 754 |
748 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { | 755 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { |
749 HEnvironment* hydrogen_env = current_block_->last_environment(); | 756 HEnvironment* hydrogen_env = current_block_->last_environment(); |
750 int argument_index_accumulator = 0; | 757 int argument_index_accumulator = 0; |
751 ZoneList<HValue*> objects_to_materialize(0, zone()); | 758 ZoneList<HValue*> objects_to_materialize(0, zone()); |
752 instr->set_environment(CreateEnvironment(hydrogen_env, | 759 instr->set_environment(CreateEnvironment(hydrogen_env, |
753 &argument_index_accumulator, | 760 &argument_index_accumulator, |
754 &objects_to_materialize)); | 761 &objects_to_materialize)); |
755 return instr; | 762 return instr; |
756 } | 763 } |
757 | 764 |
(...skipping 1944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2702 | 2709 |
2703 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { | 2710 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { |
2704 LOperand* receiver = UseRegister(instr->receiver()); | 2711 LOperand* receiver = UseRegister(instr->receiver()); |
2705 LOperand* function = UseRegister(instr->function()); | 2712 LOperand* function = UseRegister(instr->function()); |
2706 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function); | 2713 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function); |
2707 return AssignEnvironment(DefineAsRegister(result)); | 2714 return AssignEnvironment(DefineAsRegister(result)); |
2708 } | 2715 } |
2709 | 2716 |
2710 | 2717 |
2711 } } // namespace v8::internal | 2718 } } // namespace v8::internal |
OLD | NEW |