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 |
(...skipping 11 matching lines...) Expand all Loading... |
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 "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #if defined(V8_TARGET_ARCH_IA32) | 30 #if defined(V8_TARGET_ARCH_IA32) |
31 | 31 |
| 32 #include "lithium-allocator-inl.h" |
32 #include "ia32/lithium-ia32.h" | 33 #include "ia32/lithium-ia32.h" |
33 #include "ia32/lithium-codegen-ia32.h" | 34 #include "ia32/lithium-codegen-ia32.h" |
34 | 35 |
35 namespace v8 { | 36 namespace v8 { |
36 namespace internal { | 37 namespace internal { |
37 | 38 |
38 #define DEFINE_COMPILE(type) \ | 39 #define DEFINE_COMPILE(type) \ |
39 void L##type::CompileToNative(LCodeGen* generator) { \ | 40 void L##type::CompileToNative(LCodeGen* generator) { \ |
40 generator->Do##type(this); \ | 41 generator->Do##type(this); \ |
41 } | 42 } |
(...skipping 19 matching lines...) Expand all Loading... |
61 | 62 |
62 | 63 |
63 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, | 64 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, |
64 LOperand* spill_operand) { | 65 LOperand* spill_operand) { |
65 ASSERT(spill_operand->IsDoubleStackSlot()); | 66 ASSERT(spill_operand->IsDoubleStackSlot()); |
66 ASSERT(double_register_spills_[allocation_index] == NULL); | 67 ASSERT(double_register_spills_[allocation_index] == NULL); |
67 double_register_spills_[allocation_index] = spill_operand; | 68 double_register_spills_[allocation_index] = spill_operand; |
68 } | 69 } |
69 | 70 |
70 | 71 |
| 72 #ifdef DEBUG |
| 73 void LInstruction::VerifyCall() { |
| 74 // Call instructions can use only fixed registers as |
| 75 // temporaries and outputs because all registers |
| 76 // are blocked by the calling convention. |
| 77 // Inputs can use either fixed register or have a short lifetime (be |
| 78 // used at start of the instruction). |
| 79 ASSERT(Output() == NULL || |
| 80 LUnallocated::cast(Output())->HasFixedPolicy() || |
| 81 !LUnallocated::cast(Output())->HasRegisterPolicy()); |
| 82 for (UseIterator it(this); it.HasNext(); it.Advance()) { |
| 83 LOperand* operand = it.Next(); |
| 84 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || |
| 85 LUnallocated::cast(operand)->IsUsedAtStart() || |
| 86 !LUnallocated::cast(operand)->HasRegisterPolicy()); |
| 87 } |
| 88 for (TempIterator it(this); it.HasNext(); it.Advance()) { |
| 89 LOperand* operand = it.Next(); |
| 90 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || |
| 91 !LUnallocated::cast(operand)->HasRegisterPolicy()); |
| 92 } |
| 93 } |
| 94 #endif |
| 95 |
| 96 |
71 void LInstruction::PrintTo(StringStream* stream) { | 97 void LInstruction::PrintTo(StringStream* stream) { |
72 stream->Add("%s ", this->Mnemonic()); | 98 stream->Add("%s ", this->Mnemonic()); |
73 if (HasResult()) { | 99 |
74 PrintOutputOperandTo(stream); | 100 PrintOutputOperandTo(stream); |
75 } | |
76 | 101 |
77 PrintDataTo(stream); | 102 PrintDataTo(stream); |
78 | 103 |
79 if (HasEnvironment()) { | 104 if (HasEnvironment()) { |
80 stream->Add(" "); | 105 stream->Add(" "); |
81 environment()->PrintTo(stream); | 106 environment()->PrintTo(stream); |
82 } | 107 } |
83 | 108 |
84 if (HasPointerMap()) { | 109 if (HasPointerMap()) { |
85 stream->Add(" "); | 110 stream->Add(" "); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 | 409 |
385 void LStoreKeyed::PrintDataTo(StringStream* stream) { | 410 void LStoreKeyed::PrintDataTo(StringStream* stream) { |
386 object()->PrintTo(stream); | 411 object()->PrintTo(stream); |
387 stream->Add("["); | 412 stream->Add("["); |
388 key()->PrintTo(stream); | 413 key()->PrintTo(stream); |
389 stream->Add("] <- "); | 414 stream->Add("] <- "); |
390 value()->PrintTo(stream); | 415 value()->PrintTo(stream); |
391 } | 416 } |
392 | 417 |
393 | 418 |
394 int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { | 419 void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { |
395 LGap* gap = new LGap(block); | 420 LGap* gap = new LGap(block); |
396 int index = -1; | 421 int index = -1; |
397 if (instr->IsControl()) { | 422 if (instr->IsControl()) { |
398 instructions_.Add(gap); | 423 instructions_.Add(gap); |
399 index = instructions_.length(); | 424 index = instructions_.length(); |
400 instructions_.Add(instr); | 425 instructions_.Add(instr); |
401 } else { | 426 } else { |
402 index = instructions_.length(); | 427 index = instructions_.length(); |
403 instructions_.Add(instr); | 428 instructions_.Add(instr); |
404 instructions_.Add(gap); | 429 instructions_.Add(gap); |
405 } | 430 } |
406 if (instr->HasPointerMap()) { | 431 if (instr->HasPointerMap()) { |
407 pointer_maps_.Add(instr->pointer_map()); | 432 pointer_maps_.Add(instr->pointer_map()); |
408 instr->pointer_map()->set_lithium_position(index); | 433 instr->pointer_map()->set_lithium_position(index); |
409 } | 434 } |
410 return index; | |
411 } | 435 } |
412 | 436 |
413 | 437 |
414 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { | 438 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { |
415 return LConstantOperand::Create(constant->id()); | 439 return LConstantOperand::Create(constant->id()); |
416 } | 440 } |
417 | 441 |
418 | 442 |
419 int LChunk::GetParameterStackSlot(int index) const { | 443 int LChunk::GetParameterStackSlot(int index) const { |
420 // The receiver is at index 0, the first parameter at index 1, so we | 444 // The receiver is at index 0, the first parameter at index 1, so we |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { | 676 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { |
653 HEnvironment* hydrogen_env = current_block_->last_environment(); | 677 HEnvironment* hydrogen_env = current_block_->last_environment(); |
654 instr->set_environment(CreateEnvironment(hydrogen_env)); | 678 instr->set_environment(CreateEnvironment(hydrogen_env)); |
655 return instr; | 679 return instr; |
656 } | 680 } |
657 | 681 |
658 | 682 |
659 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, | 683 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, |
660 HInstruction* hinstr, | 684 HInstruction* hinstr, |
661 CanDeoptimize can_deoptimize) { | 685 CanDeoptimize can_deoptimize) { |
662 allocator_->MarkAsCall(); | 686 #ifdef DEBUG |
| 687 instr->VerifyCall(); |
| 688 #endif |
| 689 instr->MarkAsCall(); |
663 instr = AssignPointerMap(instr); | 690 instr = AssignPointerMap(instr); |
664 | 691 |
665 if (hinstr->HasSideEffects()) { | 692 if (hinstr->HasSideEffects()) { |
666 ASSERT(hinstr->next()->IsSimulate()); | 693 ASSERT(hinstr->next()->IsSimulate()); |
667 HSimulate* sim = HSimulate::cast(hinstr->next()); | 694 HSimulate* sim = HSimulate::cast(hinstr->next()); |
668 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber); | 695 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber); |
669 pending_deoptimization_ast_id_ = sim->ast_id(); | 696 pending_deoptimization_ast_id_ = sim->ast_id(); |
670 } | 697 } |
671 | 698 |
672 // If instruction does not have side-effects lazy deoptimization | 699 // If instruction does not have side-effects lazy deoptimization |
673 // after the call will try to deoptimize to the point before the call. | 700 // after the call will try to deoptimize to the point before the call. |
674 // Thus we still need to attach environment to this call even if | 701 // Thus we still need to attach environment to this call even if |
675 // call sequence can not deoptimize eagerly. | 702 // call sequence can not deoptimize eagerly. |
676 bool needs_environment = | 703 bool needs_environment = |
677 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); | 704 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); |
678 if (needs_environment && !instr->HasEnvironment()) { | 705 if (needs_environment && !instr->HasEnvironment()) { |
679 instr = AssignEnvironment(instr); | 706 instr = AssignEnvironment(instr); |
680 } | 707 } |
681 | 708 |
682 return instr; | 709 return instr; |
683 } | 710 } |
684 | 711 |
685 | 712 |
686 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { | 713 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { |
687 allocator_->MarkAsSaveDoubles(); | 714 instr->MarkAsSaveDoubles(); |
688 return instr; | 715 return instr; |
689 } | 716 } |
690 | 717 |
691 | 718 |
692 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { | 719 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
693 ASSERT(!instr->HasPointerMap()); | 720 ASSERT(!instr->HasPointerMap()); |
694 instr->set_pointer_map(new LPointerMap(position_)); | 721 instr->set_pointer_map(new LPointerMap(position_)); |
695 return instr; | 722 return instr; |
696 } | 723 } |
697 | 724 |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 } | 913 } |
887 block->set_argument_count(argument_count_); | 914 block->set_argument_count(argument_count_); |
888 next_block_ = NULL; | 915 next_block_ = NULL; |
889 current_block_ = NULL; | 916 current_block_ = NULL; |
890 } | 917 } |
891 | 918 |
892 | 919 |
893 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 920 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
894 HInstruction* old_current = current_instruction_; | 921 HInstruction* old_current = current_instruction_; |
895 current_instruction_ = current; | 922 current_instruction_ = current; |
896 allocator_->BeginInstruction(); | |
897 if (current->has_position()) position_ = current->position(); | 923 if (current->has_position()) position_ = current->position(); |
898 LInstruction* instr = current->CompileToLithium(this); | 924 LInstruction* instr = current->CompileToLithium(this); |
899 | 925 |
900 if (instr != NULL) { | 926 if (instr != NULL) { |
901 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 927 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
902 instr = AssignPointerMap(instr); | 928 instr = AssignPointerMap(instr); |
903 } | 929 } |
904 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 930 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
905 instr = AssignEnvironment(instr); | 931 instr = AssignEnvironment(instr); |
906 } | 932 } |
907 if (current->IsTest() && !instr->IsGoto()) { | 933 if (current->IsTest() && !instr->IsGoto()) { |
908 ASSERT(instr->IsControl()); | 934 ASSERT(instr->IsControl()); |
909 HTest* test = HTest::cast(current); | 935 HTest* test = HTest::cast(current); |
910 instr->set_hydrogen_value(test->value()); | 936 instr->set_hydrogen_value(test->value()); |
911 HBasicBlock* first = test->FirstSuccessor(); | 937 HBasicBlock* first = test->FirstSuccessor(); |
912 HBasicBlock* second = test->SecondSuccessor(); | 938 HBasicBlock* second = test->SecondSuccessor(); |
913 ASSERT(first != NULL && second != NULL); | 939 ASSERT(first != NULL && second != NULL); |
914 instr->SetBranchTargets(first->block_id(), second->block_id()); | 940 instr->SetBranchTargets(first->block_id(), second->block_id()); |
915 } else { | 941 } else { |
916 instr->set_hydrogen_value(current); | 942 instr->set_hydrogen_value(current); |
917 } | 943 } |
918 | 944 |
919 int index = chunk_->AddInstruction(instr, current_block_); | 945 chunk_->AddInstruction(instr, current_block_); |
920 allocator_->SummarizeInstruction(index); | |
921 } else { | |
922 // This instruction should be omitted. | |
923 allocator_->OmitInstruction(); | |
924 } | 946 } |
925 current_instruction_ = old_current; | 947 current_instruction_ = old_current; |
926 } | 948 } |
927 | 949 |
928 | 950 |
929 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { | 951 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { |
930 if (hydrogen_env == NULL) return NULL; | 952 if (hydrogen_env == NULL) return NULL; |
931 | 953 |
932 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); | 954 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); |
933 int ast_id = hydrogen_env->ast_id(); | 955 int ast_id = hydrogen_env->ast_id(); |
(...skipping 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1891 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 1913 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
1892 HEnvironment* outer = current_block_->last_environment()->outer(); | 1914 HEnvironment* outer = current_block_->last_environment()->outer(); |
1893 current_block_->UpdateEnvironment(outer); | 1915 current_block_->UpdateEnvironment(outer); |
1894 return NULL; | 1916 return NULL; |
1895 } | 1917 } |
1896 | 1918 |
1897 | 1919 |
1898 } } // namespace v8::internal | 1920 } } // namespace v8::internal |
1899 | 1921 |
1900 #endif // V8_TARGET_ARCH_IA32 | 1922 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |