OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 3585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3596 compiler->EmitEqualityRegRegCompare(left.reg(), | 3596 compiler->EmitEqualityRegRegCompare(left.reg(), |
3597 right.reg(), | 3597 right.reg(), |
3598 needs_number_check()); | 3598 needs_number_check()); |
3599 } | 3599 } |
3600 | 3600 |
3601 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 3601 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
3602 branch->EmitBranchOnCondition(compiler, true_condition); | 3602 branch->EmitBranchOnCondition(compiler, true_condition); |
3603 } | 3603 } |
3604 | 3604 |
3605 | 3605 |
| 3606 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) { |
| 3607 if (!val->BindsToConstant()) { |
| 3608 return false; |
| 3609 } |
| 3610 |
| 3611 const Object& bound_constant = val->BoundConstant(); |
| 3612 if (!bound_constant.IsSmi()) { |
| 3613 return false; |
| 3614 } |
| 3615 |
| 3616 *smi_value = Smi::Cast(bound_constant).Value(); |
| 3617 return true; |
| 3618 } |
| 3619 |
| 3620 |
| 3621 // Detect pattern when one value is zero and another is a power of 2. |
| 3622 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 3623 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 3624 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 3625 } |
| 3626 |
| 3627 |
| 3628 // Detect pattern when one value is increment of another. |
| 3629 static bool IsIncrementKind(intptr_t v1, intptr_t v2) { |
| 3630 return ((v1 == v2 + 1) || (v1 + 1 == v2)); |
| 3631 } |
| 3632 |
| 3633 |
| 3634 bool IfThenElseInstr::IsSupported() { |
| 3635 return true; |
| 3636 } |
| 3637 |
| 3638 |
| 3639 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, |
| 3640 Value* v1, |
| 3641 Value* v2) { |
| 3642 if (!(comparison->IsStrictCompare() && |
| 3643 !comparison->AsStrictCompare()->needs_number_check()) && |
| 3644 !(comparison->IsEqualityCompare() && |
| 3645 (comparison->AsEqualityCompare()->receiver_class_id() == kSmiCid))) { |
| 3646 return false; |
| 3647 } |
| 3648 |
| 3649 intptr_t v1_value, v2_value; |
| 3650 |
| 3651 if (!BindsToSmiConstant(v1, &v1_value) || |
| 3652 !BindsToSmiConstant(v2, &v2_value)) { |
| 3653 return false; |
| 3654 } |
| 3655 |
| 3656 if (IsPowerOfTwoKind(v1_value, v2_value) || |
| 3657 IsIncrementKind(v1_value, v2_value)) { |
| 3658 return true; |
| 3659 } |
| 3660 |
| 3661 return false; |
| 3662 } |
| 3663 |
| 3664 |
| 3665 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { |
| 3666 const intptr_t kNumInputs = 2; |
| 3667 const intptr_t kNumTemps = 0; |
| 3668 LocationSummary* locs = |
| 3669 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3670 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 3671 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 3672 // TODO(vegorov): support byte register constraints in the register allocator. |
| 3673 locs->set_out(Location::RegisterLocation(EDX)); |
| 3674 return locs; |
| 3675 } |
| 3676 |
| 3677 |
| 3678 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3679 ASSERT(locs()->out().reg() == EDX); |
| 3680 ASSERT(Token::IsEqualityOperator(kind())); |
| 3681 |
| 3682 Location left = locs()->in(0); |
| 3683 Location right = locs()->in(1); |
| 3684 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 3685 |
| 3686 // Clear upper part of the out register. We are going to use setcc on it |
| 3687 // which is a byte move. |
| 3688 __ xorl(EDX, EDX); |
| 3689 |
| 3690 // Compare left and right. For now only equality comparison is supported. |
| 3691 // TODO(vegorov): reuse code from the other comparison instructions instead of |
| 3692 // generating it inline here. |
| 3693 if (left.IsConstant()) { |
| 3694 __ CompareObject(right.reg(), left.constant()); |
| 3695 } else if (right.IsConstant()) { |
| 3696 __ CompareObject(left.reg(), right.constant()); |
| 3697 } else { |
| 3698 __ cmpl(left.reg(), right.reg()); |
| 3699 } |
| 3700 |
| 3701 Condition true_condition = |
| 3702 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL |
| 3703 : NOT_EQUAL; |
| 3704 |
| 3705 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 3706 |
| 3707 const intptr_t base = Utils::Minimum(if_true_, if_false_); |
| 3708 |
| 3709 if (if_true_ == base) { |
| 3710 // We need to have zero in EDX on true_condition. |
| 3711 true_condition = NegateCondition(true_condition); |
| 3712 } |
| 3713 |
| 3714 __ setcc(true_condition, DL); |
| 3715 |
| 3716 if (is_power_of_two_kind) { |
| 3717 const intptr_t shift = |
| 3718 Utils::ShiftForPowerOfTwo(Utils::Maximum(if_true_, if_false_)); |
| 3719 __ shll(EDX, Immediate(shift + kSmiTagSize)); |
| 3720 } else { |
| 3721 ASSERT(kSmiTagSize == 1); |
| 3722 __ leal(EDX, Address(EDX, TIMES_2, base << kSmiTagSize)); |
| 3723 } |
| 3724 } |
| 3725 |
| 3726 |
3606 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3727 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3607 // The arguments to the stub include the closure, as does the arguments | 3728 // The arguments to the stub include the closure, as does the arguments |
3608 // descriptor. | 3729 // descriptor. |
3609 Register temp_reg = locs()->temp(0).reg(); | 3730 Register temp_reg = locs()->temp(0).reg(); |
3610 int argument_count = ArgumentCount(); | 3731 int argument_count = ArgumentCount(); |
3611 const Array& arguments_descriptor = | 3732 const Array& arguments_descriptor = |
3612 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 3733 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
3613 argument_names())); | 3734 argument_names())); |
3614 __ LoadObject(temp_reg, arguments_descriptor); | 3735 __ LoadObject(temp_reg, arguments_descriptor); |
3615 compiler->GenerateDartCall(deopt_id(), | 3736 compiler->GenerateDartCall(deopt_id(), |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3719 PcDescriptors::kOther, | 3840 PcDescriptors::kOther, |
3720 locs()); | 3841 locs()); |
3721 __ Drop(2); // Discard type arguments and receiver. | 3842 __ Drop(2); // Discard type arguments and receiver. |
3722 } | 3843 } |
3723 | 3844 |
3724 } // namespace dart | 3845 } // namespace dart |
3725 | 3846 |
3726 #undef __ | 3847 #undef __ |
3727 | 3848 |
3728 #endif // defined TARGET_ARCH_IA32 | 3849 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |