OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
| 28 #include "lithium-allocator-inl.h" |
28 #include "arm/lithium-arm.h" | 29 #include "arm/lithium-arm.h" |
29 #include "arm/lithium-codegen-arm.h" | 30 #include "arm/lithium-codegen-arm.h" |
30 | 31 |
31 namespace v8 { | 32 namespace v8 { |
32 namespace internal { | 33 namespace internal { |
33 | 34 |
34 #define DEFINE_COMPILE(type) \ | 35 #define DEFINE_COMPILE(type) \ |
35 void L##type::CompileToNative(LCodeGen* generator) { \ | 36 void L##type::CompileToNative(LCodeGen* generator) { \ |
36 generator->Do##type(this); \ | 37 generator->Do##type(this); \ |
37 } | 38 } |
(...skipping 11 matching lines...) Expand all Loading... |
49 | 50 |
50 | 51 |
51 void LOsrEntry::MarkSpilledRegister(int allocation_index, | 52 void LOsrEntry::MarkSpilledRegister(int allocation_index, |
52 LOperand* spill_operand) { | 53 LOperand* spill_operand) { |
53 ASSERT(spill_operand->IsStackSlot()); | 54 ASSERT(spill_operand->IsStackSlot()); |
54 ASSERT(register_spills_[allocation_index] == NULL); | 55 ASSERT(register_spills_[allocation_index] == NULL); |
55 register_spills_[allocation_index] = spill_operand; | 56 register_spills_[allocation_index] = spill_operand; |
56 } | 57 } |
57 | 58 |
58 | 59 |
| 60 #ifdef DEBUG |
| 61 void LInstruction::VerifyCall() { |
| 62 // Call instructions can use only fixed registers as |
| 63 // temporaries and outputs because all registers |
| 64 // are blocked by the calling convention. |
| 65 // Inputs can use either fixed register or have a short lifetime (be |
| 66 // used at start of the instruction). |
| 67 ASSERT(Output() == NULL || |
| 68 LUnallocated::cast(Output())->HasFixedPolicy() || |
| 69 !LUnallocated::cast(Output())->HasRegisterPolicy()); |
| 70 for (UseIterator it(this); it.HasNext(); it.Advance()) { |
| 71 LOperand* operand = it.Next(); |
| 72 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || |
| 73 LUnallocated::cast(operand)->IsUsedAtStart() || |
| 74 !LUnallocated::cast(operand)->HasRegisterPolicy()); |
| 75 } |
| 76 for (TempIterator it(this); it.HasNext(); it.Advance()) { |
| 77 LOperand* operand = it.Next(); |
| 78 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || |
| 79 !LUnallocated::cast(operand)->HasRegisterPolicy()); |
| 80 } |
| 81 } |
| 82 #endif |
| 83 |
| 84 |
59 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, | 85 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, |
60 LOperand* spill_operand) { | 86 LOperand* spill_operand) { |
61 ASSERT(spill_operand->IsDoubleStackSlot()); | 87 ASSERT(spill_operand->IsDoubleStackSlot()); |
62 ASSERT(double_register_spills_[allocation_index] == NULL); | 88 ASSERT(double_register_spills_[allocation_index] == NULL); |
63 double_register_spills_[allocation_index] = spill_operand; | 89 double_register_spills_[allocation_index] = spill_operand; |
64 } | 90 } |
65 | 91 |
66 | 92 |
67 void LInstruction::PrintTo(StringStream* stream) { | 93 void LInstruction::PrintTo(StringStream* stream) { |
68 stream->Add("%s ", this->Mnemonic()); | 94 stream->Add("%s ", this->Mnemonic()); |
69 if (HasResult()) { | 95 |
70 PrintOutputOperandTo(stream); | 96 PrintOutputOperandTo(stream); |
71 } | |
72 | 97 |
73 PrintDataTo(stream); | 98 PrintDataTo(stream); |
74 | 99 |
75 if (HasEnvironment()) { | 100 if (HasEnvironment()) { |
76 stream->Add(" "); | 101 stream->Add(" "); |
77 environment()->PrintTo(stream); | 102 environment()->PrintTo(stream); |
78 } | 103 } |
79 | 104 |
80 if (HasPointerMap()) { | 105 if (HasPointerMap()) { |
81 stream->Add(" "); | 106 stream->Add(" "); |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 | 408 |
384 if (can_eliminate) { | 409 if (can_eliminate) { |
385 label->set_replacement(GetLabel(goto_instr->block_id())); | 410 label->set_replacement(GetLabel(goto_instr->block_id())); |
386 } | 411 } |
387 } | 412 } |
388 } | 413 } |
389 } | 414 } |
390 } | 415 } |
391 | 416 |
392 | 417 |
393 int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { | 418 void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { |
394 LGap* gap = new LGap(block); | 419 LGap* gap = new LGap(block); |
395 int index = -1; | 420 int index = -1; |
396 if (instr->IsControl()) { | 421 if (instr->IsControl()) { |
397 instructions_.Add(gap); | 422 instructions_.Add(gap); |
398 index = instructions_.length(); | 423 index = instructions_.length(); |
399 instructions_.Add(instr); | 424 instructions_.Add(instr); |
400 } else { | 425 } else { |
401 index = instructions_.length(); | 426 index = instructions_.length(); |
402 instructions_.Add(instr); | 427 instructions_.Add(instr); |
403 instructions_.Add(gap); | 428 instructions_.Add(gap); |
404 } | 429 } |
405 if (instr->HasPointerMap()) { | 430 if (instr->HasPointerMap()) { |
406 pointer_maps_.Add(instr->pointer_map()); | 431 pointer_maps_.Add(instr->pointer_map()); |
407 instr->pointer_map()->set_lithium_position(index); | 432 instr->pointer_map()->set_lithium_position(index); |
408 } | 433 } |
409 return index; | |
410 } | 434 } |
411 | 435 |
412 | 436 |
413 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { | 437 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { |
414 return LConstantOperand::Create(constant->id()); | 438 return LConstantOperand::Create(constant->id()); |
415 } | 439 } |
416 | 440 |
417 | 441 |
418 int LChunk::GetParameterStackSlot(int index) const { | 442 int LChunk::GetParameterStackSlot(int index) const { |
419 // The receiver is at index 0, the first parameter at index 1, so we | 443 // The receiver is at index 0, the first parameter at index 1, so we |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { | 673 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { |
650 HEnvironment* hydrogen_env = current_block_->last_environment(); | 674 HEnvironment* hydrogen_env = current_block_->last_environment(); |
651 instr->set_environment(CreateEnvironment(hydrogen_env)); | 675 instr->set_environment(CreateEnvironment(hydrogen_env)); |
652 return instr; | 676 return instr; |
653 } | 677 } |
654 | 678 |
655 | 679 |
656 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, | 680 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, |
657 HInstruction* hinstr, | 681 HInstruction* hinstr, |
658 CanDeoptimize can_deoptimize) { | 682 CanDeoptimize can_deoptimize) { |
659 allocator_->MarkAsCall(); | 683 #ifdef DEBUG |
| 684 instr->VerifyCall(); |
| 685 #endif |
| 686 instr->MarkAsCall(); |
660 instr = AssignPointerMap(instr); | 687 instr = AssignPointerMap(instr); |
661 | 688 |
662 if (hinstr->HasSideEffects()) { | 689 if (hinstr->HasSideEffects()) { |
663 ASSERT(hinstr->next()->IsSimulate()); | 690 ASSERT(hinstr->next()->IsSimulate()); |
664 HSimulate* sim = HSimulate::cast(hinstr->next()); | 691 HSimulate* sim = HSimulate::cast(hinstr->next()); |
665 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber); | 692 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber); |
666 pending_deoptimization_ast_id_ = sim->ast_id(); | 693 pending_deoptimization_ast_id_ = sim->ast_id(); |
667 } | 694 } |
668 | 695 |
669 // If instruction does not have side-effects lazy deoptimization | 696 // If instruction does not have side-effects lazy deoptimization |
670 // after the call will try to deoptimize to the point before the call. | 697 // after the call will try to deoptimize to the point before the call. |
671 // Thus we still need to attach environment to this call even if | 698 // Thus we still need to attach environment to this call even if |
672 // call sequence can not deoptimize eagerly. | 699 // call sequence can not deoptimize eagerly. |
673 bool needs_environment = | 700 bool needs_environment = |
674 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); | 701 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); |
675 if (needs_environment && !instr->HasEnvironment()) { | 702 if (needs_environment && !instr->HasEnvironment()) { |
676 instr = AssignEnvironment(instr); | 703 instr = AssignEnvironment(instr); |
677 } | 704 } |
678 | 705 |
679 return instr; | 706 return instr; |
680 } | 707 } |
681 | 708 |
682 | 709 |
683 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { | 710 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { |
684 allocator_->MarkAsSaveDoubles(); | 711 instr->MarkAsSaveDoubles(); |
685 return instr; | 712 return instr; |
686 } | 713 } |
687 | 714 |
688 | 715 |
689 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { | 716 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
690 ASSERT(!instr->HasPointerMap()); | 717 ASSERT(!instr->HasPointerMap()); |
691 instr->set_pointer_map(new LPointerMap(position_)); | 718 instr->set_pointer_map(new LPointerMap(position_)); |
692 return instr; | 719 return instr; |
693 } | 720 } |
694 | 721 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 } | 891 } |
865 block->set_argument_count(argument_count_); | 892 block->set_argument_count(argument_count_); |
866 next_block_ = NULL; | 893 next_block_ = NULL; |
867 current_block_ = NULL; | 894 current_block_ = NULL; |
868 } | 895 } |
869 | 896 |
870 | 897 |
871 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 898 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
872 HInstruction* old_current = current_instruction_; | 899 HInstruction* old_current = current_instruction_; |
873 current_instruction_ = current; | 900 current_instruction_ = current; |
874 allocator_->BeginInstruction(); | |
875 if (current->has_position()) position_ = current->position(); | 901 if (current->has_position()) position_ = current->position(); |
876 LInstruction* instr = current->CompileToLithium(this); | 902 LInstruction* instr = current->CompileToLithium(this); |
877 | 903 |
878 if (instr != NULL) { | 904 if (instr != NULL) { |
879 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 905 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
880 instr = AssignPointerMap(instr); | 906 instr = AssignPointerMap(instr); |
881 } | 907 } |
882 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 908 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
883 instr = AssignEnvironment(instr); | 909 instr = AssignEnvironment(instr); |
884 } | 910 } |
885 if (current->IsTest() && !instr->IsGoto()) { | 911 if (current->IsTest() && !instr->IsGoto()) { |
886 ASSERT(instr->IsControl()); | 912 ASSERT(instr->IsControl()); |
887 HTest* test = HTest::cast(current); | 913 HTest* test = HTest::cast(current); |
888 instr->set_hydrogen_value(test->value()); | 914 instr->set_hydrogen_value(test->value()); |
889 HBasicBlock* first = test->FirstSuccessor(); | 915 HBasicBlock* first = test->FirstSuccessor(); |
890 HBasicBlock* second = test->SecondSuccessor(); | 916 HBasicBlock* second = test->SecondSuccessor(); |
891 ASSERT(first != NULL && second != NULL); | 917 ASSERT(first != NULL && second != NULL); |
892 instr->SetBranchTargets(first->block_id(), second->block_id()); | 918 instr->SetBranchTargets(first->block_id(), second->block_id()); |
893 } else { | 919 } else { |
894 instr->set_hydrogen_value(current); | 920 instr->set_hydrogen_value(current); |
895 } | 921 } |
896 | 922 |
897 int index = chunk_->AddInstruction(instr, current_block_); | 923 chunk_->AddInstruction(instr, current_block_); |
898 allocator_->SummarizeInstruction(index); | |
899 } else { | |
900 // This instruction should be omitted. | |
901 allocator_->OmitInstruction(); | |
902 } | 924 } |
903 current_instruction_ = old_current; | 925 current_instruction_ = old_current; |
904 } | 926 } |
905 | 927 |
906 | 928 |
907 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { | 929 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { |
908 if (hydrogen_env == NULL) return NULL; | 930 if (hydrogen_env == NULL) return NULL; |
909 | 931 |
910 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); | 932 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); |
911 int ast_id = hydrogen_env->ast_id(); | 933 int ast_id = hydrogen_env->ast_id(); |
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1842 | 1864 |
1843 | 1865 |
1844 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 1866 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
1845 HEnvironment* outer = current_block_->last_environment()->outer(); | 1867 HEnvironment* outer = current_block_->last_environment()->outer(); |
1846 current_block_->UpdateEnvironment(outer); | 1868 current_block_->UpdateEnvironment(outer); |
1847 return NULL; | 1869 return NULL; |
1848 } | 1870 } |
1849 | 1871 |
1850 | 1872 |
1851 } } // namespace v8::internal | 1873 } } // namespace v8::internal |
OLD | NEW |