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_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/compiler.h" | 10 #include "vm/compiler.h" |
11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
12 #include "vm/flow_graph.h" | 12 #include "vm/flow_graph.h" |
13 #include "vm/flow_graph_compiler.h" | 13 #include "vm/flow_graph_compiler.h" |
14 #include "vm/flow_graph_range_analysis.h" | 14 #include "vm/flow_graph_range_analysis.h" |
15 #include "vm/locations.h" | 15 #include "vm/locations.h" |
16 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
17 #include "vm/parser.h" | 17 #include "vm/parser.h" |
18 #include "vm/stack_frame.h" | 18 #include "vm/stack_frame.h" |
19 #include "vm/stub_code.h" | 19 #include "vm/stub_code.h" |
20 #include "vm/symbols.h" | 20 #include "vm/symbols.h" |
21 | 21 |
22 #define __ compiler->assembler()-> | 22 #define __ compiler->assembler()-> |
23 | 23 |
24 namespace dart { | 24 namespace dart { |
25 | 25 |
26 DECLARE_FLAG(bool, allow_absolute_addresses); | 26 DECLARE_FLAG(bool, allow_absolute_addresses); |
27 DECLARE_FLAG(bool, emit_edge_counters); | 27 DECLARE_FLAG(bool, emit_edge_counters); |
28 DECLARE_FLAG(int, optimization_counter_threshold); | 28 DECLARE_FLAG(int, optimization_counter_threshold); |
29 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | |
30 DECLARE_FLAG(bool, use_osr); | 29 DECLARE_FLAG(bool, use_osr); |
31 DECLARE_FLAG(bool, precompilation); | 30 DECLARE_FLAG(bool, precompilation); |
32 | 31 |
33 // Generic summary for call instructions that have all arguments pushed | 32 // Generic summary for call instructions that have all arguments pushed |
34 // on the stack and return the result in a fixed register RAX. | 33 // on the stack and return the result in a fixed register RAX. |
35 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 34 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
36 LocationSummary* result = new(zone) LocationSummary( | 35 LocationSummary* result = new(zone) LocationSummary( |
37 zone, 0, 0, LocationSummary::kCall); | 36 zone, 0, 0, LocationSummary::kCall); |
38 result->set_out(0, Location::RegisterLocation(RAX)); | 37 result->set_out(0, Location::RegisterLocation(RAX)); |
39 return result; | 38 return result; |
(...skipping 2640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2680 Immediate(threshold)); | 2679 Immediate(threshold)); |
2681 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); | 2680 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); |
2682 } | 2681 } |
2683 if (compiler->ForceSlowPathForStackOverflow()) { | 2682 if (compiler->ForceSlowPathForStackOverflow()) { |
2684 __ jmp(slow_path->entry_label()); | 2683 __ jmp(slow_path->entry_label()); |
2685 } | 2684 } |
2686 __ Bind(slow_path->exit_label()); | 2685 __ Bind(slow_path->exit_label()); |
2687 } | 2686 } |
2688 | 2687 |
2689 | 2688 |
2690 static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler, | |
2691 Range* range, | |
2692 Label* overflow, | |
2693 Register result) { | |
2694 if (!RangeUtils::IsWithin(range, -0x20000000000000LL, 0x20000000000000LL)) { | |
2695 ASSERT(overflow != NULL); | |
2696 // TODO(zra): This can be tightened to one compare/branch using: | |
2697 // overflow = (result + 2^52) > 2^53 with an unsigned comparison. | |
2698 __ CompareImmediate(result, Immediate(-0x20000000000000LL)); | |
2699 __ j(LESS, overflow); | |
2700 __ CompareImmediate(result, Immediate(0x20000000000000LL)); | |
2701 __ j(GREATER, overflow); | |
2702 } | |
2703 } | |
2704 | |
2705 | |
2706 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2689 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
2707 BinarySmiOpInstr* shift_left) { | 2690 BinarySmiOpInstr* shift_left) { |
2708 const LocationSummary& locs = *shift_left->locs(); | 2691 const LocationSummary& locs = *shift_left->locs(); |
2709 Register left = locs.in(0).reg(); | 2692 Register left = locs.in(0).reg(); |
2710 Register result = locs.out(0).reg(); | 2693 Register result = locs.out(0).reg(); |
2711 ASSERT(left == result); | 2694 ASSERT(left == result); |
2712 Label* deopt = shift_left->CanDeoptimize() ? | 2695 Label* deopt = shift_left->CanDeoptimize() ? |
2713 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 2696 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) |
2714 : NULL; | 2697 : NULL; |
2715 if (locs.in(1).IsConstant()) { | 2698 if (locs.in(1).IsConstant()) { |
2716 const Object& constant = locs.in(1).constant(); | 2699 const Object& constant = locs.in(1).constant(); |
2717 ASSERT(constant.IsSmi()); | 2700 ASSERT(constant.IsSmi()); |
2718 // shlq operation masks the count to 6 bits. | 2701 // shlq operation masks the count to 6 bits. |
2719 const intptr_t kCountLimit = 0x3F; | 2702 const intptr_t kCountLimit = 0x3F; |
2720 const intptr_t value = Smi::Cast(constant).Value(); | 2703 const intptr_t value = Smi::Cast(constant).Value(); |
2721 ASSERT((0 < value) && (value < kCountLimit)); | 2704 ASSERT((0 < value) && (value < kCountLimit)); |
2722 if (shift_left->can_overflow()) { | 2705 if (shift_left->can_overflow()) { |
2723 // Check for overflow. | 2706 // Check for overflow. |
2724 Register temp = locs.temp(0).reg(); | 2707 Register temp = locs.temp(0).reg(); |
2725 __ movq(temp, left); | 2708 __ movq(temp, left); |
2726 __ shlq(left, Immediate(value)); | 2709 __ shlq(left, Immediate(value)); |
2727 __ sarq(left, Immediate(value)); | 2710 __ sarq(left, Immediate(value)); |
2728 __ cmpq(left, temp); | 2711 __ cmpq(left, temp); |
2729 __ j(NOT_EQUAL, deopt); // Overflow. | 2712 __ j(NOT_EQUAL, deopt); // Overflow. |
2730 } | 2713 } |
2731 // Shift for result now we know there is no overflow. | 2714 // Shift for result now we know there is no overflow. |
2732 __ shlq(left, Immediate(value)); | 2715 __ shlq(left, Immediate(value)); |
2733 if (FLAG_throw_on_javascript_int_overflow) { | |
2734 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); | |
2735 } | |
2736 return; | 2716 return; |
2737 } | 2717 } |
2738 | 2718 |
2739 // Right (locs.in(1)) is not constant. | 2719 // Right (locs.in(1)) is not constant. |
2740 Register right = locs.in(1).reg(); | 2720 Register right = locs.in(1).reg(); |
2741 Range* right_range = shift_left->right()->definition()->range(); | 2721 Range* right_range = shift_left->right()->definition()->range(); |
2742 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { | 2722 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { |
2743 // TODO(srdjan): Implement code below for is_truncating(). | 2723 // TODO(srdjan): Implement code below for is_truncating(). |
2744 // If left is constant, we know the maximal allowed size for right. | 2724 // If left is constant, we know the maximal allowed size for right. |
2745 const Object& obj = shift_left->left()->BoundConstant(); | 2725 const Object& obj = shift_left->left()->BoundConstant(); |
2746 if (obj.IsSmi()) { | 2726 if (obj.IsSmi()) { |
2747 const intptr_t left_int = Smi::Cast(obj).Value(); | 2727 const intptr_t left_int = Smi::Cast(obj).Value(); |
2748 if (left_int == 0) { | 2728 if (left_int == 0) { |
2749 __ CompareImmediate(right, Immediate(0)); | 2729 __ CompareImmediate(right, Immediate(0)); |
2750 __ j(NEGATIVE, deopt); | 2730 __ j(NEGATIVE, deopt); |
2751 return; | 2731 return; |
2752 } | 2732 } |
2753 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2733 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
2754 const bool right_needs_check = | 2734 const bool right_needs_check = |
2755 !RangeUtils::IsWithin(right_range, 0, max_right - 1); | 2735 !RangeUtils::IsWithin(right_range, 0, max_right - 1); |
2756 if (right_needs_check) { | 2736 if (right_needs_check) { |
2757 __ CompareImmediate(right, | 2737 __ CompareImmediate(right, |
2758 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); | 2738 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); |
2759 __ j(ABOVE_EQUAL, deopt); | 2739 __ j(ABOVE_EQUAL, deopt); |
2760 } | 2740 } |
2761 __ SmiUntag(right); | 2741 __ SmiUntag(right); |
2762 __ shlq(left, right); | 2742 __ shlq(left, right); |
2763 } | 2743 } |
2764 if (FLAG_throw_on_javascript_int_overflow) { | |
2765 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); | |
2766 } | |
2767 return; | 2744 return; |
2768 } | 2745 } |
2769 | 2746 |
2770 const bool right_needs_check = | 2747 const bool right_needs_check = |
2771 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 2748 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |
2772 ASSERT(right == RCX); // Count must be in RCX | 2749 ASSERT(right == RCX); // Count must be in RCX |
2773 if (!shift_left->can_overflow()) { | 2750 if (!shift_left->can_overflow()) { |
2774 if (right_needs_check) { | 2751 if (right_needs_check) { |
2775 const bool right_may_be_negative = | 2752 const bool right_may_be_negative = |
2776 (right_range == NULL) || !right_range->IsPositive(); | 2753 (right_range == NULL) || !right_range->IsPositive(); |
(...skipping 29 matching lines...) Expand all Loading... |
2806 __ movq(temp, left); | 2783 __ movq(temp, left); |
2807 __ SmiUntag(right); | 2784 __ SmiUntag(right); |
2808 // Overflow test (preserve temp and right); | 2785 // Overflow test (preserve temp and right); |
2809 __ shlq(left, right); | 2786 __ shlq(left, right); |
2810 __ sarq(left, right); | 2787 __ sarq(left, right); |
2811 __ cmpq(left, temp); | 2788 __ cmpq(left, temp); |
2812 __ j(NOT_EQUAL, deopt); // Overflow. | 2789 __ j(NOT_EQUAL, deopt); // Overflow. |
2813 // Shift for result now we know there is no overflow. | 2790 // Shift for result now we know there is no overflow. |
2814 __ shlq(left, right); | 2791 __ shlq(left, right); |
2815 } | 2792 } |
2816 if (FLAG_throw_on_javascript_int_overflow) { | |
2817 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); | |
2818 } | |
2819 } | 2793 } |
2820 | 2794 |
2821 | 2795 |
2822 static bool CanBeImmediate(const Object& constant) { | 2796 static bool CanBeImmediate(const Object& constant) { |
2823 return constant.IsSmi() && | 2797 return constant.IsSmi() && |
2824 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); | 2798 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); |
2825 } | 2799 } |
2826 | 2800 |
2827 | 2801 |
2828 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 2802 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2989 __ sarq(left, Immediate( | 2963 __ sarq(left, Immediate( |
2990 Utils::Minimum(value + kSmiTagSize, kCountLimit))); | 2964 Utils::Minimum(value + kSmiTagSize, kCountLimit))); |
2991 __ SmiTag(left); | 2965 __ SmiTag(left); |
2992 break; | 2966 break; |
2993 } | 2967 } |
2994 | 2968 |
2995 default: | 2969 default: |
2996 UNREACHABLE(); | 2970 UNREACHABLE(); |
2997 break; | 2971 break; |
2998 } | 2972 } |
2999 if (FLAG_throw_on_javascript_int_overflow) { | |
3000 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); | |
3001 } | |
3002 return; | 2973 return; |
3003 } // locs()->in(1).IsConstant(). | 2974 } // locs()->in(1).IsConstant(). |
3004 | 2975 |
3005 | 2976 |
3006 if (locs()->in(1).IsStackSlot()) { | 2977 if (locs()->in(1).IsStackSlot()) { |
3007 const Address& right = locs()->in(1).ToStackSlotAddress(); | 2978 const Address& right = locs()->in(1).ToStackSlotAddress(); |
3008 switch (op_kind()) { | 2979 switch (op_kind()) { |
3009 case Token::kADD: { | 2980 case Token::kADD: { |
3010 __ addq(left, right); | 2981 __ addq(left, right); |
3011 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2982 if (deopt != NULL) __ j(OVERFLOW, deopt); |
(...skipping 22 matching lines...) Expand all Loading... |
3034 } | 3005 } |
3035 case Token::kBIT_XOR: { | 3006 case Token::kBIT_XOR: { |
3036 // No overflow check. | 3007 // No overflow check. |
3037 __ xorq(left, right); | 3008 __ xorq(left, right); |
3038 break; | 3009 break; |
3039 } | 3010 } |
3040 default: | 3011 default: |
3041 UNREACHABLE(); | 3012 UNREACHABLE(); |
3042 break; | 3013 break; |
3043 } | 3014 } |
3044 if (FLAG_throw_on_javascript_int_overflow) { | |
3045 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); | |
3046 } | |
3047 return; | 3015 return; |
3048 } // locs()->in(1).IsStackSlot(). | 3016 } // locs()->in(1).IsStackSlot(). |
3049 | 3017 |
3050 // if locs()->in(1).IsRegister. | 3018 // if locs()->in(1).IsRegister. |
3051 Register right = locs()->in(1).reg(); | 3019 Register right = locs()->in(1).reg(); |
3052 Range* right_range = this->right()->definition()->range(); | 3020 Range* right_range = this->right()->definition()->range(); |
3053 switch (op_kind()) { | 3021 switch (op_kind()) { |
3054 case Token::kADD: { | 3022 case Token::kADD: { |
3055 __ addq(left, right); | 3023 __ addq(left, right); |
3056 if (deopt != NULL) __ j(OVERFLOW, deopt); | 3024 if (deopt != NULL) __ j(OVERFLOW, deopt); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3233 case Token::kAND: { | 3201 case Token::kAND: { |
3234 // Flow graph builder has dissected this operation to guarantee correct | 3202 // Flow graph builder has dissected this operation to guarantee correct |
3235 // behavior (short-circuit evaluation). | 3203 // behavior (short-circuit evaluation). |
3236 UNREACHABLE(); | 3204 UNREACHABLE(); |
3237 break; | 3205 break; |
3238 } | 3206 } |
3239 default: | 3207 default: |
3240 UNREACHABLE(); | 3208 UNREACHABLE(); |
3241 break; | 3209 break; |
3242 } | 3210 } |
3243 if (FLAG_throw_on_javascript_int_overflow) { | |
3244 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); | |
3245 } | |
3246 } | 3211 } |
3247 | 3212 |
3248 | 3213 |
3249 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3214 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
3250 bool opt) const { | 3215 bool opt) const { |
3251 intptr_t left_cid = left()->Type()->ToCid(); | 3216 intptr_t left_cid = left()->Type()->ToCid(); |
3252 intptr_t right_cid = right()->Type()->ToCid(); | 3217 intptr_t right_cid = right()->Type()->ToCid(); |
3253 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3218 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
3254 const intptr_t kNumInputs = 2; | 3219 const intptr_t kNumInputs = 2; |
3255 const bool need_temp = (left()->definition() != right()->definition()) | 3220 const bool need_temp = (left()->definition() != right()->definition()) |
(...skipping 1469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4725 | 4690 |
4726 | 4691 |
4727 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4692 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4728 Register value = locs()->in(0).reg(); | 4693 Register value = locs()->in(0).reg(); |
4729 ASSERT(value == locs()->out(0).reg()); | 4694 ASSERT(value == locs()->out(0).reg()); |
4730 switch (op_kind()) { | 4695 switch (op_kind()) { |
4731 case Token::kNEGATE: { | 4696 case Token::kNEGATE: { |
4732 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 4697 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
4733 __ negq(value); | 4698 __ negq(value); |
4734 __ j(OVERFLOW, deopt); | 4699 __ j(OVERFLOW, deopt); |
4735 if (FLAG_throw_on_javascript_int_overflow) { | |
4736 EmitJavascriptOverflowCheck(compiler, range(), deopt, value); | |
4737 } | |
4738 break; | 4700 break; |
4739 } | 4701 } |
4740 case Token::kBIT_NOT: | 4702 case Token::kBIT_NOT: |
4741 __ notq(value); | 4703 __ notq(value); |
4742 // Remove inverted smi-tag. | 4704 // Remove inverted smi-tag. |
4743 __ AndImmediate(value, Immediate(~kSmiTagMask)); | 4705 __ AndImmediate(value, Immediate(~kSmiTagMask)); |
4744 break; | 4706 break; |
4745 default: | 4707 default: |
4746 UNREACHABLE(); | 4708 UNREACHABLE(); |
4747 } | 4709 } |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4931 ASSERT(result != temp); | 4893 ASSERT(result != temp); |
4932 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); | 4894 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); |
4933 __ cvttsd2siq(result, value_double); | 4895 __ cvttsd2siq(result, value_double); |
4934 // Overflow is signalled with minint. | 4896 // Overflow is signalled with minint. |
4935 Label do_call, done; | 4897 Label do_call, done; |
4936 // Check for overflow and that it fits into Smi. | 4898 // Check for overflow and that it fits into Smi. |
4937 __ movq(temp, result); | 4899 __ movq(temp, result); |
4938 __ shlq(temp, Immediate(1)); | 4900 __ shlq(temp, Immediate(1)); |
4939 __ j(OVERFLOW, &do_call, Assembler::kNearJump); | 4901 __ j(OVERFLOW, &do_call, Assembler::kNearJump); |
4940 __ SmiTag(result); | 4902 __ SmiTag(result); |
4941 if (FLAG_throw_on_javascript_int_overflow) { | |
4942 EmitJavascriptOverflowCheck(compiler, range(), &do_call, result); | |
4943 } | |
4944 __ jmp(&done); | 4903 __ jmp(&done); |
4945 __ Bind(&do_call); | 4904 __ Bind(&do_call); |
4946 ASSERT(instance_call()->HasICData()); | 4905 ASSERT(instance_call()->HasICData()); |
4947 const ICData& ic_data = *instance_call()->ic_data(); | 4906 const ICData& ic_data = *instance_call()->ic_data(); |
4948 ASSERT((ic_data.NumberOfChecks() == 1)); | 4907 ASSERT((ic_data.NumberOfChecks() == 1)); |
4949 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 4908 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
4950 | 4909 |
4951 const intptr_t kNumberOfArguments = 1; | 4910 const intptr_t kNumberOfArguments = 1; |
4952 __ pushq(value_obj); | 4911 __ pushq(value_obj); |
4953 compiler->GenerateStaticCall(deopt_id(), | 4912 compiler->GenerateStaticCall(deopt_id(), |
(...skipping 27 matching lines...) Expand all Loading... |
4981 Register temp = locs()->temp(0).reg(); | 4940 Register temp = locs()->temp(0).reg(); |
4982 | 4941 |
4983 __ cvttsd2siq(result, value); | 4942 __ cvttsd2siq(result, value); |
4984 // Overflow is signalled with minint. | 4943 // Overflow is signalled with minint. |
4985 Label do_call, done; | 4944 Label do_call, done; |
4986 // Check for overflow and that it fits into Smi. | 4945 // Check for overflow and that it fits into Smi. |
4987 __ movq(temp, result); | 4946 __ movq(temp, result); |
4988 __ shlq(temp, Immediate(1)); | 4947 __ shlq(temp, Immediate(1)); |
4989 __ j(OVERFLOW, deopt); | 4948 __ j(OVERFLOW, deopt); |
4990 __ SmiTag(result); | 4949 __ SmiTag(result); |
4991 if (FLAG_throw_on_javascript_int_overflow) { | |
4992 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); | |
4993 } | |
4994 } | 4950 } |
4995 | 4951 |
4996 | 4952 |
4997 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, | 4953 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, |
4998 bool opt) const { | 4954 bool opt) const { |
4999 const intptr_t kNumInputs = 1; | 4955 const intptr_t kNumInputs = 1; |
5000 const intptr_t kNumTemps = 0; | 4956 const intptr_t kNumTemps = 0; |
5001 LocationSummary* result = new(zone) LocationSummary( | 4957 LocationSummary* result = new(zone) LocationSummary( |
5002 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4958 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5003 result->set_in(0, Location::RequiresFpuRegister()); | 4959 result->set_in(0, Location::RequiresFpuRegister()); |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5416 // Right is positive. | 5372 // Right is positive. |
5417 __ addq(RDX, right); | 5373 __ addq(RDX, right); |
5418 } else { | 5374 } else { |
5419 // Right is negative. | 5375 // Right is negative. |
5420 __ subq(RDX, right); | 5376 __ subq(RDX, right); |
5421 } | 5377 } |
5422 __ Bind(&all_done); | 5378 __ Bind(&all_done); |
5423 | 5379 |
5424 __ SmiTag(RAX); | 5380 __ SmiTag(RAX); |
5425 __ SmiTag(RDX); | 5381 __ SmiTag(RDX); |
5426 // FLAG_throw_on_javascript_int_overflow: not needed. | |
5427 // Note that the result of an integer division/modulo of two | 5382 // Note that the result of an integer division/modulo of two |
5428 // in-range arguments, cannot create out-of-range result. | 5383 // in-range arguments, cannot create out-of-range result. |
5429 return; | 5384 return; |
5430 } | 5385 } |
5431 if (kind() == MergedMathInstr::kSinCos) { | 5386 if (kind() == MergedMathInstr::kSinCos) { |
5432 ASSERT(locs()->out(0).IsPairLocation()); | 5387 ASSERT(locs()->out(0).IsPairLocation()); |
5433 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5388 PairLocation* pair = locs()->out(0).AsPairLocation(); |
5434 XmmRegister out1 = pair->At(0).fpu_reg(); | 5389 XmmRegister out1 = pair->At(0).fpu_reg(); |
5435 XmmRegister out2 = pair->At(1).fpu_reg(); | 5390 XmmRegister out2 = pair->At(1).fpu_reg(); |
5436 | 5391 |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5721 const Register out = locs()->out(0).reg(); | 5676 const Register out = locs()->out(0).reg(); |
5722 | 5677 |
5723 ASSERT(out == left); | 5678 ASSERT(out == left); |
5724 | 5679 |
5725 Label* deopt = NULL; | 5680 Label* deopt = NULL; |
5726 if (CanDeoptimize()) { | 5681 if (CanDeoptimize()) { |
5727 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5682 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
5728 } | 5683 } |
5729 | 5684 |
5730 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); | 5685 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); |
5731 | |
5732 if (FLAG_throw_on_javascript_int_overflow) { | |
5733 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); | |
5734 } | |
5735 } | 5686 } |
5736 | 5687 |
5737 | 5688 |
5738 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5689 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
5739 bool opt) const { | 5690 bool opt) const { |
5740 const intptr_t kNumInputs = 1; | 5691 const intptr_t kNumInputs = 1; |
5741 const intptr_t kNumTemps = 0; | 5692 const intptr_t kNumTemps = 0; |
5742 LocationSummary* summary = new(zone) LocationSummary( | 5693 LocationSummary* summary = new(zone) LocationSummary( |
5743 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5694 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5744 summary->set_in(0, Location::RequiresRegister()); | 5695 summary->set_in(0, Location::RequiresRegister()); |
5745 summary->set_out(0, Location::SameAsFirstInput()); | 5696 summary->set_out(0, Location::SameAsFirstInput()); |
5746 return summary; | 5697 return summary; |
5747 } | 5698 } |
5748 | 5699 |
5749 | 5700 |
5750 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5701 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5751 ASSERT(op_kind() == Token::kBIT_NOT); | 5702 ASSERT(op_kind() == Token::kBIT_NOT); |
5752 const Register left = locs()->in(0).reg(); | 5703 const Register left = locs()->in(0).reg(); |
5753 const Register out = locs()->out(0).reg(); | 5704 const Register out = locs()->out(0).reg(); |
5754 ASSERT(out == left); | 5705 ASSERT(out == left); |
5755 | |
5756 Label* deopt = NULL; | |
5757 if (FLAG_throw_on_javascript_int_overflow) { | |
5758 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | |
5759 } | |
5760 | |
5761 __ notq(left); | 5706 __ notq(left); |
5762 | |
5763 if (FLAG_throw_on_javascript_int_overflow) { | |
5764 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); | |
5765 } | |
5766 } | 5707 } |
5767 | 5708 |
5768 | 5709 |
5769 static const intptr_t kMintShiftCountLimit = 63; | 5710 static const intptr_t kMintShiftCountLimit = 63; |
5770 | 5711 |
5771 bool ShiftMintOpInstr::has_shift_count_check() const { | 5712 bool ShiftMintOpInstr::has_shift_count_check() const { |
5772 return !RangeUtils::IsWithin( | 5713 return !RangeUtils::IsWithin( |
5773 right()->definition()->range(), 0, kMintShiftCountLimit); | 5714 right()->definition()->range(), 0, kMintShiftCountLimit); |
5774 } | 5715 } |
5775 | 5716 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5852 __ j(NOT_EQUAL, deopt); // Overflow. | 5793 __ j(NOT_EQUAL, deopt); // Overflow. |
5853 } | 5794 } |
5854 // Shift for result now we know there is no overflow. | 5795 // Shift for result now we know there is no overflow. |
5855 __ shlq(left, RCX); | 5796 __ shlq(left, RCX); |
5856 break; | 5797 break; |
5857 } | 5798 } |
5858 default: | 5799 default: |
5859 UNREACHABLE(); | 5800 UNREACHABLE(); |
5860 } | 5801 } |
5861 } | 5802 } |
5862 if (FLAG_throw_on_javascript_int_overflow) { | |
5863 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); | |
5864 } | |
5865 } | 5803 } |
5866 | 5804 |
5867 | 5805 |
5868 CompileType BinaryUint32OpInstr::ComputeType() const { | 5806 CompileType BinaryUint32OpInstr::ComputeType() const { |
5869 return CompileType::FromCid(kSmiCid); | 5807 return CompileType::FromCid(kSmiCid); |
5870 } | 5808 } |
5871 | 5809 |
5872 | 5810 |
5873 CompileType ShiftUint32OpInstr::ComputeType() const { | 5811 CompileType ShiftUint32OpInstr::ComputeType() const { |
5874 return CompileType::FromCid(kSmiCid); | 5812 return CompileType::FromCid(kSmiCid); |
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6459 __ Drop(1); | 6397 __ Drop(1); |
6460 __ popq(result); | 6398 __ popq(result); |
6461 } | 6399 } |
6462 | 6400 |
6463 | 6401 |
6464 } // namespace dart | 6402 } // namespace dart |
6465 | 6403 |
6466 #undef __ | 6404 #undef __ |
6467 | 6405 |
6468 #endif // defined TARGET_ARCH_X64 | 6406 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |