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