| 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 "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 | 6 |
| 7 #include "src/address-map.h" | 7 #include "src/address-map.h" |
| 8 #include "src/base/adapters.h" | 8 #include "src/base/adapters.h" |
| 9 #include "src/compilation-info.h" | 9 #include "src/compilation-info.h" |
| 10 #include "src/compiler/code-generator-impl.h" | 10 #include "src/compiler/code-generator-impl.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 handlers_(code->zone()), | 51 handlers_(code->zone()), |
| 52 deoptimization_exits_(code->zone()), | 52 deoptimization_exits_(code->zone()), |
| 53 deoptimization_states_(code->zone()), | 53 deoptimization_states_(code->zone()), |
| 54 deoptimization_literals_(code->zone()), | 54 deoptimization_literals_(code->zone()), |
| 55 inlined_function_count_(0), | 55 inlined_function_count_(0), |
| 56 translations_(code->zone()), | 56 translations_(code->zone()), |
| 57 last_lazy_deopt_pc_(0), | 57 last_lazy_deopt_pc_(0), |
| 58 jump_tables_(nullptr), | 58 jump_tables_(nullptr), |
| 59 ools_(nullptr), | 59 ools_(nullptr), |
| 60 osr_pc_offset_(-1), | 60 osr_pc_offset_(-1), |
| 61 optimized_out_literal_id_(-1), |
| 61 source_position_table_builder_(code->zone(), | 62 source_position_table_builder_(code->zone(), |
| 62 info->SourcePositionRecordingMode()), | 63 info->SourcePositionRecordingMode()), |
| 63 protected_instructions_(protected_instructions) { | 64 protected_instructions_(protected_instructions) { |
| 64 for (int i = 0; i < code->InstructionBlockCount(); ++i) { | 65 for (int i = 0; i < code->InstructionBlockCount(); ++i) { |
| 65 new (&labels_[i]) Label; | 66 new (&labels_[i]) Label; |
| 66 } | 67 } |
| 67 CreateFrameAccessState(frame); | 68 CreateFrameAccessState(frame); |
| 68 } | 69 } |
| 69 | 70 |
| 70 Isolate* CodeGenerator::isolate() const { return info_->isolate(); } | 71 Isolate* CodeGenerator::isolate() const { return info_->isolate(); } |
| (...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 // If the pre-call frame state differs from the post-call one, produce the | 634 // If the pre-call frame state differs from the post-call one, produce the |
| 634 // pre-call frame state, too. | 635 // pre-call frame state, too. |
| 635 // TODO(jarin) We might want to avoid building the pre-call frame state | 636 // TODO(jarin) We might want to avoid building the pre-call frame state |
| 636 // because it is only used to get locals and arguments (by the debugger and | 637 // because it is only used to get locals and arguments (by the debugger and |
| 637 // f.arguments), and those are the same in the pre-call and post-call | 638 // f.arguments), and those are the same in the pre-call and post-call |
| 638 // states. | 639 // states. |
| 639 if (!descriptor->state_combine().IsOutputIgnored()) { | 640 if (!descriptor->state_combine().IsOutputIgnored()) { |
| 640 deopt_state_id = BuildTranslation(instr, -1, frame_state_offset, | 641 deopt_state_id = BuildTranslation(instr, -1, frame_state_offset, |
| 641 OutputFrameStateCombine::Ignore()); | 642 OutputFrameStateCombine::Ignore()); |
| 642 } | 643 } |
| 643 #if DEBUG | |
| 644 // Make sure all the values live in stack slots or they are immediates. | |
| 645 // (The values should not live in register because registers are clobbered | |
| 646 // by calls.) | |
| 647 for (size_t i = 0; i < descriptor->GetSize(); i++) { | |
| 648 InstructionOperand* op = instr->InputAt(frame_state_offset + 1 + i); | |
| 649 CHECK(op->IsStackSlot() || op->IsFPStackSlot() || op->IsImmediate()); | |
| 650 } | |
| 651 #endif | |
| 652 safepoints()->RecordLazyDeoptimizationIndex(deopt_state_id); | 644 safepoints()->RecordLazyDeoptimizationIndex(deopt_state_id); |
| 653 } | 645 } |
| 654 } | 646 } |
| 655 | 647 |
| 656 | 648 |
| 657 int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) { | 649 int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) { |
| 658 int result = static_cast<int>(deoptimization_literals_.size()); | 650 int result = static_cast<int>(deoptimization_literals_.size()); |
| 659 for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) { | 651 for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) { |
| 660 if (deoptimization_literals_[i].is_identical_to(literal)) return i; | 652 if (deoptimization_literals_[i].is_identical_to(literal)) return i; |
| 661 } | 653 } |
| 662 deoptimization_literals_.push_back(literal); | 654 deoptimization_literals_.push_back(literal); |
| 663 return result; | 655 return result; |
| 664 } | 656 } |
| 665 | 657 |
| 666 DeoptimizationEntry const& CodeGenerator::GetDeoptimizationEntry( | 658 DeoptimizationEntry const& CodeGenerator::GetDeoptimizationEntry( |
| 667 Instruction* instr, size_t frame_state_offset) { | 659 Instruction* instr, size_t frame_state_offset) { |
| 668 InstructionOperandConverter i(this, instr); | 660 InstructionOperandConverter i(this, instr); |
| 669 int const state_id = i.InputInt32(frame_state_offset); | 661 int const state_id = i.InputInt32(frame_state_offset); |
| 670 return code()->GetDeoptimizationEntry(state_id); | 662 return code()->GetDeoptimizationEntry(state_id); |
| 671 } | 663 } |
| 672 | 664 |
| 673 DeoptimizeReason CodeGenerator::GetDeoptimizationReason( | 665 DeoptimizeReason CodeGenerator::GetDeoptimizationReason( |
| 674 int deoptimization_id) const { | 666 int deoptimization_id) const { |
| 675 size_t const index = static_cast<size_t>(deoptimization_id); | 667 size_t const index = static_cast<size_t>(deoptimization_id); |
| 676 DCHECK_LT(index, deoptimization_states_.size()); | 668 DCHECK_LT(index, deoptimization_states_.size()); |
| 677 return deoptimization_states_[index]->reason(); | 669 return deoptimization_states_[index]->reason(); |
| 678 } | 670 } |
| 679 | 671 |
| 680 void CodeGenerator::TranslateStateValueDescriptor( | 672 void CodeGenerator::TranslateStateValueDescriptor( |
| 681 StateValueDescriptor* desc, Translation* translation, | 673 StateValueDescriptor* desc, StateValueList* nested, |
| 682 InstructionOperandIterator* iter) { | 674 Translation* translation, InstructionOperandIterator* iter) { |
| 683 if (desc->IsNested()) { | 675 if (desc->IsNested()) { |
| 684 translation->BeginCapturedObject(static_cast<int>(desc->size())); | 676 translation->BeginCapturedObject(static_cast<int>(nested->size())); |
| 685 for (size_t index = 0; index < desc->fields().size(); index++) { | 677 for (auto field : *nested) { |
| 686 TranslateStateValueDescriptor(&desc->fields()[index], translation, iter); | 678 TranslateStateValueDescriptor(field.desc, field.nested, translation, |
| 679 iter); |
| 687 } | 680 } |
| 688 } else if (desc->IsDuplicate()) { | 681 } else if (desc->IsDuplicate()) { |
| 689 translation->DuplicateObject(static_cast<int>(desc->id())); | 682 translation->DuplicateObject(static_cast<int>(desc->id())); |
| 690 } else { | 683 } else if (desc->IsPlain()) { |
| 691 DCHECK(desc->IsPlain()); | |
| 692 AddTranslationForOperand(translation, iter->instruction(), iter->Advance(), | 684 AddTranslationForOperand(translation, iter->instruction(), iter->Advance(), |
| 693 desc->type()); | 685 desc->type()); |
| 686 } else { |
| 687 DCHECK(desc->IsOptimizedOut()); |
| 688 if (optimized_out_literal_id_ == -1) { |
| 689 optimized_out_literal_id_ = |
| 690 DefineDeoptimizationLiteral(isolate()->factory()->optimized_out()); |
| 691 } |
| 692 translation->StoreLiteral(optimized_out_literal_id_); |
| 694 } | 693 } |
| 695 } | 694 } |
| 696 | 695 |
| 697 | 696 |
| 698 void CodeGenerator::TranslateFrameStateDescriptorOperands( | 697 void CodeGenerator::TranslateFrameStateDescriptorOperands( |
| 699 FrameStateDescriptor* desc, InstructionOperandIterator* iter, | 698 FrameStateDescriptor* desc, InstructionOperandIterator* iter, |
| 700 OutputFrameStateCombine combine, Translation* translation) { | 699 OutputFrameStateCombine combine, Translation* translation) { |
| 701 for (size_t index = 0; index < desc->GetSize(combine); index++) { | 700 size_t index = 0; |
| 702 switch (combine.kind()) { | 701 StateValueList* values = desc->GetStateValueDescriptors(); |
| 703 case OutputFrameStateCombine::kPushOutput: { | 702 for (StateValueList::iterator it = values->begin(); it != values->end(); |
| 704 DCHECK(combine.GetPushCount() <= iter->instruction()->OutputCount()); | 703 ++it, ++index) { |
| 705 size_t size_without_output = | 704 if (combine.kind() == OutputFrameStateCombine::kPokeAt) { |
| 706 desc->GetSize(OutputFrameStateCombine::Ignore()); | 705 // The result of the call should be placed at position |
| 707 // If the index is past the existing stack items in values_. | 706 // [index_from_top] in the stack (overwriting whatever was |
| 708 if (index >= size_without_output) { | 707 // previously there). |
| 709 // Materialize the result of the call instruction in this slot. | 708 size_t index_from_top = |
| 710 AddTranslationForOperand( | 709 desc->GetSize(combine) - 1 - combine.GetOffsetToPokeAt(); |
| 711 translation, iter->instruction(), | 710 if (index >= index_from_top && |
| 712 iter->instruction()->OutputAt(index - size_without_output), | 711 index < index_from_top + iter->instruction()->OutputCount()) { |
| 713 MachineType::AnyTagged()); | 712 AddTranslationForOperand( |
| 714 continue; | 713 translation, iter->instruction(), |
| 715 } | 714 iter->instruction()->OutputAt(index - index_from_top), |
| 716 break; | 715 MachineType::AnyTagged()); |
| 716 iter->Advance(); // We do not use this input, but we need to |
| 717 // advace, as the input got replaced. |
| 718 continue; |
| 717 } | 719 } |
| 718 case OutputFrameStateCombine::kPokeAt: | |
| 719 // The result of the call should be placed at position | |
| 720 // [index_from_top] in the stack (overwriting whatever was | |
| 721 // previously there). | |
| 722 size_t index_from_top = | |
| 723 desc->GetSize(combine) - 1 - combine.GetOffsetToPokeAt(); | |
| 724 if (index >= index_from_top && | |
| 725 index < index_from_top + iter->instruction()->OutputCount()) { | |
| 726 AddTranslationForOperand( | |
| 727 translation, iter->instruction(), | |
| 728 iter->instruction()->OutputAt(index - index_from_top), | |
| 729 MachineType::AnyTagged()); | |
| 730 iter->Advance(); // We do not use this input, but we need to | |
| 731 // advace, as the input got replaced. | |
| 732 continue; | |
| 733 } | |
| 734 break; | |
| 735 } | 720 } |
| 736 StateValueDescriptor* value_desc = desc->GetStateValueDescriptor(); | 721 TranslateStateValueDescriptor((*it).desc, (*it).nested, translation, iter); |
| 737 TranslateStateValueDescriptor(&value_desc->fields()[index], translation, | 722 } |
| 738 iter); | 723 DCHECK_EQ(desc->GetSize(OutputFrameStateCombine::Ignore()), index); |
| 724 |
| 725 if (combine.kind() == OutputFrameStateCombine::kPushOutput) { |
| 726 DCHECK(combine.GetPushCount() <= iter->instruction()->OutputCount()); |
| 727 for (size_t output = 0; output < combine.GetPushCount(); output++) { |
| 728 // Materialize the result of the call instruction in this slot. |
| 729 AddTranslationForOperand(translation, iter->instruction(), |
| 730 iter->instruction()->OutputAt(output), |
| 731 MachineType::AnyTagged()); |
| 732 } |
| 739 } | 733 } |
| 740 } | 734 } |
| 741 | 735 |
| 742 | 736 |
| 743 void CodeGenerator::BuildTranslationForFrameStateDescriptor( | 737 void CodeGenerator::BuildTranslationForFrameStateDescriptor( |
| 744 FrameStateDescriptor* descriptor, InstructionOperandIterator* iter, | 738 FrameStateDescriptor* descriptor, InstructionOperandIterator* iter, |
| 745 Translation* translation, OutputFrameStateCombine state_combine) { | 739 Translation* translation, OutputFrameStateCombine state_combine) { |
| 746 // Outer-most state must be added to translation first. | 740 // Outer-most state must be added to translation first. |
| 747 if (descriptor->outer_state() != nullptr) { | 741 if (descriptor->outer_state() != nullptr) { |
| 748 BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), iter, | 742 BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), iter, |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 : frame_(gen->frame()), masm_(gen->masm()), next_(gen->ools_) { | 967 : frame_(gen->frame()), masm_(gen->masm()), next_(gen->ools_) { |
| 974 gen->ools_ = this; | 968 gen->ools_ = this; |
| 975 } | 969 } |
| 976 | 970 |
| 977 | 971 |
| 978 OutOfLineCode::~OutOfLineCode() {} | 972 OutOfLineCode::~OutOfLineCode() {} |
| 979 | 973 |
| 980 } // namespace compiler | 974 } // namespace compiler |
| 981 } // namespace internal | 975 } // namespace internal |
| 982 } // namespace v8 | 976 } // namespace v8 |
| OLD | NEW |