Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: runtime/vm/intermediate_language_x64.cc

Issue 564843002: Initial steps towards cleaning up integer arithmetic IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 2524 matching lines...) Expand 10 before | Expand all | Expand 10 after
2535 __ CompareImmediate(result, Immediate(-0x20000000000000LL), PP); 2535 __ CompareImmediate(result, Immediate(-0x20000000000000LL), PP);
2536 __ j(LESS, overflow); 2536 __ j(LESS, overflow);
2537 __ CompareImmediate(result, Immediate(0x20000000000000LL), PP); 2537 __ CompareImmediate(result, Immediate(0x20000000000000LL), PP);
2538 __ j(GREATER, overflow); 2538 __ j(GREATER, overflow);
2539 } 2539 }
2540 } 2540 }
2541 2541
2542 2542
2543 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, 2543 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
2544 BinarySmiOpInstr* shift_left) { 2544 BinarySmiOpInstr* shift_left) {
2545 const bool is_truncating = shift_left->IsTruncating();
2546 const LocationSummary& locs = *shift_left->locs(); 2545 const LocationSummary& locs = *shift_left->locs();
2547 Register left = locs.in(0).reg(); 2546 Register left = locs.in(0).reg();
2548 Register result = locs.out(0).reg(); 2547 Register result = locs.out(0).reg();
2549 ASSERT(left == result); 2548 ASSERT(left == result);
2550 Label* deopt = shift_left->CanDeoptimize() ? 2549 Label* deopt = shift_left->CanDeoptimize() ?
2551 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) 2550 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
2552 : NULL; 2551 : NULL;
2553 if (locs.in(1).IsConstant()) { 2552 if (locs.in(1).IsConstant()) {
2554 const Object& constant = locs.in(1).constant(); 2553 const Object& constant = locs.in(1).constant();
2555 ASSERT(constant.IsSmi()); 2554 ASSERT(constant.IsSmi());
2556 // shlq operation masks the count to 6 bits. 2555 // shlq operation masks the count to 6 bits.
2557 const intptr_t kCountLimit = 0x3F; 2556 const intptr_t kCountLimit = 0x3F;
2558 const intptr_t value = Smi::Cast(constant).Value(); 2557 const intptr_t value = Smi::Cast(constant).Value();
2559 if (value == 0) { 2558 ASSERT((0 < value) && (value < kCountLimit));
2560 // No code needed. 2559 if (shift_left->can_overflow()) {
2561 } else if ((value < 0) || (value >= kCountLimit)) { 2560 // Check for overflow.
2562 // This condition may not be known earlier in some cases because 2561 Register temp = locs.temp(0).reg();
2563 // of constant propagation, inlining, etc. 2562 __ movq(temp, left);
2564 if ((value >= kCountLimit) && is_truncating) {
2565 __ xorq(result, result);
2566 } else {
2567 // Result is Mint or exception.
2568 __ jmp(deopt);
2569 }
2570 } else {
2571 if (!is_truncating) {
2572 // Check for overflow.
2573 Register temp = locs.temp(0).reg();
2574 __ movq(temp, left);
2575 __ shlq(left, Immediate(value));
2576 __ sarq(left, Immediate(value));
2577 __ cmpq(left, temp);
2578 __ j(NOT_EQUAL, deopt); // Overflow.
2579 }
2580 // Shift for result now we know there is no overflow.
2581 __ shlq(left, Immediate(value)); 2563 __ shlq(left, Immediate(value));
2564 __ sarq(left, Immediate(value));
2565 __ cmpq(left, temp);
2566 __ j(NOT_EQUAL, deopt); // Overflow.
2582 } 2567 }
2568 // Shift for result now we know there is no overflow.
2569 __ shlq(left, Immediate(value));
2583 if (FLAG_throw_on_javascript_int_overflow) { 2570 if (FLAG_throw_on_javascript_int_overflow) {
2584 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); 2571 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
2585 } 2572 }
2586 return; 2573 return;
2587 } 2574 }
2588 2575
2589 // Right (locs.in(1)) is not constant. 2576 // Right (locs.in(1)) is not constant.
2590 Register right = locs.in(1).reg(); 2577 Register right = locs.in(1).reg();
2591 Range* right_range = shift_left->right()->definition()->range(); 2578 Range* right_range = shift_left->right()->definition()->range();
2592 if (shift_left->left()->BindsToConstant() && !is_truncating) { 2579 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
2593 // TODO(srdjan): Implement code below for is_truncating(). 2580 // TODO(srdjan): Implement code below for is_truncating().
2594 // If left is constant, we know the maximal allowed size for right. 2581 // If left is constant, we know the maximal allowed size for right.
2595 const Object& obj = shift_left->left()->BoundConstant(); 2582 const Object& obj = shift_left->left()->BoundConstant();
2596 if (obj.IsSmi()) { 2583 if (obj.IsSmi()) {
2597 const intptr_t left_int = Smi::Cast(obj).Value(); 2584 const intptr_t left_int = Smi::Cast(obj).Value();
2598 if (left_int == 0) { 2585 if (left_int == 0) {
2599 __ CompareImmediate(right, Immediate(0), PP); 2586 __ CompareImmediate(right, Immediate(0), PP);
2600 __ j(NEGATIVE, deopt); 2587 __ j(NEGATIVE, deopt);
2601 return; 2588 return;
2602 } 2589 }
(...skipping 10 matching lines...) Expand all
2613 } 2600 }
2614 if (FLAG_throw_on_javascript_int_overflow) { 2601 if (FLAG_throw_on_javascript_int_overflow) {
2615 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); 2602 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
2616 } 2603 }
2617 return; 2604 return;
2618 } 2605 }
2619 2606
2620 const bool right_needs_check = 2607 const bool right_needs_check =
2621 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); 2608 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1));
2622 ASSERT(right == RCX); // Count must be in RCX 2609 ASSERT(right == RCX); // Count must be in RCX
2623 if (is_truncating) { 2610 if (!shift_left->can_overflow()) {
2624 if (right_needs_check) { 2611 if (right_needs_check) {
2625 const bool right_may_be_negative = 2612 const bool right_may_be_negative =
2626 (right_range == NULL) || !right_range->IsPositive(); 2613 (right_range == NULL) || !right_range->IsPositive();
2627 if (right_may_be_negative) { 2614 if (right_may_be_negative) {
2628 ASSERT(shift_left->CanDeoptimize()); 2615 ASSERT(shift_left->CanDeoptimize());
2629 __ CompareImmediate(right, Immediate(0), PP); 2616 __ CompareImmediate(right, Immediate(0), PP);
2630 __ j(NEGATIVE, deopt); 2617 __ j(NEGATIVE, deopt);
2631 } 2618 }
2632 Label done, is_not_zero; 2619 Label done, is_not_zero;
2633 __ CompareImmediate(right, 2620 __ CompareImmediate(right,
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
2727 return summary; 2714 return summary;
2728 } else if (op_kind() == Token::kSHR) { 2715 } else if (op_kind() == Token::kSHR) {
2729 const intptr_t kNumTemps = 0; 2716 const intptr_t kNumTemps = 0;
2730 LocationSummary* summary = new(isolate) LocationSummary( 2717 LocationSummary* summary = new(isolate) LocationSummary(
2731 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2718 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
2732 summary->set_in(0, Location::RequiresRegister()); 2719 summary->set_in(0, Location::RequiresRegister());
2733 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); 2720 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
2734 summary->set_out(0, Location::SameAsFirstInput()); 2721 summary->set_out(0, Location::SameAsFirstInput());
2735 return summary; 2722 return summary;
2736 } else if (op_kind() == Token::kSHL) { 2723 } else if (op_kind() == Token::kSHL) {
2737 const intptr_t kNumTemps = !IsTruncating() ? 1 : 0; 2724 const intptr_t kNumTemps = can_overflow() ? 1 : 0;
2738 LocationSummary* summary = new(isolate) LocationSummary( 2725 LocationSummary* summary = new(isolate) LocationSummary(
2739 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2726 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
2740 summary->set_in(0, Location::RequiresRegister()); 2727 summary->set_in(0, Location::RequiresRegister());
2741 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); 2728 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
2742 if (!IsTruncating()) { 2729 if (can_overflow()) {
2743 summary->set_temp(0, Location::RequiresRegister()); 2730 summary->set_temp(0, Location::RequiresRegister());
2744 } 2731 }
2745 summary->set_out(0, Location::SameAsFirstInput()); 2732 summary->set_out(0, Location::SameAsFirstInput());
2746 return summary; 2733 return summary;
2747 } else { 2734 } else {
2748 const intptr_t kNumTemps = 0; 2735 const intptr_t kNumTemps = 0;
2749 LocationSummary* summary = new(isolate) LocationSummary( 2736 LocationSummary* summary = new(isolate) LocationSummary(
2750 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2737 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
2751 summary->set_in(0, Location::RequiresRegister()); 2738 summary->set_in(0, Location::RequiresRegister());
2752 ConstantInstr* constant = right()->definition()->AsConstant(); 2739 ConstantInstr* constant = right()->definition()->AsConstant();
(...skipping 20 matching lines...) Expand all
2773 if (CanDeoptimize()) { 2760 if (CanDeoptimize()) {
2774 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); 2761 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
2775 } 2762 }
2776 2763
2777 if (locs()->in(1).IsConstant()) { 2764 if (locs()->in(1).IsConstant()) {
2778 const Object& constant = locs()->in(1).constant(); 2765 const Object& constant = locs()->in(1).constant();
2779 ASSERT(constant.IsSmi()); 2766 ASSERT(constant.IsSmi());
2780 const int64_t imm = reinterpret_cast<int64_t>(constant.raw()); 2767 const int64_t imm = reinterpret_cast<int64_t>(constant.raw());
2781 switch (op_kind()) { 2768 switch (op_kind()) {
2782 case Token::kADD: { 2769 case Token::kADD: {
2783 if (imm != 0) { 2770 __ AddImmediate(left, Immediate(imm), PP);
2784 // Checking overflow without emitting an instruction would be wrong. 2771 if (deopt != NULL) __ j(OVERFLOW, deopt);
Cutch 2014/09/11 17:41:53 Please use curlies (here and elsewhere): if (deop
2785 __ AddImmediate(left, Immediate(imm), PP);
2786 if (deopt != NULL) __ j(OVERFLOW, deopt);
2787 }
2788 break; 2772 break;
2789 } 2773 }
2790 case Token::kSUB: { 2774 case Token::kSUB: {
2791 if (imm != 0) { 2775 __ SubImmediate(left, Immediate(imm), PP);
2792 // Checking overflow without emitting an instruction would be wrong. 2776 if (deopt != NULL) __ j(OVERFLOW, deopt);
2793 __ SubImmediate(left, Immediate(imm), PP);
2794 if (deopt != NULL) __ j(OVERFLOW, deopt);
2795 }
2796 break; 2777 break;
2797 } 2778 }
2798 case Token::kMUL: { 2779 case Token::kMUL: {
2799 // Keep left value tagged and untag right value. 2780 // Keep left value tagged and untag right value.
2800 const intptr_t value = Smi::Cast(constant).Value(); 2781 const intptr_t value = Smi::Cast(constant).Value();
2801 if (value == 2) { 2782 __ MulImmediate(left, Immediate(value), PP);
2802 __ shlq(left, Immediate(1));
2803 } else {
2804 __ MulImmediate(left, Immediate(value), PP);
2805 }
2806 if (deopt != NULL) __ j(OVERFLOW, deopt); 2783 if (deopt != NULL) __ j(OVERFLOW, deopt);
2807 break; 2784 break;
2808 } 2785 }
2809 case Token::kTRUNCDIV: { 2786 case Token::kTRUNCDIV: {
2810 const intptr_t value = Smi::Cast(constant).Value(); 2787 const intptr_t value = Smi::Cast(constant).Value();
2811 if (value == 1) {
2812 // Do nothing.
2813 break;
2814 } else if (value == -1) {
2815 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2816 // case we cannot negate the result.
2817 __ CompareImmediate(left, Immediate(0x8000000000000000), PP);
2818 __ j(EQUAL, deopt);
2819 __ negq(left);
2820 break;
2821 }
2822
2823 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); 2788 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value)));
2824 const intptr_t shift_count = 2789 const intptr_t shift_count =
2825 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; 2790 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
2826 ASSERT(kSmiTagSize == 1); 2791 ASSERT(kSmiTagSize == 1);
2827 Register temp = locs()->temp(0).reg(); 2792 Register temp = locs()->temp(0).reg();
2828 __ movq(temp, left); 2793 __ movq(temp, left);
2829 __ sarq(temp, Immediate(63)); 2794 __ sarq(temp, Immediate(63));
2830 ASSERT(shift_count > 1); // 1, -1 case handled above. 2795 ASSERT(shift_count > 1); // 1, -1 case handled above.
2831 __ shrq(temp, Immediate(64 - shift_count)); 2796 __ shrq(temp, Immediate(64 - shift_count));
2832 __ addq(left, temp); 2797 __ addq(left, temp);
(...skipping 17 matching lines...) Expand all
2850 } 2815 }
2851 case Token::kBIT_XOR: { 2816 case Token::kBIT_XOR: {
2852 // No overflow check. 2817 // No overflow check.
2853 __ XorImmediate(left, Immediate(imm), PP); 2818 __ XorImmediate(left, Immediate(imm), PP);
2854 break; 2819 break;
2855 } 2820 }
2856 2821
2857 case Token::kSHR: { 2822 case Token::kSHR: {
2858 // sarq operation masks the count to 6 bits. 2823 // sarq operation masks the count to 6 bits.
2859 const intptr_t kCountLimit = 0x3F; 2824 const intptr_t kCountLimit = 0x3F;
2860 intptr_t value = Smi::Cast(constant).Value(); 2825 const intptr_t value = Smi::Cast(constant).Value();
2861 2826 __ sarq(left, Immediate(
2862 if (value == 0) { 2827 Utils::Minimum(value + kSmiTagSize, kCountLimit)));
2863 // TODO(vegorov): should be handled outside.
2864 break;
2865 } else if (value < 0) {
2866 // TODO(vegorov): should be handled outside.
2867 __ jmp(deopt);
2868 break;
2869 }
2870
2871 value = value + kSmiTagSize;
2872 if (value >= kCountLimit) value = kCountLimit;
2873
2874 __ sarq(left, Immediate(value));
2875 __ SmiTag(left); 2828 __ SmiTag(left);
2876 break; 2829 break;
2877 } 2830 }
2878 2831
2879 default: 2832 default:
2880 UNREACHABLE(); 2833 UNREACHABLE();
2881 break; 2834 break;
2882 } 2835 }
2883 if (FLAG_throw_on_javascript_int_overflow) { 2836 if (FLAG_throw_on_javascript_int_overflow) {
2884 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); 2837 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
(...skipping 3093 matching lines...) Expand 10 before | Expand all | Expand 10 after
5978 __ movq(R10, Immediate(kInvalidObjectPointer)); 5931 __ movq(R10, Immediate(kInvalidObjectPointer));
5979 __ movq(RBX, Immediate(kInvalidObjectPointer)); 5932 __ movq(RBX, Immediate(kInvalidObjectPointer));
5980 #endif 5933 #endif
5981 } 5934 }
5982 5935
5983 } // namespace dart 5936 } // namespace dart
5984 5937
5985 #undef __ 5938 #undef __
5986 5939
5987 #endif // defined TARGET_ARCH_X64 5940 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698