| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 | 1055 |
| 1056 void LCodeGen::DeoptimizeIfZero(Register rt, LEnvironment* environment) { | 1056 void LCodeGen::DeoptimizeIfZero(Register rt, LEnvironment* environment) { |
| 1057 Label dont_deopt; | 1057 Label dont_deopt; |
| 1058 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL); | 1058 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL); |
| 1059 __ Cbnz(rt, &dont_deopt); | 1059 __ Cbnz(rt, &dont_deopt); |
| 1060 Deoptimize(environment, bailout_type); | 1060 Deoptimize(environment, bailout_type); |
| 1061 __ Bind(&dont_deopt); | 1061 __ Bind(&dont_deopt); |
| 1062 } | 1062 } |
| 1063 | 1063 |
| 1064 | 1064 |
| 1065 void LCodeGen::DeoptimizeIfNotZero(Register rt, LEnvironment* environment) { |
| 1066 Label dont_deopt; |
| 1067 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL); |
| 1068 __ Cbz(rt, &dont_deopt); |
| 1069 Deoptimize(environment, bailout_type); |
| 1070 __ Bind(&dont_deopt); |
| 1071 } |
| 1072 |
| 1073 |
| 1065 void LCodeGen::DeoptimizeIfNegative(Register rt, LEnvironment* environment) { | 1074 void LCodeGen::DeoptimizeIfNegative(Register rt, LEnvironment* environment) { |
| 1066 Label dont_deopt; | 1075 Label dont_deopt; |
| 1067 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL); | 1076 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL); |
| 1068 __ Tbz(rt, rt.Is64Bits() ? kXSignBit : kWSignBit, &dont_deopt); | 1077 __ Tbz(rt, rt.Is64Bits() ? kXSignBit : kWSignBit, &dont_deopt); |
| 1069 Deoptimize(environment, bailout_type); | 1078 Deoptimize(environment, bailout_type); |
| 1070 __ Bind(&dont_deopt); | 1079 __ Bind(&dont_deopt); |
| 1071 } | 1080 } |
| 1072 | 1081 |
| 1073 | 1082 |
| 1074 void LCodeGen::DeoptimizeIfSmi(Register rt, | 1083 void LCodeGen::DeoptimizeIfSmi(Register rt, |
| (...skipping 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2574 if (info()->IsStub() && (type == Deoptimizer::EAGER)) { | 2583 if (info()->IsStub() && (type == Deoptimizer::EAGER)) { |
| 2575 type = Deoptimizer::LAZY; | 2584 type = Deoptimizer::LAZY; |
| 2576 } | 2585 } |
| 2577 | 2586 |
| 2578 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); | 2587 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
| 2579 DeoptimizeHeader(instr->environment(), &type); | 2588 DeoptimizeHeader(instr->environment(), &type); |
| 2580 Deoptimize(instr->environment(), type); | 2589 Deoptimize(instr->environment(), type); |
| 2581 } | 2590 } |
| 2582 | 2591 |
| 2583 | 2592 |
| 2593 void LCodeGen::DoDivConstI(LDivConstI* instr) { |
| 2594 ASSERT(instr->hydrogen()->RightIsPowerOf2()); |
| 2595 |
| 2596 HDiv* hinstr = instr->hydrogen(); |
| 2597 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 2598 bool bailout_on_minus_zero = hinstr->CheckFlag(HValue::kBailoutOnMinusZero); |
| 2599 bool all_uses_truncating_to_int32 = |
| 2600 hinstr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32); |
| 2601 bool is_smi = hinstr->representation().IsSmi(); |
| 2602 |
| 2603 Register dividend = is_smi ? |
| 2604 ToRegister(instr->left()) : ToRegister32(instr->left()); |
| 2605 Register result = is_smi ? |
| 2606 ToRegister(instr->result()) : ToRegister32(instr->result()); |
| 2607 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); |
| 2608 int32_t power; |
| 2609 int64_t power_mask; |
| 2610 Label done; |
| 2611 |
| 2612 ASSERT(divisor != 0); |
| 2613 if (divisor > 0) { |
| 2614 power = WhichPowerOf2(divisor); |
| 2615 power_mask = divisor - 1; |
| 2616 } else { |
| 2617 // Check for (0 / -x) as that will produce negative zero. |
| 2618 if (bailout_on_minus_zero) { |
| 2619 if (all_uses_truncating_to_int32) { |
| 2620 // If all uses truncate, and the dividend is zero, the truncated |
| 2621 // result is zero. |
| 2622 __ Mov(result, 0); |
| 2623 __ Cbz(dividend, &done); |
| 2624 } else { |
| 2625 DeoptimizeIfZero(dividend, instr->environment()); |
| 2626 } |
| 2627 } |
| 2628 // Check for (kMinInt / -1). |
| 2629 if ((divisor == -1) && can_overflow && !all_uses_truncating_to_int32) { |
| 2630 // Check for kMinInt (or the smi equivalent) by subtracting one and |
| 2631 // checking for overflow. |
| 2632 __ Cmp(dividend, 1); |
| 2633 DeoptimizeIf(vs, instr->environment()); |
| 2634 } |
| 2635 power = WhichPowerOf2(-divisor); |
| 2636 power_mask = -divisor - 1; |
| 2637 } |
| 2638 |
| 2639 if (power_mask != 0) { |
| 2640 if (all_uses_truncating_to_int32) { |
| 2641 __ Cmp(dividend, 0); |
| 2642 __ Cneg(result, dividend, lt); |
| 2643 __ Lsr(result, result, power); |
| 2644 if (divisor > 0) __ Cneg(result, result, lt); |
| 2645 if (divisor < 0) __ Cneg(result, result, gt); |
| 2646 if (is_smi) { |
| 2647 // Clear the bits shifted into the smi tag. |
| 2648 __ Bic(result, result, kSmiShiftMask); |
| 2649 } |
| 2650 return; |
| 2651 } else { |
| 2652 if (is_smi) power_mask <<= kSmiShift; |
| 2653 |
| 2654 // Deoptimize if remainder is not 0. If the least-significant |
| 2655 // power bits aren't 0, it's not a multiple of 2^power, and |
| 2656 // therefore, there will be a remainder. |
| 2657 __ Tst(dividend, power_mask); |
| 2658 DeoptimizeIf(ne, instr->environment()); |
| 2659 __ Asr(result, dividend, power); |
| 2660 if (divisor < 0) __ Neg(result, result); |
| 2661 |
| 2662 // If there's no remainder, there will be no set bits in the smi tag area |
| 2663 // after shifting, so the result is a valid smi. |
| 2664 } |
| 2665 } else { |
| 2666 ASSERT((divisor == 1) || (divisor == -1)); |
| 2667 if (divisor < 0) { |
| 2668 __ Neg(result, dividend); |
| 2669 } else { |
| 2670 __ Mov(result, dividend); |
| 2671 } |
| 2672 } |
| 2673 __ Bind(&done); |
| 2674 } |
| 2675 |
| 2676 |
| 2584 void LCodeGen::DoDivI(LDivI* instr) { | 2677 void LCodeGen::DoDivI(LDivI* instr) { |
| 2585 Register dividend = ToRegister32(instr->left()); | 2678 HDiv* hinstr = instr->hydrogen(); |
| 2679 bool can_overflow = hinstr->CheckFlag(HValue::kCanOverflow); |
| 2680 bool bailout_on_minus_zero = hinstr->CheckFlag(HValue::kBailoutOnMinusZero); |
| 2681 bool can_be_div_by_zero = hinstr->CheckFlag(HValue::kCanBeDivByZero); |
| 2682 bool all_uses_truncating_to_int32 = |
| 2683 hinstr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32); |
| 2684 bool is_smi = hinstr->representation().IsSmi(); |
| 2685 |
| 2586 Register result = ToRegister32(instr->result()); | 2686 Register result = ToRegister32(instr->result()); |
| 2687 Register dividend, divisor; |
| 2587 | 2688 |
| 2588 bool has_power_of_2_divisor = instr->hydrogen()->RightIsPowerOf2(); | 2689 if (is_smi) { |
| 2589 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 2690 dividend = ToRegister32(instr->temp2()); |
| 2590 bool bailout_on_minus_zero = | 2691 divisor = ToRegister32(instr->temp3()); |
| 2591 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 2692 __ SmiUntag(dividend, ToRegister(instr->left())); |
| 2592 bool can_be_div_by_zero = | 2693 __ SmiUntag(divisor, ToRegister(instr->right())); |
| 2593 instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero); | 2694 } else { |
| 2594 bool all_uses_truncating_to_int32 = | 2695 // Additional temps are not required for the int32 case. |
| 2595 instr->hydrogen()->CheckFlag(HInstruction::kAllUsesTruncatingToInt32); | 2696 ASSERT((instr->temp2() == NULL) && (instr->temp3() == NULL)); |
| 2697 dividend = ToRegister32(instr->left()); |
| 2698 divisor = ToRegister32(instr->right()); |
| 2699 } |
| 2596 | 2700 |
| 2597 if (has_power_of_2_divisor) { | 2701 // Issue the division first, and then check for any deopt cases whilst the |
| 2598 ASSERT(instr->temp() == NULL); | 2702 // result is computed. |
| 2599 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); | 2703 __ Sdiv(result, dividend, divisor); |
| 2600 int32_t power; | |
| 2601 int32_t power_mask; | |
| 2602 Label deopt, done; | |
| 2603 | 2704 |
| 2604 ASSERT(divisor != 0); | 2705 if (all_uses_truncating_to_int32) { |
| 2605 if (divisor > 0) { | 2706 // Equivalent to integer division, so no special handling required. |
| 2606 power = WhichPowerOf2(divisor); | 2707 // Sdiv gives the correct answer for truncated infinite or minus zero |
| 2607 power_mask = divisor - 1; | 2708 // results. |
| 2608 } else { | 2709 ASSERT(instr->temp1() == NULL); |
| 2609 // Check for (0 / -x) as that will produce negative zero. | 2710 } else { |
| 2610 if (bailout_on_minus_zero) { | 2711 // Check for x / 0. |
| 2611 if (all_uses_truncating_to_int32) { | 2712 if (can_be_div_by_zero) { |
| 2612 // If all uses truncate, and the dividend is zero, the truncated | 2713 // A non-truncated zero divisor has a floating point result, so deopt. |
| 2613 // result is zero. | 2714 DeoptimizeIfZero(divisor, instr->environment()); |
| 2614 __ Mov(result, 0); | |
| 2615 __ Cbz(dividend, &done); | |
| 2616 } else { | |
| 2617 __ Cbz(dividend, &deopt); | |
| 2618 } | |
| 2619 } | |
| 2620 // Check for (kMinInt / -1). | |
| 2621 if ((divisor == -1) && can_overflow && !all_uses_truncating_to_int32) { | |
| 2622 // Check for kMinInt by subtracting one and checking for overflow. | |
| 2623 __ Cmp(dividend, 1); | |
| 2624 __ B(vs, &deopt); | |
| 2625 } | |
| 2626 power = WhichPowerOf2(-divisor); | |
| 2627 power_mask = -divisor - 1; | |
| 2628 } | 2715 } |
| 2629 | 2716 |
| 2630 if (power_mask != 0) { | 2717 // Check for (0 / -x) as that will produce negative zero. |
| 2631 if (all_uses_truncating_to_int32) { | 2718 if (bailout_on_minus_zero) { |
| 2632 __ Cmp(dividend, 0); | 2719 __ Cmp(divisor, 0); |
| 2633 __ Cneg(result, dividend, lt); | 2720 |
| 2634 __ Asr(result, result, power); | 2721 // If the divisor < 0 (mi), compare the dividend, and deopt if it is |
| 2635 if (divisor > 0) __ Cneg(result, result, lt); | 2722 // zero, ie. zero dividend with negative divisor deopts. |
| 2636 if (divisor < 0) __ Cneg(result, result, gt); | 2723 // If the divisor >= 0 (pl, the opposite of mi) set the flags to |
| 2637 return; // Don't fall through to negation below. | 2724 // condition ne, so we don't deopt, ie. positive divisor doesn't deopt. |
| 2638 } else { | 2725 __ Ccmp(dividend, 0, NoFlag, mi); |
| 2639 // Deoptimize if remainder is not 0. If the least-significant | 2726 DeoptimizeIf(eq, instr->environment()); |
| 2640 // power bits aren't 0, it's not a multiple of 2^power, and | |
| 2641 // therefore, there will be a remainder. | |
| 2642 __ TestAndBranchIfAnySet(dividend, power_mask, &deopt); | |
| 2643 __ Asr(result, dividend, power); | |
| 2644 if (divisor < 0) __ Neg(result, result); | |
| 2645 } | |
| 2646 } else { | |
| 2647 ASSERT((divisor == 1) || (divisor == -1)); | |
| 2648 if (divisor < 0) { | |
| 2649 __ Neg(result, dividend); | |
| 2650 } else { | |
| 2651 __ Mov(result, dividend); | |
| 2652 } | |
| 2653 } | 2727 } |
| 2654 __ B(&done); | |
| 2655 __ Bind(&deopt); | |
| 2656 Deoptimize(instr->environment()); | |
| 2657 __ Bind(&done); | |
| 2658 } else { | |
| 2659 Register divisor = ToRegister32(instr->right()); | |
| 2660 | 2728 |
| 2661 // Issue the division first, and then check for any deopt cases whilst the | 2729 // Check for (kMinInt / -1). |
| 2662 // result is computed. | 2730 if (can_overflow) { |
| 2663 __ Sdiv(result, dividend, divisor); | 2731 // Test dividend for kMinInt by subtracting one (cmp) and checking for |
| 2732 // overflow. |
| 2733 __ Cmp(dividend, 1); |
| 2734 // If overflow is set, ie. dividend = kMinInt, compare the divisor with |
| 2735 // -1. If overflow is clear, set the flags for condition ne, as the |
| 2736 // dividend isn't -1, and thus we shouldn't deopt. |
| 2737 __ Ccmp(divisor, -1, NoFlag, vs); |
| 2738 DeoptimizeIf(eq, instr->environment()); |
| 2739 } |
| 2664 | 2740 |
| 2665 if (!all_uses_truncating_to_int32) { | 2741 // Compute remainder and deopt if it's not zero. |
| 2666 Label deopt; | 2742 Register remainder = ToRegister32(instr->temp1()); |
| 2667 // Check for x / 0. | 2743 __ Msub(remainder, result, divisor, dividend); |
| 2668 if (can_be_div_by_zero) { | 2744 DeoptimizeIfNotZero(remainder, instr->environment()); |
| 2669 __ Cbz(divisor, &deopt); | 2745 } |
| 2670 } | |
| 2671 | 2746 |
| 2672 // Check for (0 / -x) as that will produce negative zero. | 2747 if (is_smi) { |
| 2673 if (bailout_on_minus_zero) { | 2748 __ SmiTag(result.X()); |
| 2674 __ Cmp(divisor, 0); | |
| 2675 | |
| 2676 // If the divisor < 0 (mi), compare the dividend, and deopt if it is | |
| 2677 // zero, ie. zero dividend with negative divisor deopts. | |
| 2678 // If the divisor >= 0 (pl, the opposite of mi) set the flags to | |
| 2679 // condition ne, so we don't deopt, ie. positive divisor doesn't deopt. | |
| 2680 __ Ccmp(dividend, 0, NoFlag, mi); | |
| 2681 __ B(eq, &deopt); | |
| 2682 } | |
| 2683 | |
| 2684 // Check for (kMinInt / -1). | |
| 2685 if (can_overflow) { | |
| 2686 // Test dividend for kMinInt by subtracting one (cmp) and checking for | |
| 2687 // overflow. | |
| 2688 __ Cmp(dividend, 1); | |
| 2689 // If overflow is set, ie. dividend = kMinInt, compare the divisor with | |
| 2690 // -1. If overflow is clear, set the flags for condition ne, as the | |
| 2691 // dividend isn't -1, and thus we shouldn't deopt. | |
| 2692 __ Ccmp(divisor, -1, NoFlag, vs); | |
| 2693 __ B(eq, &deopt); | |
| 2694 } | |
| 2695 | |
| 2696 // Compute remainder and deopt if it's not zero. | |
| 2697 Register remainder = ToRegister32(instr->temp()); | |
| 2698 __ Msub(remainder, result, divisor, dividend); | |
| 2699 __ Cbnz(remainder, &deopt); | |
| 2700 | |
| 2701 Label div_ok; | |
| 2702 __ B(&div_ok); | |
| 2703 __ Bind(&deopt); | |
| 2704 Deoptimize(instr->environment()); | |
| 2705 __ Bind(&div_ok); | |
| 2706 } else { | |
| 2707 ASSERT(instr->temp() == NULL); | |
| 2708 } | |
| 2709 } | 2749 } |
| 2710 } | 2750 } |
| 2711 | 2751 |
| 2712 | 2752 |
| 2713 void LCodeGen::DoDoubleToIntOrSmi(LDoubleToIntOrSmi* instr) { | 2753 void LCodeGen::DoDoubleToIntOrSmi(LDoubleToIntOrSmi* instr) { |
| 2714 DoubleRegister input = ToDoubleRegister(instr->value()); | 2754 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 2715 Register result = ToRegister32(instr->result()); | 2755 Register result = ToRegister32(instr->result()); |
| 2716 Label done, deopt; | 2756 Label done, deopt; |
| 2717 | 2757 |
| 2718 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2758 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| (...skipping 2998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5717 __ Bind(&out_of_object); | 5757 __ Bind(&out_of_object); |
| 5718 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5758 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 5719 // Index is equal to negated out of object property index plus 1. | 5759 // Index is equal to negated out of object property index plus 1. |
| 5720 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5760 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 5721 __ Ldr(result, FieldMemOperand(result, | 5761 __ Ldr(result, FieldMemOperand(result, |
| 5722 FixedArray::kHeaderSize - kPointerSize)); | 5762 FixedArray::kHeaderSize - kPointerSize)); |
| 5723 __ Bind(&done); | 5763 __ Bind(&done); |
| 5724 } | 5764 } |
| 5725 | 5765 |
| 5726 } } // namespace v8::internal | 5766 } } // namespace v8::internal |
| OLD | NEW |