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