OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1171 Register left_reg = ToRegister(instr->left()); | 1171 Register left_reg = ToRegister(instr->left()); |
1172 Register right_reg = ToRegister(instr->right()); | 1172 Register right_reg = ToRegister(instr->right()); |
1173 Register result_reg = ToRegister(instr->result()); | 1173 Register result_reg = ToRegister(instr->result()); |
1174 Register scratch = scratch0(); | 1174 Register scratch = scratch0(); |
1175 ASSERT(!scratch.is(left_reg)); | 1175 ASSERT(!scratch.is(left_reg)); |
1176 ASSERT(!scratch.is(right_reg)); | 1176 ASSERT(!scratch.is(right_reg)); |
1177 ASSERT(!scratch.is(result_reg)); | 1177 ASSERT(!scratch.is(result_reg)); |
1178 DwVfpRegister dividend = ToDoubleRegister(instr->temp()); | 1178 DwVfpRegister dividend = ToDoubleRegister(instr->temp()); |
1179 DwVfpRegister divisor = ToDoubleRegister(instr->temp2()); | 1179 DwVfpRegister divisor = ToDoubleRegister(instr->temp2()); |
1180 ASSERT(!divisor.is(dividend)); | 1180 ASSERT(!divisor.is(dividend)); |
1181 DwVfpRegister quotient = double_scratch0(); | 1181 LowDwVfpRegister quotient = double_scratch0(); |
1182 ASSERT(!quotient.is(dividend)); | 1182 ASSERT(!quotient.is(dividend)); |
1183 ASSERT(!quotient.is(divisor)); | 1183 ASSERT(!quotient.is(divisor)); |
1184 | 1184 |
1185 Label done; | 1185 Label done; |
1186 // Check for x % 0, we have to deopt in this case because we can't return a | 1186 // Check for x % 0, we have to deopt in this case because we can't return a |
1187 // NaN. | 1187 // NaN. |
1188 if (right->CanBeZero()) { | 1188 if (right->CanBeZero()) { |
1189 __ cmp(right_reg, Operand::Zero()); | 1189 __ cmp(right_reg, Operand::Zero()); |
1190 DeoptimizeIf(eq, instr->environment()); | 1190 DeoptimizeIf(eq, instr->environment()); |
1191 } | 1191 } |
1192 | 1192 |
1193 __ Move(result_reg, left_reg); | 1193 __ Move(result_reg, left_reg); |
1194 // Load the arguments in VFP registers. The divisor value is preloaded | 1194 // Load the arguments in VFP registers. The divisor value is preloaded |
1195 // before. Be careful that 'right_reg' is only live on entry. | 1195 // before. Be careful that 'right_reg' is only live on entry. |
1196 // TODO(svenpanne) The last comments seems to be wrong nowadays. | 1196 // TODO(svenpanne) The last comments seems to be wrong nowadays. |
1197 __ vmov(dividend.low(), left_reg); | 1197 __ vmov(double_scratch0().low(), left_reg); |
1198 __ vmov(divisor.low(), right_reg); | 1198 __ vcvt_f64_s32(dividend, double_scratch0().low()); |
1199 | 1199 __ vmov(double_scratch0().low(), right_reg); |
1200 __ vcvt_f64_s32(dividend, dividend.low()); | 1200 __ vcvt_f64_s32(divisor, double_scratch0().low()); |
1201 __ vcvt_f64_s32(divisor, divisor.low()); | |
1202 | 1201 |
1203 // We do not care about the sign of the divisor. Note that we still handle | 1202 // We do not care about the sign of the divisor. Note that we still handle |
1204 // the kMinInt % -1 case correctly, though. | 1203 // the kMinInt % -1 case correctly, though. |
1205 __ vabs(divisor, divisor); | 1204 __ vabs(divisor, divisor); |
1206 // Compute the quotient and round it to a 32bit integer. | 1205 // Compute the quotient and round it to a 32bit integer. |
1207 __ vdiv(quotient, dividend, divisor); | 1206 __ vdiv(quotient, dividend, divisor); |
1208 __ vcvt_s32_f64(quotient.low(), quotient); | 1207 __ vcvt_s32_f64(quotient.low(), quotient); |
1209 __ vcvt_f64_s32(quotient, quotient.low()); | 1208 __ vcvt_f64_s32(quotient, quotient.low()); |
1210 | 1209 |
1211 // Compute the remainder in result. | 1210 // Compute the remainder in result. |
1212 DwVfpRegister double_scratch = dividend; | 1211 __ vmul(double_scratch0(), divisor, quotient); |
1213 __ vmul(double_scratch, divisor, quotient); | 1212 __ vcvt_s32_f64(double_scratch0().low(), double_scratch0()); |
1214 __ vcvt_s32_f64(double_scratch.low(), double_scratch); | 1213 __ vmov(scratch, double_scratch0().low()); |
1215 __ vmov(scratch, double_scratch.low()); | |
1216 __ sub(result_reg, left_reg, scratch, SetCC); | 1214 __ sub(result_reg, left_reg, scratch, SetCC); |
1217 | 1215 |
1218 // If we care about -0, test if the dividend is <0 and the result is 0. | 1216 // If we care about -0, test if the dividend is <0 and the result is 0. |
1219 if (left->CanBeNegative() && | 1217 if (left->CanBeNegative() && |
1220 hmod->CanBeZero() && | 1218 hmod->CanBeZero() && |
1221 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1219 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1222 __ b(ne, &done); | 1220 __ b(ne, &done); |
1223 __ cmp(left_reg, Operand::Zero()); | 1221 __ cmp(left_reg, Operand::Zero()); |
1224 DeoptimizeIf(mi, instr->environment()); | 1222 DeoptimizeIf(mi, instr->environment()); |
1225 } | 1223 } |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1405 HInstruction::kAllUsesTruncatingToInt32)) { | 1403 HInstruction::kAllUsesTruncatingToInt32)) { |
1406 // Compute remainder and deopt if it's not zero. | 1404 // Compute remainder and deopt if it's not zero. |
1407 const Register remainder = scratch0(); | 1405 const Register remainder = scratch0(); |
1408 __ mls(remainder, result, right, left); | 1406 __ mls(remainder, result, right, left); |
1409 __ cmp(remainder, Operand::Zero()); | 1407 __ cmp(remainder, Operand::Zero()); |
1410 DeoptimizeIf(ne, instr->environment()); | 1408 DeoptimizeIf(ne, instr->environment()); |
1411 } | 1409 } |
1412 } else { | 1410 } else { |
1413 const DoubleRegister vleft = ToDoubleRegister(instr->temp()); | 1411 const DoubleRegister vleft = ToDoubleRegister(instr->temp()); |
1414 const DoubleRegister vright = double_scratch0(); | 1412 const DoubleRegister vright = double_scratch0(); |
1415 __ vmov(vleft.low(), left); | 1413 __ vmov(double_scratch0().low(), left); |
1416 __ vmov(vright.low(), right); | 1414 __ vcvt_f64_s32(vleft, double_scratch0().low()); |
1417 __ vcvt_f64_s32(vleft, vleft.low()); | 1415 __ vmov(double_scratch0().low(), right); |
1418 __ vcvt_f64_s32(vright, vright.low()); | 1416 __ vcvt_f64_s32(vright, double_scratch0().low()); |
1419 __ vdiv(vleft, vleft, vright); // vleft now contains the result. | 1417 __ vdiv(vleft, vleft, vright); // vleft now contains the result. |
1420 __ vcvt_s32_f64(vright.low(), vleft); | 1418 __ vcvt_s32_f64(double_scratch0().low(), vleft); |
1421 __ vmov(result, vright.low()); | 1419 __ vmov(result, double_scratch0().low()); |
1422 | 1420 |
1423 if (!instr->hydrogen()->CheckFlag( | 1421 if (!instr->hydrogen()->CheckFlag( |
1424 HInstruction::kAllUsesTruncatingToInt32)) { | 1422 HInstruction::kAllUsesTruncatingToInt32)) { |
1425 // Deopt if exact conversion to integer was not possible. | 1423 // Deopt if exact conversion to integer was not possible. |
1426 // Use vright as scratch register. | 1424 // Use vright as scratch register. |
1427 __ vcvt_f64_s32(vright, vright.low()); | 1425 __ vcvt_f64_s32(double_scratch0(), double_scratch0().low()); |
1428 __ VFPCompareAndSetFlags(vleft, vright); | 1426 __ VFPCompareAndSetFlags(vleft, double_scratch0()); |
1429 DeoptimizeIf(ne, instr->environment()); | 1427 DeoptimizeIf(ne, instr->environment()); |
1430 } | 1428 } |
1431 } | 1429 } |
1432 } | 1430 } |
1433 | 1431 |
1434 | 1432 |
1435 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { | 1433 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { |
1436 DwVfpRegister addend = ToDoubleRegister(instr->addend()); | 1434 DwVfpRegister addend = ToDoubleRegister(instr->addend()); |
1437 DwVfpRegister multiplier = ToDoubleRegister(instr->multiplier()); | 1435 DwVfpRegister multiplier = ToDoubleRegister(instr->multiplier()); |
1438 DwVfpRegister multiplicand = ToDoubleRegister(instr->multiplicand()); | 1436 DwVfpRegister multiplicand = ToDoubleRegister(instr->multiplicand()); |
(...skipping 1740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3179 int additional_offset = instr->additional_index() << element_size_shift; | 3177 int additional_offset = instr->additional_index() << element_size_shift; |
3180 | 3178 |
3181 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3179 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
3182 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3180 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
3183 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3181 DwVfpRegister result = ToDoubleRegister(instr->result()); |
3184 Operand operand = key_is_constant | 3182 Operand operand = key_is_constant |
3185 ? Operand(constant_key << element_size_shift) | 3183 ? Operand(constant_key << element_size_shift) |
3186 : Operand(key, LSL, shift_size); | 3184 : Operand(key, LSL, shift_size); |
3187 __ add(scratch0(), external_pointer, operand); | 3185 __ add(scratch0(), external_pointer, operand); |
3188 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 3186 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
3189 __ vldr(kScratchDoubleReg.low(), scratch0(), additional_offset); | 3187 __ vldr(double_scratch0().low(), scratch0(), additional_offset); |
3190 __ vcvt_f64_f32(result, kScratchDoubleReg.low()); | 3188 __ vcvt_f64_f32(result, double_scratch0().low()); |
3191 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | 3189 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
3192 __ vldr(result, scratch0(), additional_offset); | 3190 __ vldr(result, scratch0(), additional_offset); |
3193 } | 3191 } |
3194 } else { | 3192 } else { |
3195 Register result = ToRegister(instr->result()); | 3193 Register result = ToRegister(instr->result()); |
3196 MemOperand mem_operand = PrepareKeyedOperand( | 3194 MemOperand mem_operand = PrepareKeyedOperand( |
3197 key, external_pointer, key_is_constant, constant_key, | 3195 key, external_pointer, key_is_constant, constant_key, |
3198 element_size_shift, shift_size, | 3196 element_size_shift, shift_size, |
3199 instr->additional_index(), additional_offset); | 3197 instr->additional_index(), additional_offset); |
3200 switch (elements_kind) { | 3198 switch (elements_kind) { |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3748 } | 3746 } |
3749 } | 3747 } |
3750 | 3748 |
3751 | 3749 |
3752 void LCodeGen::DoMathFloor(LMathFloor* instr) { | 3750 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
3753 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3751 DwVfpRegister input = ToDoubleRegister(instr->value()); |
3754 Register result = ToRegister(instr->result()); | 3752 Register result = ToRegister(instr->result()); |
3755 Register input_high = scratch0(); | 3753 Register input_high = scratch0(); |
3756 Label done, exact; | 3754 Label done, exact; |
3757 | 3755 |
3758 __ vmov(input_high, input.high()); | |
3759 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact); | 3756 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact); |
3760 DeoptimizeIf(al, instr->environment()); | 3757 DeoptimizeIf(al, instr->environment()); |
3761 | 3758 |
3762 __ bind(&exact); | 3759 __ bind(&exact); |
3763 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3760 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3764 // Test for -0. | 3761 // Test for -0. |
3765 __ cmp(result, Operand::Zero()); | 3762 __ cmp(result, Operand::Zero()); |
3766 __ b(ne, &done); | 3763 __ b(ne, &done); |
3767 __ cmp(input_high, Operand::Zero()); | 3764 __ cmp(input_high, Operand::Zero()); |
3768 DeoptimizeIf(mi, instr->environment()); | 3765 DeoptimizeIf(mi, instr->environment()); |
(...skipping 12 matching lines...) Expand all Loading... |
3781 Label convert, done; | 3778 Label convert, done; |
3782 | 3779 |
3783 __ Vmov(dot_five, 0.5, scratch0()); | 3780 __ Vmov(dot_five, 0.5, scratch0()); |
3784 __ vabs(double_scratch1, input); | 3781 __ vabs(double_scratch1, input); |
3785 __ VFPCompareAndSetFlags(double_scratch1, dot_five); | 3782 __ VFPCompareAndSetFlags(double_scratch1, dot_five); |
3786 // If input is in [-0.5, -0], the result is -0. | 3783 // If input is in [-0.5, -0], the result is -0. |
3787 // If input is in [+0, +0.5[, the result is +0. | 3784 // If input is in [+0, +0.5[, the result is +0. |
3788 // If the input is +0.5, the result is 1. | 3785 // If the input is +0.5, the result is 1. |
3789 __ b(hi, &convert); // Out of [-0.5, +0.5]. | 3786 __ b(hi, &convert); // Out of [-0.5, +0.5]. |
3790 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3787 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3791 __ vmov(input_high, input.high()); | 3788 __ VmovHigh(input_high, input); |
3792 __ cmp(input_high, Operand::Zero()); | 3789 __ cmp(input_high, Operand::Zero()); |
3793 DeoptimizeIf(mi, instr->environment()); // [-0.5, -0]. | 3790 DeoptimizeIf(mi, instr->environment()); // [-0.5, -0]. |
3794 } | 3791 } |
3795 __ VFPCompareAndSetFlags(input, dot_five); | 3792 __ VFPCompareAndSetFlags(input, dot_five); |
3796 __ mov(result, Operand(1), LeaveCC, eq); // +0.5. | 3793 __ mov(result, Operand(1), LeaveCC, eq); // +0.5. |
3797 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on | 3794 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on |
3798 // flag kBailoutOnMinusZero. | 3795 // flag kBailoutOnMinusZero. |
3799 __ mov(result, Operand::Zero(), LeaveCC, ne); | 3796 __ mov(result, Operand::Zero(), LeaveCC, ne); |
3800 __ b(&done); | 3797 __ b(&done); |
3801 | 3798 |
3802 __ bind(&convert); | 3799 __ bind(&convert); |
3803 __ vadd(input_plus_dot_five, input, dot_five); | 3800 __ vadd(input_plus_dot_five, input, dot_five); |
3804 __ vmov(input_high, input_plus_dot_five.high()); | |
3805 // Reuse dot_five (double_scratch0) as we no longer need this value. | 3801 // Reuse dot_five (double_scratch0) as we no longer need this value. |
3806 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(), | 3802 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(), |
3807 &done, &done); | 3803 &done, &done); |
3808 DeoptimizeIf(al, instr->environment()); | 3804 DeoptimizeIf(al, instr->environment()); |
3809 __ bind(&done); | 3805 __ bind(&done); |
3810 } | 3806 } |
3811 | 3807 |
3812 | 3808 |
3813 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { | 3809 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { |
3814 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3810 DwVfpRegister input = ToDoubleRegister(instr->value()); |
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4717 __ bind(deferred->exit()); | 4713 __ bind(deferred->exit()); |
4718 } | 4714 } |
4719 | 4715 |
4720 | 4716 |
4721 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, | 4717 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, |
4722 LOperand* value, | 4718 LOperand* value, |
4723 IntegerSignedness signedness) { | 4719 IntegerSignedness signedness) { |
4724 Label slow; | 4720 Label slow; |
4725 Register src = ToRegister(value); | 4721 Register src = ToRegister(value); |
4726 Register dst = ToRegister(instr->result()); | 4722 Register dst = ToRegister(instr->result()); |
4727 DwVfpRegister dbl_scratch = double_scratch0(); | 4723 LowDwVfpRegister dbl_scratch = double_scratch0(); |
4728 SwVfpRegister flt_scratch = dbl_scratch.low(); | |
4729 | 4724 |
4730 // Preserve the value of all registers. | 4725 // Preserve the value of all registers. |
4731 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4726 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4732 | 4727 |
4733 Label done; | 4728 Label done; |
4734 if (signedness == SIGNED_INT32) { | 4729 if (signedness == SIGNED_INT32) { |
4735 // There was overflow, so bits 30 and 31 of the original integer | 4730 // There was overflow, so bits 30 and 31 of the original integer |
4736 // disagree. Try to allocate a heap number in new space and store | 4731 // disagree. Try to allocate a heap number in new space and store |
4737 // the value in there. If that fails, call the runtime system. | 4732 // the value in there. If that fails, call the runtime system. |
4738 if (dst.is(src)) { | 4733 if (dst.is(src)) { |
4739 __ SmiUntag(src, dst); | 4734 __ SmiUntag(src, dst); |
4740 __ eor(src, src, Operand(0x80000000)); | 4735 __ eor(src, src, Operand(0x80000000)); |
4741 } | 4736 } |
4742 __ vmov(flt_scratch, src); | 4737 __ vmov(dbl_scratch.low(), src); |
4743 __ vcvt_f64_s32(dbl_scratch, flt_scratch); | 4738 __ vcvt_f64_s32(dbl_scratch, dbl_scratch.low()); |
4744 } else { | 4739 } else { |
4745 __ vmov(flt_scratch, src); | 4740 __ vmov(dbl_scratch.low(), src); |
4746 __ vcvt_f64_u32(dbl_scratch, flt_scratch); | 4741 __ vcvt_f64_u32(dbl_scratch, dbl_scratch.low()); |
4747 } | 4742 } |
4748 | 4743 |
4749 if (FLAG_inline_new) { | 4744 if (FLAG_inline_new) { |
4750 __ LoadRoot(scratch0(), Heap::kHeapNumberMapRootIndex); | 4745 __ LoadRoot(scratch0(), Heap::kHeapNumberMapRootIndex); |
4751 __ AllocateHeapNumber(r5, r3, r4, scratch0(), &slow, DONT_TAG_RESULT); | 4746 __ AllocateHeapNumber(r5, r3, r4, scratch0(), &slow, DONT_TAG_RESULT); |
4752 __ Move(dst, r5); | 4747 __ Move(dst, r5); |
4753 __ b(&done); | 4748 __ b(&done); |
4754 } | 4749 } |
4755 | 4750 |
4756 // Slow case: Call the runtime system to do the number allocation. | 4751 // Slow case: Call the runtime system to do the number allocation. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4797 HLoadKeyed* load = HLoadKeyed::cast(change_input); | 4792 HLoadKeyed* load = HLoadKeyed::cast(change_input); |
4798 convert_hole = load->UsesMustHandleHole(); | 4793 convert_hole = load->UsesMustHandleHole(); |
4799 } | 4794 } |
4800 | 4795 |
4801 Label no_special_nan_handling; | 4796 Label no_special_nan_handling; |
4802 Label done; | 4797 Label done; |
4803 if (convert_hole) { | 4798 if (convert_hole) { |
4804 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); | 4799 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); |
4805 __ VFPCompareAndSetFlags(input_reg, input_reg); | 4800 __ VFPCompareAndSetFlags(input_reg, input_reg); |
4806 __ b(vc, &no_special_nan_handling); | 4801 __ b(vc, &no_special_nan_handling); |
4807 __ vmov(scratch, input_reg.high()); | 4802 __ VmovHigh(scratch, input_reg); |
4808 __ cmp(scratch, Operand(kHoleNanUpper32)); | 4803 __ cmp(scratch, Operand(kHoleNanUpper32)); |
4809 // If not the hole NaN, force the NaN to be canonical. | 4804 // If not the hole NaN, force the NaN to be canonical. |
4810 __ VFPCanonicalizeNaN(input_reg, ne); | 4805 __ VFPCanonicalizeNaN(input_reg, ne); |
4811 __ b(ne, &no_special_nan_handling); | 4806 __ b(ne, &no_special_nan_handling); |
4812 __ Move(reg, factory()->the_hole_value()); | 4807 __ Move(reg, factory()->the_hole_value()); |
4813 __ b(&done); | 4808 __ b(&done); |
4814 } | 4809 } |
4815 | 4810 |
4816 __ bind(&no_special_nan_handling); | 4811 __ bind(&no_special_nan_handling); |
4817 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4812 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4897 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4892 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
4898 __ cmp(input_reg, Operand(ip)); | 4893 __ cmp(input_reg, Operand(ip)); |
4899 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) { | 4894 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) { |
4900 __ b(eq, &convert); | 4895 __ b(eq, &convert); |
4901 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 4896 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
4902 __ cmp(input_reg, Operand(ip)); | 4897 __ cmp(input_reg, Operand(ip)); |
4903 } | 4898 } |
4904 DeoptimizeIf(ne, env); | 4899 DeoptimizeIf(ne, env); |
4905 | 4900 |
4906 __ bind(&convert); | 4901 __ bind(&convert); |
4907 __ LoadRoot(ip, Heap::kNanValueRootIndex); | 4902 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
4908 __ sub(ip, ip, Operand(kHeapObjectTag)); | 4903 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag); |
4909 __ vldr(result_reg, ip, HeapNumber::kValueOffset); | |
4910 __ jmp(&done); | 4904 __ jmp(&done); |
4911 | 4905 |
4912 __ bind(&heap_number); | 4906 __ bind(&heap_number); |
4913 } | 4907 } |
4914 // Heap number to double register conversion. | 4908 // Heap number to double register conversion. |
4915 __ sub(ip, input_reg, Operand(kHeapObjectTag)); | 4909 __ vldr(result_reg, input_reg, HeapNumber::kValueOffset - kHeapObjectTag); |
4916 __ vldr(result_reg, ip, HeapNumber::kValueOffset); | |
4917 if (deoptimize_on_minus_zero) { | 4910 if (deoptimize_on_minus_zero) { |
4918 __ vmov(ip, result_reg.low()); | 4911 __ VmovLow(scratch, result_reg); |
4919 __ cmp(ip, Operand::Zero()); | 4912 __ cmp(scratch, Operand::Zero()); |
4920 __ b(ne, &done); | 4913 __ b(ne, &done); |
4921 __ vmov(ip, result_reg.high()); | 4914 __ VmovHigh(scratch, result_reg); |
4922 __ cmp(ip, Operand(HeapNumber::kSignMask)); | 4915 __ cmp(scratch, Operand(HeapNumber::kSignMask)); |
4923 DeoptimizeIf(eq, env); | 4916 DeoptimizeIf(eq, env); |
4924 } | 4917 } |
4925 __ jmp(&done); | 4918 __ jmp(&done); |
4926 } else { | 4919 } else { |
4927 __ SmiUntag(scratch, input_reg); | 4920 __ SmiUntag(scratch, input_reg); |
4928 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); | 4921 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); |
4929 } | 4922 } |
4930 | 4923 |
4931 // Smi to double register conversion | 4924 // Smi to double register conversion |
4932 __ bind(&load_smi); | 4925 __ bind(&load_smi); |
4933 // scratch: untagged value of input_reg | 4926 // scratch: untagged value of input_reg |
4934 __ vmov(flt_scratch, scratch); | 4927 __ vmov(flt_scratch, scratch); |
4935 __ vcvt_f64_s32(result_reg, flt_scratch); | 4928 __ vcvt_f64_s32(result_reg, flt_scratch); |
4936 __ bind(&done); | 4929 __ bind(&done); |
4937 } | 4930 } |
4938 | 4931 |
4939 | 4932 |
4940 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 4933 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
4941 Register input_reg = ToRegister(instr->value()); | 4934 Register input_reg = ToRegister(instr->value()); |
4942 Register scratch1 = scratch0(); | 4935 Register scratch1 = scratch0(); |
4943 Register scratch2 = ToRegister(instr->temp()); | 4936 Register scratch2 = ToRegister(instr->temp()); |
4944 DwVfpRegister double_scratch = double_scratch0(); | 4937 LowDwVfpRegister double_scratch = double_scratch0(); |
4945 DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3()); | 4938 DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3()); |
4946 | 4939 |
4947 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); | 4940 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); |
4948 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); | 4941 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); |
4949 | 4942 |
4950 Label done; | 4943 Label done; |
4951 | 4944 |
4952 // The input was optimistically untagged; revert it. | 4945 // The input was optimistically untagged; revert it. |
4953 // The carry flag is set when we reach this deferred code as we just executed | 4946 // The carry flag is set when we reach this deferred code as we just executed |
4954 // SmiUntag(heap_object, SetCC) | 4947 // SmiUntag(heap_object, SetCC) |
(...skipping 27 matching lines...) Expand all Loading... |
4982 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset); | 4975 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset); |
4983 | 4976 |
4984 __ ECMAToInt32(input_reg, double_scratch2, | 4977 __ ECMAToInt32(input_reg, double_scratch2, |
4985 scratch1, scratch2, scratch3, double_scratch); | 4978 scratch1, scratch2, scratch3, double_scratch); |
4986 | 4979 |
4987 } else { | 4980 } else { |
4988 // Deoptimize if we don't have a heap number. | 4981 // Deoptimize if we don't have a heap number. |
4989 DeoptimizeIf(ne, instr->environment()); | 4982 DeoptimizeIf(ne, instr->environment()); |
4990 | 4983 |
4991 __ sub(ip, input_reg, Operand(kHeapObjectTag)); | 4984 __ sub(ip, input_reg, Operand(kHeapObjectTag)); |
4992 __ vldr(double_scratch, ip, HeapNumber::kValueOffset); | 4985 __ vldr(double_scratch2, ip, HeapNumber::kValueOffset); |
4993 __ TryDoubleToInt32Exact(input_reg, double_scratch, double_scratch2); | 4986 __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch); |
4994 DeoptimizeIf(ne, instr->environment()); | 4987 DeoptimizeIf(ne, instr->environment()); |
4995 | 4988 |
4996 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4989 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
4997 __ cmp(input_reg, Operand::Zero()); | 4990 __ cmp(input_reg, Operand::Zero()); |
4998 __ b(ne, &done); | 4991 __ b(ne, &done); |
4999 __ vmov(scratch1, double_scratch.high()); | 4992 __ VmovHigh(scratch1, double_scratch2); |
5000 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 4993 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
5001 DeoptimizeIf(ne, instr->environment()); | 4994 DeoptimizeIf(ne, instr->environment()); |
5002 } | 4995 } |
5003 } | 4996 } |
5004 __ bind(&done); | 4997 __ bind(&done); |
5005 } | 4998 } |
5006 | 4999 |
5007 | 5000 |
5008 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 5001 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
5009 class DeferredTaggedToI: public LDeferredCode { | 5002 class DeferredTaggedToI: public LDeferredCode { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5062 instr->environment(), | 5055 instr->environment(), |
5063 mode); | 5056 mode); |
5064 } | 5057 } |
5065 | 5058 |
5066 | 5059 |
5067 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5060 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
5068 Register result_reg = ToRegister(instr->result()); | 5061 Register result_reg = ToRegister(instr->result()); |
5069 Register scratch1 = scratch0(); | 5062 Register scratch1 = scratch0(); |
5070 Register scratch2 = ToRegister(instr->temp()); | 5063 Register scratch2 = ToRegister(instr->temp()); |
5071 DwVfpRegister double_input = ToDoubleRegister(instr->value()); | 5064 DwVfpRegister double_input = ToDoubleRegister(instr->value()); |
5072 DwVfpRegister double_scratch = double_scratch0(); | 5065 LowDwVfpRegister double_scratch = double_scratch0(); |
5073 | 5066 |
5074 if (instr->truncating()) { | 5067 if (instr->truncating()) { |
5075 Register scratch3 = ToRegister(instr->temp2()); | 5068 Register scratch3 = ToRegister(instr->temp2()); |
5076 __ ECMAToInt32(result_reg, double_input, | 5069 __ ECMAToInt32(result_reg, double_input, |
5077 scratch1, scratch2, scratch3, double_scratch); | 5070 scratch1, scratch2, scratch3, double_scratch); |
5078 } else { | 5071 } else { |
5079 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); | 5072 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); |
5080 // Deoptimize if the input wasn't a int32 (inside a double). | 5073 // Deoptimize if the input wasn't a int32 (inside a double). |
5081 DeoptimizeIf(ne, instr->environment()); | 5074 DeoptimizeIf(ne, instr->environment()); |
5082 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5075 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
5083 Label done; | 5076 Label done; |
5084 __ cmp(result_reg, Operand::Zero()); | 5077 __ cmp(result_reg, Operand::Zero()); |
5085 __ b(ne, &done); | 5078 __ b(ne, &done); |
5086 __ vmov(scratch1, double_input.high()); | 5079 __ VmovHigh(scratch1, double_input); |
5087 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 5080 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
5088 DeoptimizeIf(ne, instr->environment()); | 5081 DeoptimizeIf(ne, instr->environment()); |
5089 __ bind(&done); | 5082 __ bind(&done); |
5090 } | 5083 } |
5091 } | 5084 } |
5092 } | 5085 } |
5093 | 5086 |
5094 | 5087 |
5095 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 5088 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
5096 Register result_reg = ToRegister(instr->result()); | 5089 Register result_reg = ToRegister(instr->result()); |
5097 Register scratch1 = scratch0(); | 5090 Register scratch1 = scratch0(); |
5098 Register scratch2 = ToRegister(instr->temp()); | 5091 Register scratch2 = ToRegister(instr->temp()); |
5099 DwVfpRegister double_input = ToDoubleRegister(instr->value()); | 5092 DwVfpRegister double_input = ToDoubleRegister(instr->value()); |
5100 DwVfpRegister double_scratch = double_scratch0(); | 5093 LowDwVfpRegister double_scratch = double_scratch0(); |
5101 | 5094 |
5102 if (instr->truncating()) { | 5095 if (instr->truncating()) { |
5103 Register scratch3 = ToRegister(instr->temp2()); | 5096 Register scratch3 = ToRegister(instr->temp2()); |
5104 __ ECMAToInt32(result_reg, double_input, | 5097 __ ECMAToInt32(result_reg, double_input, |
5105 scratch1, scratch2, scratch3, double_scratch); | 5098 scratch1, scratch2, scratch3, double_scratch); |
5106 } else { | 5099 } else { |
5107 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); | 5100 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); |
5108 // Deoptimize if the input wasn't a int32 (inside a double). | 5101 // Deoptimize if the input wasn't a int32 (inside a double). |
5109 DeoptimizeIf(ne, instr->environment()); | 5102 DeoptimizeIf(ne, instr->environment()); |
5110 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5103 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
5111 Label done; | 5104 Label done; |
5112 __ cmp(result_reg, Operand::Zero()); | 5105 __ cmp(result_reg, Operand::Zero()); |
5113 __ b(ne, &done); | 5106 __ b(ne, &done); |
5114 __ vmov(scratch1, double_input.high()); | 5107 __ VmovHigh(scratch1, double_input); |
5115 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 5108 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
5116 DeoptimizeIf(ne, instr->environment()); | 5109 DeoptimizeIf(ne, instr->environment()); |
5117 __ bind(&done); | 5110 __ bind(&done); |
5118 } | 5111 } |
5119 } | 5112 } |
5120 __ SmiTag(result_reg, SetCC); | 5113 __ SmiTag(result_reg, SetCC); |
5121 DeoptimizeIf(vs, instr->environment()); | 5114 DeoptimizeIf(vs, instr->environment()); |
5122 } | 5115 } |
5123 | 5116 |
5124 | 5117 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5225 } | 5218 } |
5226 Handle<Map> map = map_set->last(); | 5219 Handle<Map> map = map_set->last(); |
5227 DoCheckMapCommon(map_reg, map, instr->environment()); | 5220 DoCheckMapCommon(map_reg, map, instr->environment()); |
5228 __ bind(&success); | 5221 __ bind(&success); |
5229 } | 5222 } |
5230 | 5223 |
5231 | 5224 |
5232 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5225 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
5233 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5226 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped()); |
5234 Register result_reg = ToRegister(instr->result()); | 5227 Register result_reg = ToRegister(instr->result()); |
5235 DwVfpRegister temp_reg = ToDoubleRegister(instr->temp()); | 5228 __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0()); |
5236 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); | |
5237 } | 5229 } |
5238 | 5230 |
5239 | 5231 |
5240 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 5232 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
5241 Register unclamped_reg = ToRegister(instr->unclamped()); | 5233 Register unclamped_reg = ToRegister(instr->unclamped()); |
5242 Register result_reg = ToRegister(instr->result()); | 5234 Register result_reg = ToRegister(instr->result()); |
5243 __ ClampUint8(result_reg, unclamped_reg); | 5235 __ ClampUint8(result_reg, unclamped_reg); |
5244 } | 5236 } |
5245 | 5237 |
5246 | 5238 |
(...skipping 14 matching lines...) Expand all Loading... |
5261 | 5253 |
5262 // Check for undefined. Undefined is converted to zero for clamping | 5254 // Check for undefined. Undefined is converted to zero for clamping |
5263 // conversions. | 5255 // conversions. |
5264 __ cmp(input_reg, Operand(factory()->undefined_value())); | 5256 __ cmp(input_reg, Operand(factory()->undefined_value())); |
5265 DeoptimizeIf(ne, instr->environment()); | 5257 DeoptimizeIf(ne, instr->environment()); |
5266 __ mov(result_reg, Operand::Zero()); | 5258 __ mov(result_reg, Operand::Zero()); |
5267 __ jmp(&done); | 5259 __ jmp(&done); |
5268 | 5260 |
5269 // Heap number | 5261 // Heap number |
5270 __ bind(&heap_number); | 5262 __ bind(&heap_number); |
5271 __ vldr(double_scratch0(), FieldMemOperand(input_reg, | 5263 __ vldr(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
5272 HeapNumber::kValueOffset)); | 5264 __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0()); |
5273 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); | |
5274 __ jmp(&done); | 5265 __ jmp(&done); |
5275 | 5266 |
5276 // smi | 5267 // smi |
5277 __ bind(&is_smi); | 5268 __ bind(&is_smi); |
5278 __ ClampUint8(result_reg, result_reg); | 5269 __ ClampUint8(result_reg, result_reg); |
5279 | 5270 |
5280 __ bind(&done); | 5271 __ bind(&done); |
5281 } | 5272 } |
5282 | 5273 |
5283 | 5274 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5436 __ jmp(&allocated); | 5427 __ jmp(&allocated); |
5437 | 5428 |
5438 __ bind(&runtime_allocate); | 5429 __ bind(&runtime_allocate); |
5439 __ mov(r0, Operand(Smi::FromInt(size))); | 5430 __ mov(r0, Operand(Smi::FromInt(size))); |
5440 __ Push(r1, r0); | 5431 __ Push(r1, r0); |
5441 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 5432 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
5442 __ pop(r1); | 5433 __ pop(r1); |
5443 | 5434 |
5444 __ bind(&allocated); | 5435 __ bind(&allocated); |
5445 // Copy the content into the newly allocated memory. | 5436 // Copy the content into the newly allocated memory. |
5446 __ CopyFields(r0, r1, double_scratch0(), double_scratch0().low(), | 5437 __ CopyFields(r0, r1, double_scratch0(), size / kPointerSize); |
5447 size / kPointerSize); | |
5448 } | 5438 } |
5449 | 5439 |
5450 | 5440 |
5451 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 5441 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
5452 // Use the fast case closure allocation code that allocates in new | 5442 // Use the fast case closure allocation code that allocates in new |
5453 // space for nested functions that don't need literals cloning. | 5443 // space for nested functions that don't need literals cloning. |
5454 bool pretenure = instr->hydrogen()->pretenure(); | 5444 bool pretenure = instr->hydrogen()->pretenure(); |
5455 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5445 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
5456 FastNewClosureStub stub(instr->hydrogen()->language_mode(), | 5446 FastNewClosureStub stub(instr->hydrogen()->language_mode(), |
5457 instr->hydrogen()->is_generator()); | 5447 instr->hydrogen()->is_generator()); |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5807 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5797 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5808 __ ldr(result, FieldMemOperand(scratch, | 5798 __ ldr(result, FieldMemOperand(scratch, |
5809 FixedArray::kHeaderSize - kPointerSize)); | 5799 FixedArray::kHeaderSize - kPointerSize)); |
5810 __ bind(&done); | 5800 __ bind(&done); |
5811 } | 5801 } |
5812 | 5802 |
5813 | 5803 |
5814 #undef __ | 5804 #undef __ |
5815 | 5805 |
5816 } } // namespace v8::internal | 5806 } } // namespace v8::internal |
OLD | NEW |