OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/hydrogen-osr.h" | 9 #include "src/hydrogen-osr.h" |
10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 int pc_offset = masm()->pc_offset(); | 756 int pc_offset = masm()->pc_offset(); |
757 environment->Register(deoptimization_index, | 757 environment->Register(deoptimization_index, |
758 translation.index(), | 758 translation.index(), |
759 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 759 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
760 deoptimizations_.Add(environment, zone()); | 760 deoptimizations_.Add(environment, zone()); |
761 } | 761 } |
762 } | 762 } |
763 | 763 |
764 | 764 |
765 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, | 765 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, |
| 766 Deoptimizer::DeoptReason deopt_reason, |
766 Deoptimizer::BailoutType bailout_type, | 767 Deoptimizer::BailoutType bailout_type, |
767 const char* detail, Register src1, | 768 Register src1, const Operand& src2) { |
768 const Operand& src2) { | |
769 LEnvironment* environment = instr->environment(); | 769 LEnvironment* environment = instr->environment(); |
770 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 770 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
771 DCHECK(environment->HasBeenRegistered()); | 771 DCHECK(environment->HasBeenRegistered()); |
772 int id = environment->deoptimization_index(); | 772 int id = environment->deoptimization_index(); |
773 DCHECK(info()->IsOptimizing() || info()->IsStub()); | 773 DCHECK(info()->IsOptimizing() || info()->IsStub()); |
774 Address entry = | 774 Address entry = |
775 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 775 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
776 if (entry == NULL) { | 776 if (entry == NULL) { |
777 Abort(kBailoutWasNotPrepared); | 777 Abort(kBailoutWasNotPrepared); |
778 return; | 778 return; |
(...skipping 21 matching lines...) Expand all Loading... |
800 if (info()->ShouldTrapOnDeopt()) { | 800 if (info()->ShouldTrapOnDeopt()) { |
801 Label skip; | 801 Label skip; |
802 if (condition != al) { | 802 if (condition != al) { |
803 __ Branch(&skip, NegateCondition(condition), src1, src2); | 803 __ Branch(&skip, NegateCondition(condition), src1, src2); |
804 } | 804 } |
805 __ stop("trap_on_deopt"); | 805 __ stop("trap_on_deopt"); |
806 __ bind(&skip); | 806 __ bind(&skip); |
807 } | 807 } |
808 | 808 |
809 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), | 809 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), |
810 instr->Mnemonic(), detail); | 810 instr->Mnemonic(), deopt_reason); |
811 DCHECK(info()->IsStub() || frame_is_built_); | 811 DCHECK(info()->IsStub() || frame_is_built_); |
812 // Go through jump table if we need to handle condition, build frame, or | 812 // Go through jump table if we need to handle condition, build frame, or |
813 // restore caller doubles. | 813 // restore caller doubles. |
814 if (condition == al && frame_is_built_ && | 814 if (condition == al && frame_is_built_ && |
815 !info()->saves_caller_doubles()) { | 815 !info()->saves_caller_doubles()) { |
816 DeoptComment(reason); | 816 DeoptComment(reason); |
817 __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2); | 817 __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2); |
818 } else { | 818 } else { |
819 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, | 819 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, |
820 !frame_is_built_); | 820 !frame_is_built_); |
821 // We often have several deopts to the same entry, reuse the last | 821 // We often have several deopts to the same entry, reuse the last |
822 // jump entry if this is the case. | 822 // jump entry if this is the case. |
823 if (jump_table_.is_empty() || | 823 if (jump_table_.is_empty() || |
824 !table_entry.IsEquivalentTo(jump_table_.last())) { | 824 !table_entry.IsEquivalentTo(jump_table_.last())) { |
825 jump_table_.Add(table_entry, zone()); | 825 jump_table_.Add(table_entry, zone()); |
826 } | 826 } |
827 __ Branch(&jump_table_.last().label, condition, src1, src2); | 827 __ Branch(&jump_table_.last().label, condition, src1, src2); |
828 } | 828 } |
829 } | 829 } |
830 | 830 |
831 | 831 |
832 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, | 832 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, |
833 const char* detail, Register src1, | 833 Deoptimizer::DeoptReason deopt_reason, |
834 const Operand& src2) { | 834 Register src1, const Operand& src2) { |
835 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 835 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
836 ? Deoptimizer::LAZY | 836 ? Deoptimizer::LAZY |
837 : Deoptimizer::EAGER; | 837 : Deoptimizer::EAGER; |
838 DeoptimizeIf(condition, instr, bailout_type, detail, src1, src2); | 838 DeoptimizeIf(condition, instr, deopt_reason, bailout_type, src1, src2); |
839 } | 839 } |
840 | 840 |
841 | 841 |
842 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 842 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
843 int length = deoptimizations_.length(); | 843 int length = deoptimizations_.length(); |
844 if (length == 0) return; | 844 if (length == 0) return; |
845 Handle<DeoptimizationInputData> data = | 845 Handle<DeoptimizationInputData> data = |
846 DeoptimizationInputData::New(isolate(), length, TENURED); | 846 DeoptimizationInputData::New(isolate(), length, TENURED); |
847 | 847 |
848 Handle<ByteArray> translations = | 848 Handle<ByteArray> translations = |
(...skipping 2419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3268 } else { | 3268 } else { |
3269 __ dsra(at, key, -shift_size); | 3269 __ dsra(at, key, -shift_size); |
3270 } | 3270 } |
3271 __ Daddu(scratch, scratch, at); | 3271 __ Daddu(scratch, scratch, at); |
3272 } | 3272 } |
3273 | 3273 |
3274 __ ldc1(result, MemOperand(scratch)); | 3274 __ ldc1(result, MemOperand(scratch)); |
3275 | 3275 |
3276 if (instr->hydrogen()->RequiresHoleCheck()) { | 3276 if (instr->hydrogen()->RequiresHoleCheck()) { |
3277 __ lwu(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); | 3277 __ lwu(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); |
3278 DeoptimizeIf(eq, instr, Deopt::kHole, scratch, Operand(kHoleNanUpper32)); | 3278 DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch, |
| 3279 Operand(kHoleNanUpper32)); |
3279 } | 3280 } |
3280 } | 3281 } |
3281 | 3282 |
3282 | 3283 |
3283 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3284 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
3284 HLoadKeyed* hinstr = instr->hydrogen(); | 3285 HLoadKeyed* hinstr = instr->hydrogen(); |
3285 Register elements = ToRegister(instr->elements()); | 3286 Register elements = ToRegister(instr->elements()); |
3286 Register result = ToRegister(instr->result()); | 3287 Register result = ToRegister(instr->result()); |
3287 Register scratch = scratch0(); | 3288 Register scratch = scratch0(); |
3288 Register store_base = scratch; | 3289 Register store_base = scratch; |
(...skipping 1759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5048 __ mov(input_reg, zero_reg); // In delay slot. | 5049 __ mov(input_reg, zero_reg); // In delay slot. |
5049 | 5050 |
5050 __ bind(&check_bools); | 5051 __ bind(&check_bools); |
5051 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 5052 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
5052 __ Branch(&check_false, ne, scratch2, Operand(at)); | 5053 __ Branch(&check_false, ne, scratch2, Operand(at)); |
5053 __ Branch(USE_DELAY_SLOT, &done); | 5054 __ Branch(USE_DELAY_SLOT, &done); |
5054 __ li(input_reg, Operand(1)); // In delay slot. | 5055 __ li(input_reg, Operand(1)); // In delay slot. |
5055 | 5056 |
5056 __ bind(&check_false); | 5057 __ bind(&check_false); |
5057 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 5058 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
5058 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedTrueFalse, | 5059 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean, |
5059 scratch2, Operand(at)); | 5060 scratch2, Operand(at)); |
5060 __ Branch(USE_DELAY_SLOT, &done); | 5061 __ Branch(USE_DELAY_SLOT, &done); |
5061 __ mov(input_reg, zero_reg); // In delay slot. | 5062 __ mov(input_reg, zero_reg); // In delay slot. |
5062 } else { | 5063 } else { |
5063 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch1, | 5064 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch1, |
5064 Operand(at)); | 5065 Operand(at)); |
5065 | 5066 |
5066 // Load the double value. | 5067 // Load the double value. |
5067 __ ldc1(double_scratch, | 5068 __ ldc1(double_scratch, |
5068 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 5069 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5810 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5811 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
5811 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5812 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
5812 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5813 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
5813 // needed return address), even though the implementation of LAZY and EAGER is | 5814 // needed return address), even though the implementation of LAZY and EAGER is |
5814 // now identical. When LAZY is eventually completely folded into EAGER, remove | 5815 // now identical. When LAZY is eventually completely folded into EAGER, remove |
5815 // the special case below. | 5816 // the special case below. |
5816 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5817 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
5817 type = Deoptimizer::LAZY; | 5818 type = Deoptimizer::LAZY; |
5818 } | 5819 } |
5819 | 5820 |
5820 DeoptimizeIf(al, instr, type, instr->hydrogen()->reason(), zero_reg, | 5821 DeoptimizeIf(al, instr, instr->hydrogen()->reason(), type, zero_reg, |
5821 Operand(zero_reg)); | 5822 Operand(zero_reg)); |
5822 } | 5823 } |
5823 | 5824 |
5824 | 5825 |
5825 void LCodeGen::DoDummy(LDummy* instr) { | 5826 void LCodeGen::DoDummy(LDummy* instr) { |
5826 // Nothing to see here, move on! | 5827 // Nothing to see here, move on! |
5827 } | 5828 } |
5828 | 5829 |
5829 | 5830 |
5830 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5831 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6055 __ li(at, scope_info); | 6056 __ li(at, scope_info); |
6056 __ Push(at, ToRegister(instr->function())); | 6057 __ Push(at, ToRegister(instr->function())); |
6057 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 6058 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
6058 RecordSafepoint(Safepoint::kNoLazyDeopt); | 6059 RecordSafepoint(Safepoint::kNoLazyDeopt); |
6059 } | 6060 } |
6060 | 6061 |
6061 | 6062 |
6062 #undef __ | 6063 #undef __ |
6063 | 6064 |
6064 } } // namespace v8::internal | 6065 } } // namespace v8::internal |
OLD | NEW |