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((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ) || | |
Florian Schneider
2013/04/10 13:59:50
ASSERT(Token::IsEqualityOperator(kind_))
Vyacheslav Egorov (Google)
2013/04/10 14:51:32
Done.
| |
3681 (kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)); | |
3682 | |
3683 Location left = locs()->in(0); | |
3684 Location right = locs()->in(1); | |
3685 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
3686 | |
3687 // Clear upper part of the out register. We are going to use setcc on it | |
3688 // which is a byte move. | |
3689 __ xorl(EDX, EDX); | |
3690 | |
3691 // Compare left and right. For now only equality comparison is supported. | |
3692 // TODO(vegorov): reuse code from the other comparison instructions instead of | |
3693 // generating it inline here. | |
3694 if (left.IsConstant()) { | |
3695 __ CompareObject(right.reg(), left.constant()); | |
3696 } else if (right.IsConstant()) { | |
3697 __ CompareObject(left.reg(), right.constant()); | |
3698 } else { | |
3699 __ cmpl(left.reg(), right.reg()); | |
3700 } | |
3701 | |
3702 Condition true_condition = | |
3703 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL | |
3704 : NOT_EQUAL; | |
3705 | |
3706 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | |
3707 | |
3708 const intptr_t base = Utils::Minimum(if_true_, if_false_); | |
3709 | |
3710 if (if_true_ == base) { | |
3711 // We need to have zero in EDX on true_condition. | |
3712 true_condition = NegateCondition(true_condition); | |
3713 } | |
3714 | |
3715 __ setcc(true_condition, DL); | |
3716 | |
3717 if (is_power_of_two_kind) { | |
3718 const intptr_t shift = | |
3719 Utils::ShiftForPowerOfTwo(Utils::Maximum(if_true_, if_false_)); | |
3720 __ shll(EDX, Immediate(shift + kSmiTagSize)); | |
3721 } else { | |
3722 ASSERT(kSmiTagSize == 1); | |
3723 __ leal(EDX, Address(EDX, TIMES_2, base << kSmiTagSize)); | |
3724 } | |
3725 } | |
3726 | |
3727 | |
3606 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3728 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3607 // The arguments to the stub include the closure, as does the arguments | 3729 // The arguments to the stub include the closure, as does the arguments |
3608 // descriptor. | 3730 // descriptor. |
3609 Register temp_reg = locs()->temp(0).reg(); | 3731 Register temp_reg = locs()->temp(0).reg(); |
3610 int argument_count = ArgumentCount(); | 3732 int argument_count = ArgumentCount(); |
3611 const Array& arguments_descriptor = | 3733 const Array& arguments_descriptor = |
3612 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 3734 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
3613 argument_names())); | 3735 argument_names())); |
3614 __ LoadObject(temp_reg, arguments_descriptor); | 3736 __ LoadObject(temp_reg, arguments_descriptor); |
3615 compiler->GenerateDartCall(deopt_id(), | 3737 compiler->GenerateDartCall(deopt_id(), |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3719 PcDescriptors::kOther, | 3841 PcDescriptors::kOther, |
3720 locs()); | 3842 locs()); |
3721 __ Drop(2); // Discard type arguments and receiver. | 3843 __ Drop(2); // Discard type arguments and receiver. |
3722 } | 3844 } |
3723 | 3845 |
3724 } // namespace dart | 3846 } // namespace dart |
3725 | 3847 |
3726 #undef __ | 3848 #undef __ |
3727 | 3849 |
3728 #endif // defined TARGET_ARCH_IA32 | 3850 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |