Chromium Code Reviews| 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 |