| 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" |
| (...skipping 2868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2879 | 2879 |
| 2880 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2880 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
| 2881 bool opt) const { | 2881 bool opt) const { |
| 2882 const intptr_t kNumInputs = 2; | 2882 const intptr_t kNumInputs = 2; |
| 2883 const intptr_t kNumTemps = 0; | 2883 const intptr_t kNumTemps = 0; |
| 2884 LocationSummary* summary = new(zone) LocationSummary( | 2884 LocationSummary* summary = new(zone) LocationSummary( |
| 2885 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2885 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2886 summary->set_in(0, Location::RequiresRegister()); | 2886 summary->set_in(0, Location::RequiresRegister()); |
| 2887 summary->set_in(1, Location::RequiresRegister()); | 2887 summary->set_in(1, Location::RequiresRegister()); |
| 2888 switch (op_kind()) { | 2888 switch (op_kind()) { |
| 2889 case Token::kEQ: | |
| 2890 case Token::kLT: | |
| 2891 case Token::kLTE: | |
| 2892 case Token::kGT: | |
| 2893 case Token::kGTE: | |
| 2894 case Token::kADD: | 2889 case Token::kADD: |
| 2895 case Token::kSUB: | 2890 case Token::kSUB: |
| 2896 case Token::kMUL: | 2891 case Token::kMUL: |
| 2897 summary->set_out(0, Location::RequiresRegister()); | 2892 summary->set_out(0, Location::RequiresRegister()); |
| 2898 break; | 2893 break; |
| 2899 case Token::kBIT_OR: | 2894 case Token::kBIT_OR: |
| 2900 case Token::kBIT_AND: | 2895 case Token::kBIT_AND: |
| 2901 case Token::kBIT_XOR: | 2896 case Token::kBIT_XOR: |
| 2902 summary->set_out(0, Location::SameAsFirstInput()); | 2897 summary->set_out(0, Location::SameAsFirstInput()); |
| 2903 break; | 2898 break; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2953 __ orq(result, right); | 2948 __ orq(result, right); |
| 2954 break; | 2949 break; |
| 2955 case Token::kBIT_AND: | 2950 case Token::kBIT_AND: |
| 2956 ASSERT(left == result); | 2951 ASSERT(left == result); |
| 2957 __ andq(result, right); | 2952 __ andq(result, right); |
| 2958 break; | 2953 break; |
| 2959 case Token::kBIT_XOR: | 2954 case Token::kBIT_XOR: |
| 2960 ASSERT(left == result); | 2955 ASSERT(left == result); |
| 2961 __ xorq(result, right); | 2956 __ xorq(result, right); |
| 2962 break; | 2957 break; |
| 2963 case Token::kEQ: | |
| 2964 case Token::kLT: | |
| 2965 case Token::kLTE: | |
| 2966 case Token::kGT: | |
| 2967 case Token::kGTE: { | |
| 2968 Label true_label, false_label, done; | |
| 2969 BranchLabels labels = { &true_label, &false_label, &false_label }; | |
| 2970 Condition true_condition = | |
| 2971 EmitInt64ComparisonOp(compiler, *locs(), op_kind()); | |
| 2972 EmitBranchOnCondition(compiler, true_condition, labels); | |
| 2973 __ Bind(&false_label); | |
| 2974 __ LoadObject(result, Bool::False()); | |
| 2975 __ jmp(&done); | |
| 2976 __ Bind(&true_label); | |
| 2977 __ LoadObject(result, Bool::True()); | |
| 2978 __ Bind(&done); | |
| 2979 break; | |
| 2980 } | |
| 2981 default: | 2958 default: |
| 2982 UNIMPLEMENTED(); | 2959 UNIMPLEMENTED(); |
| 2983 } | 2960 } |
| 2984 __ Bind(slow_path->exit_label()); | 2961 __ Bind(slow_path->exit_label()); |
| 2985 } | 2962 } |
| 2986 | 2963 |
| 2987 | 2964 |
| 2965 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
| 2966 public: |
| 2967 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
| 2968 intptr_t try_index, |
| 2969 BranchLabels labels, |
| 2970 bool merged = false) |
| 2971 : instruction_(instruction), |
| 2972 try_index_(try_index), |
| 2973 labels_(labels), |
| 2974 merged_(merged) { } |
| 2975 |
| 2976 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2977 if (Assembler::EmittingComments()) { |
| 2978 __ Comment("slow path smi comparison"); |
| 2979 } |
| 2980 __ Bind(entry_label()); |
| 2981 LocationSummary* locs = instruction_->locs(); |
| 2982 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |
| 2983 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
| 2984 |
| 2985 compiler->SaveLiveRegisters(locs); |
| 2986 __ pushq(locs->in(0).reg()); |
| 2987 __ pushq(locs->in(1).reg()); |
| 2988 compiler->EmitMegamorphicInstanceCall( |
| 2989 *instruction_->call()->ic_data(), |
| 2990 instruction_->call()->ArgumentCount(), |
| 2991 instruction_->call()->deopt_id(), |
| 2992 instruction_->call()->token_pos(), |
| 2993 locs, |
| 2994 try_index_, |
| 2995 /* slow_path_argument_count = */ 2); |
| 2996 __ MoveRegister(result, RAX); |
| 2997 compiler->RestoreLiveRegisters(locs); |
| 2998 if (merged_) { |
| 2999 __ CompareObject(result, Bool::True()); |
| 3000 __ j(EQUAL, instruction_->is_negated() |
| 3001 ? labels_.false_label : labels_.true_label); |
| 3002 __ jmp(instruction_->is_negated() |
| 3003 ? labels_.true_label : labels_.false_label); |
| 3004 } else { |
| 3005 __ jmp(exit_label()); |
| 3006 } |
| 3007 } |
| 3008 |
| 3009 private: |
| 3010 CheckedSmiComparisonInstr* instruction_; |
| 3011 intptr_t try_index_; |
| 3012 BranchLabels labels_; |
| 3013 bool merged_; |
| 3014 }; |
| 3015 |
| 3016 |
| 3017 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
| 3018 Zone* zone, bool opt) const { |
| 3019 const intptr_t kNumInputs = 2; |
| 3020 const intptr_t kNumTemps = 1; |
| 3021 LocationSummary* summary = new(zone) LocationSummary( |
| 3022 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3023 summary->set_in(0, Location::RequiresRegister()); |
| 3024 summary->set_in(1, Location::RequiresRegister()); |
| 3025 summary->set_temp(0, Location::RequiresRegister()); |
| 3026 summary->set_out(0, Location::RequiresRegister()); |
| 3027 return summary; |
| 3028 } |
| 3029 |
| 3030 |
| 3031 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
| 3032 FlowGraphCompiler* compiler, BranchLabels labels) { |
| 3033 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
| 3034 } |
| 3035 |
| 3036 |
| 3037 #define EMIT_SMI_CHECK \ |
| 3038 intptr_t left_cid = left()->Type()->ToCid(); \ |
| 3039 intptr_t right_cid = right()->Type()->ToCid(); \ |
| 3040 Register left = locs()->in(0).reg(); \ |
| 3041 Register right = locs()->in(1).reg(); \ |
| 3042 if (this->left()->definition() == this->right()->definition()) { \ |
| 3043 __ testq(left, Immediate(kSmiTagMask)); \ |
| 3044 } else if (left_cid == kSmiCid) { \ |
| 3045 __ testq(right, Immediate(kSmiTagMask)); \ |
| 3046 } else if (right_cid == kSmiCid) { \ |
| 3047 __ testq(left, Immediate(kSmiTagMask)); \ |
| 3048 } else { \ |
| 3049 __ movq(TMP, left); \ |
| 3050 __ orq(TMP, right); \ |
| 3051 __ testq(TMP, Immediate(kSmiTagMask)); \ |
| 3052 } \ |
| 3053 __ j(NOT_ZERO, slow_path->entry_label()) |
| 3054 |
| 3055 |
| 3056 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3057 BranchInstr* branch) { |
| 3058 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3059 CheckedSmiComparisonSlowPath* slow_path = |
| 3060 new CheckedSmiComparisonSlowPath(this, |
| 3061 compiler->CurrentTryIndex(), |
| 3062 labels, |
| 3063 /* merged = */ true); |
| 3064 compiler->AddSlowPathCode(slow_path); |
| 3065 EMIT_SMI_CHECK; |
| 3066 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3067 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3068 __ Bind(slow_path->exit_label()); |
| 3069 } |
| 3070 |
| 3071 |
| 3072 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3073 Label true_label, false_label, done; |
| 3074 BranchLabels labels = { &true_label, &false_label, &false_label }; |
| 3075 CheckedSmiComparisonSlowPath* slow_path = |
| 3076 new CheckedSmiComparisonSlowPath(this, |
| 3077 compiler->CurrentTryIndex(), |
| 3078 labels, |
| 3079 /* merged = */ false); |
| 3080 compiler->AddSlowPathCode(slow_path); |
| 3081 EMIT_SMI_CHECK; |
| 3082 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3083 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3084 Register result = locs()->out(0).reg(); |
| 3085 __ Bind(&false_label); |
| 3086 __ LoadObject(result, Bool::False()); |
| 3087 __ jmp(&done); |
| 3088 __ Bind(&true_label); |
| 3089 __ LoadObject(result, Bool::True()); |
| 3090 __ Bind(&done); |
| 3091 __ Bind(slow_path->exit_label()); |
| 3092 } |
| 3093 |
| 3094 |
| 2988 static bool CanBeImmediate(const Object& constant) { | 3095 static bool CanBeImmediate(const Object& constant) { |
| 2989 return constant.IsSmi() && | 3096 return constant.IsSmi() && |
| 2990 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); | 3097 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); |
| 2991 } | 3098 } |
| 2992 | 3099 |
| 2993 static bool IsSmiValue(const Object& constant, intptr_t value) { | 3100 static bool IsSmiValue(const Object& constant, intptr_t value) { |
| 2994 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); | 3101 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); |
| 2995 } | 3102 } |
| 2996 | 3103 |
| 2997 | 3104 |
| (...skipping 3708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6706 __ Drop(1); | 6813 __ Drop(1); |
| 6707 __ popq(result); | 6814 __ popq(result); |
| 6708 } | 6815 } |
| 6709 | 6816 |
| 6710 | 6817 |
| 6711 } // namespace dart | 6818 } // namespace dart |
| 6712 | 6819 |
| 6713 #undef __ | 6820 #undef __ |
| 6714 | 6821 |
| 6715 #endif // defined TARGET_ARCH_X64 | 6822 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |