| 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 |