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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/bootstrap.h" | 8 #include "vm/bootstrap.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/constant_propagator.h" | 10 #include "vm/constant_propagator.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "vm/symbols.h" | 26 #include "vm/symbols.h" |
27 | 27 |
28 #include "vm/il_printer.h" | 28 #include "vm/il_printer.h" |
29 | 29 |
30 namespace dart { | 30 namespace dart { |
31 | 31 |
32 DEFINE_FLAG(bool, propagate_ic_data, true, | 32 DEFINE_FLAG(bool, propagate_ic_data, true, |
33 "Propagate IC data from unoptimized to optimized IC calls."); | 33 "Propagate IC data from unoptimized to optimized IC calls."); |
34 DEFINE_FLAG(bool, two_args_smi_icd, true, | 34 DEFINE_FLAG(bool, two_args_smi_icd, true, |
35 "Generate special IC stubs for two args Smi operations"); | 35 "Generate special IC stubs for two args Smi operations"); |
36 DEFINE_FLAG(bool, unbox_numeric_fields, true, | 36 DEFINE_FLAG(bool, unbox_numeric_fields, !USING_DBC, |
37 "Support unboxed double and float32x4 fields."); | 37 "Support unboxed double and float32x4 fields."); |
38 DECLARE_FLAG(bool, eliminate_type_checks); | 38 DECLARE_FLAG(bool, eliminate_type_checks); |
39 | 39 |
40 | 40 |
41 #if defined(DEBUG) | 41 #if defined(DEBUG) |
42 void Instruction::CheckField(const Field& field) const { | 42 void Instruction::CheckField(const Field& field) const { |
43 ASSERT(field.IsZoneHandle()); | 43 ASSERT(field.IsZoneHandle()); |
44 ASSERT(!Compiler::IsBackgroundCompilation() || !field.IsOriginal()); | 44 ASSERT(!Compiler::IsBackgroundCompilation() || !field.IsOriginal()); |
45 } | 45 } |
46 #endif // DEBUG | 46 #endif // DEBUG |
(...skipping 2701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2748 LocationSummary* TargetEntryInstr::MakeLocationSummary(Zone* zone, | 2748 LocationSummary* TargetEntryInstr::MakeLocationSummary(Zone* zone, |
2749 bool optimizing) const { | 2749 bool optimizing) const { |
2750 UNREACHABLE(); | 2750 UNREACHABLE(); |
2751 return NULL; | 2751 return NULL; |
2752 } | 2752 } |
2753 | 2753 |
2754 | 2754 |
2755 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2755 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2756 __ Bind(compiler->GetJumpLabel(this)); | 2756 __ Bind(compiler->GetJumpLabel(this)); |
2757 if (!compiler->is_optimizing()) { | 2757 if (!compiler->is_optimizing()) { |
| 2758 #if !defined(TARGET_ARCH_DBC) |
2758 if (compiler->NeedsEdgeCounter(this)) { | 2759 if (compiler->NeedsEdgeCounter(this)) { |
2759 compiler->EmitEdgeCounter(preorder_number()); | 2760 compiler->EmitEdgeCounter(preorder_number()); |
2760 } | 2761 } |
| 2762 #endif |
| 2763 |
2761 // The deoptimization descriptor points after the edge counter code for | 2764 // The deoptimization descriptor points after the edge counter code for |
2762 // uniformity with ARM and MIPS, where we can reuse pattern matching | 2765 // uniformity with ARM and MIPS, where we can reuse pattern matching |
2763 // code that matches backwards from the end of the pattern. | 2766 // code that matches backwards from the end of the pattern. |
2764 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2767 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, |
2765 GetDeoptId(), | 2768 GetDeoptId(), |
2766 TokenPosition::kNoSource); | 2769 TokenPosition::kNoSource); |
2767 } | 2770 } |
2768 if (HasParallelMove()) { | 2771 if (HasParallelMove()) { |
2769 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2772 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
2770 } | 2773 } |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2950 Location::SameAsFirstInput(), | 2953 Location::SameAsFirstInput(), |
2951 LocationSummary::kNoCall) | 2954 LocationSummary::kNoCall) |
2952 : LocationSummary::Make(zone, | 2955 : LocationSummary::Make(zone, |
2953 0, | 2956 0, |
2954 Location::NoLocation(), | 2957 Location::NoLocation(), |
2955 LocationSummary::kNoCall); | 2958 LocationSummary::kNoCall); |
2956 } | 2959 } |
2957 | 2960 |
2958 | 2961 |
2959 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2962 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2963 #if defined(TARGET_ARCH_DBC) |
| 2964 ASSERT(!compiler->is_optimizing()); |
| 2965 if (InputCount() != 0 && HasTemp()) { |
| 2966 __ DropR(num_temps()); |
| 2967 } else { |
| 2968 __ Drop(num_temps() + ((InputCount() != 0) ? 1 : 0)); |
| 2969 } |
| 2970 #else |
2960 ASSERT(!compiler->is_optimizing()); | 2971 ASSERT(!compiler->is_optimizing()); |
2961 // Assert that register assignment is correct. | 2972 // Assert that register assignment is correct. |
2962 ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg())); | 2973 ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg())); |
2963 __ Drop(num_temps()); | 2974 __ Drop(num_temps()); |
| 2975 #endif |
2964 } | 2976 } |
2965 | 2977 |
2966 | 2978 |
2967 StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos, | 2979 StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos, |
2968 Token::Kind kind, | 2980 Token::Kind kind, |
2969 Value* left, | 2981 Value* left, |
2970 Value* right, | 2982 Value* right, |
2971 bool needs_number_check) | 2983 bool needs_number_check) |
2972 : ComparisonInstr(token_pos, | 2984 : ComparisonInstr(token_pos, |
2973 kind, | 2985 kind, |
2974 left, | 2986 left, |
2975 right, | 2987 right, |
2976 Thread::Current()->GetNextDeoptId()), | 2988 Thread::Current()->GetNextDeoptId()), |
2977 needs_number_check_(needs_number_check) { | 2989 needs_number_check_(needs_number_check) { |
2978 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); | 2990 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); |
2979 } | 2991 } |
2980 | 2992 |
2981 | 2993 |
2982 LocationSummary* InstanceCallInstr::MakeLocationSummary(Zone* zone, | 2994 LocationSummary* InstanceCallInstr::MakeLocationSummary(Zone* zone, |
2983 bool optimizing) const { | 2995 bool optimizing) const { |
2984 return MakeCallSummary(zone); | 2996 return MakeCallSummary(zone); |
2985 } | 2997 } |
2986 | 2998 |
2987 | 2999 |
| 3000 #if !defined(TARGET_ARCH_DBC) |
2988 static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) { | 3001 static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) { |
2989 if (!FLAG_two_args_smi_icd) { | 3002 if (!FLAG_two_args_smi_icd) { |
2990 return 0; | 3003 return 0; |
2991 } | 3004 } |
2992 switch (kind) { | 3005 switch (kind) { |
2993 case Token::kADD: return StubCode::SmiAddInlineCache_entry(); | 3006 case Token::kADD: return StubCode::SmiAddInlineCache_entry(); |
2994 case Token::kSUB: return StubCode::SmiSubInlineCache_entry(); | 3007 case Token::kSUB: return StubCode::SmiSubInlineCache_entry(); |
2995 case Token::kEQ: return StubCode::SmiEqualInlineCache_entry(); | 3008 case Token::kEQ: return StubCode::SmiEqualInlineCache_entry(); |
2996 default: return NULL; | 3009 default: return NULL; |
2997 } | 3010 } |
2998 } | 3011 } |
| 3012 #endif |
2999 | 3013 |
3000 | 3014 |
3001 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3015 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3002 Zone* zone = compiler->zone(); | 3016 Zone* zone = compiler->zone(); |
3003 const ICData* call_ic_data = NULL; | 3017 const ICData* call_ic_data = NULL; |
3004 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || | 3018 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || |
3005 (ic_data() == NULL)) { | 3019 (ic_data() == NULL)) { |
3006 const Array& arguments_descriptor = | 3020 const Array& arguments_descriptor = |
3007 Array::Handle(zone, ArgumentsDescriptor::New(ArgumentCount(), | 3021 Array::Handle(zone, ArgumentsDescriptor::New(ArgumentCount(), |
3008 argument_names())); | 3022 argument_names())); |
3009 call_ic_data = compiler->GetOrAddInstanceCallICData( | 3023 call_ic_data = compiler->GetOrAddInstanceCallICData( |
3010 deopt_id(), function_name(), arguments_descriptor, | 3024 deopt_id(), function_name(), arguments_descriptor, |
3011 checked_argument_count()); | 3025 checked_argument_count()); |
3012 } else { | 3026 } else { |
3013 call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw()); | 3027 call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw()); |
3014 } | 3028 } |
| 3029 |
| 3030 #if !defined(TARGET_ARCH_DBC) |
3015 if (compiler->is_optimizing() && HasICData()) { | 3031 if (compiler->is_optimizing() && HasICData()) { |
3016 ASSERT(HasICData()); | 3032 ASSERT(HasICData()); |
3017 if (ic_data()->NumberOfUsedChecks() > 0) { | 3033 if (ic_data()->NumberOfUsedChecks() > 0) { |
3018 const ICData& unary_ic_data = | 3034 const ICData& unary_ic_data = |
3019 ICData::ZoneHandle(zone, ic_data()->AsUnaryClassChecks()); | 3035 ICData::ZoneHandle(zone, ic_data()->AsUnaryClassChecks()); |
3020 compiler->GenerateInstanceCall(deopt_id(), | 3036 compiler->GenerateInstanceCall(deopt_id(), |
3021 token_pos(), | 3037 token_pos(), |
3022 ArgumentCount(), | 3038 ArgumentCount(), |
3023 locs(), | 3039 locs(), |
3024 unary_ic_data); | 3040 unary_ic_data); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3078 compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(), | 3094 compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(), |
3079 deopt_id(), token_pos(), locs()); | 3095 deopt_id(), token_pos(), locs()); |
3080 } else { | 3096 } else { |
3081 compiler->GenerateInstanceCall(deopt_id(), | 3097 compiler->GenerateInstanceCall(deopt_id(), |
3082 token_pos(), | 3098 token_pos(), |
3083 ArgumentCount(), | 3099 ArgumentCount(), |
3084 locs(), | 3100 locs(), |
3085 *call_ic_data); | 3101 *call_ic_data); |
3086 } | 3102 } |
3087 } | 3103 } |
| 3104 #else |
| 3105 // Emit smi fast path instruction. If fast-path succeeds it skips the next |
| 3106 // instruction otherwise it fall through. |
| 3107 if (function_name().raw() == Symbols::Plus().raw()) { |
| 3108 __ AddTOS(); |
| 3109 } else if (function_name().raw() == Symbols::EqualOperator().raw()) { |
| 3110 __ EqualTOS(); |
| 3111 } else if (function_name().raw() == Symbols::LAngleBracket().raw()) { |
| 3112 __ LessThanTOS(); |
| 3113 } else if (function_name().raw() == Symbols::RAngleBracket().raw()) { |
| 3114 __ GreaterThanTOS(); |
| 3115 } else if (function_name().raw() == Symbols::BitAnd().raw()) { |
| 3116 __ BitAndTOS(); |
| 3117 } else if (function_name().raw() == Symbols::BitOr().raw()) { |
| 3118 __ BitOrTOS(); |
| 3119 } else if (function_name().raw() == Symbols::Star().raw()) { |
| 3120 __ MulTOS(); |
| 3121 } |
| 3122 |
| 3123 const intptr_t call_ic_data_kidx = __ AddConstant(*call_ic_data); |
| 3124 switch (call_ic_data->NumArgsTested()) { |
| 3125 case 1: |
| 3126 __ InstanceCall(ArgumentCount(), call_ic_data_kidx); |
| 3127 break; |
| 3128 case 2: |
| 3129 __ InstanceCall2(ArgumentCount(), call_ic_data_kidx); |
| 3130 break; |
| 3131 case 3: |
| 3132 __ InstanceCall3(ArgumentCount(), call_ic_data_kidx); |
| 3133 break; |
| 3134 default: |
| 3135 UNIMPLEMENTED(); |
| 3136 break; |
| 3137 } |
| 3138 compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, |
| 3139 deopt_id(), |
| 3140 token_pos()); |
| 3141 #endif // !defined(TARGET_ARCH_DBC) |
3088 } | 3142 } |
3089 | 3143 |
3090 | 3144 |
3091 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { | 3145 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { |
3092 return ic_data().HasOneTarget() && | 3146 return ic_data().HasOneTarget() && |
3093 (MethodRecognizer::RecognizeKind( | 3147 (MethodRecognizer::RecognizeKind( |
3094 Function::Handle(ic_data().GetTargetAt(0))) != | 3148 Function::Handle(ic_data().GetTargetAt(0))) != |
3095 MethodRecognizer::kUnknown); | 3149 MethodRecognizer::kUnknown); |
3096 } | 3150 } |
3097 | 3151 |
3098 | 3152 |
3099 bool PolymorphicInstanceCallInstr::HasOnlyDispatcherTargets() const { | 3153 bool PolymorphicInstanceCallInstr::HasOnlyDispatcherTargets() const { |
3100 for (intptr_t i = 0; i < ic_data().NumberOfChecks(); ++i) { | 3154 for (intptr_t i = 0; i < ic_data().NumberOfChecks(); ++i) { |
3101 const Function& target = Function::Handle(ic_data().GetTargetAt(i)); | 3155 const Function& target = Function::Handle(ic_data().GetTargetAt(i)); |
3102 if (!target.IsNoSuchMethodDispatcher() && | 3156 if (!target.IsNoSuchMethodDispatcher() && |
3103 !target.IsInvokeFieldDispatcher()) { | 3157 !target.IsInvokeFieldDispatcher()) { |
3104 return false; | 3158 return false; |
3105 } | 3159 } |
3106 } | 3160 } |
3107 return true; | 3161 return true; |
3108 } | 3162 } |
3109 | 3163 |
| 3164 |
| 3165 #if !defined(TARGET_ARCH_DBC) |
3110 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3166 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3111 ASSERT(ic_data().NumArgsTested() == 1); | 3167 ASSERT(ic_data().NumArgsTested() == 1); |
3112 if (!with_checks()) { | 3168 if (!with_checks()) { |
3113 ASSERT(ic_data().HasOneTarget()); | 3169 ASSERT(ic_data().HasOneTarget()); |
3114 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); | 3170 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); |
3115 compiler->GenerateStaticCall(deopt_id(), | 3171 compiler->GenerateStaticCall(deopt_id(), |
3116 instance_call()->token_pos(), | 3172 instance_call()->token_pos(), |
3117 target, | 3173 target, |
3118 instance_call()->ArgumentCount(), | 3174 instance_call()->ArgumentCount(), |
3119 instance_call()->argument_names(), | 3175 instance_call()->argument_names(), |
3120 locs(), | 3176 locs(), |
3121 ICData::Handle()); | 3177 ICData::Handle()); |
3122 return; | 3178 return; |
3123 } | 3179 } |
3124 | 3180 |
3125 compiler->EmitPolymorphicInstanceCall(ic_data(), | 3181 compiler->EmitPolymorphicInstanceCall(ic_data(), |
3126 instance_call()->ArgumentCount(), | 3182 instance_call()->ArgumentCount(), |
3127 instance_call()->argument_names(), | 3183 instance_call()->argument_names(), |
3128 deopt_id(), | 3184 deopt_id(), |
3129 instance_call()->token_pos(), | 3185 instance_call()->token_pos(), |
3130 locs()); | 3186 locs()); |
3131 } | 3187 } |
| 3188 #endif |
3132 | 3189 |
3133 | 3190 |
3134 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone, | 3191 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone, |
3135 bool optimizing) const { | 3192 bool optimizing) const { |
3136 return MakeCallSummary(zone); | 3193 return MakeCallSummary(zone); |
3137 } | 3194 } |
3138 | 3195 |
3139 | 3196 |
3140 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3197 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3198 #if !defined(TARGET_ARCH_DBC) |
3141 const ICData* call_ic_data = NULL; | 3199 const ICData* call_ic_data = NULL; |
3142 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || | 3200 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || |
3143 (ic_data() == NULL)) { | 3201 (ic_data() == NULL)) { |
3144 const Array& arguments_descriptor = | 3202 const Array& arguments_descriptor = |
3145 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), | 3203 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), |
3146 argument_names())); | 3204 argument_names())); |
3147 MethodRecognizer::Kind recognized_kind = | 3205 MethodRecognizer::Kind recognized_kind = |
3148 MethodRecognizer::RecognizeKind(function()); | 3206 MethodRecognizer::RecognizeKind(function()); |
3149 int num_args_checked = 0; | 3207 int num_args_checked = 0; |
3150 switch (recognized_kind) { | 3208 switch (recognized_kind) { |
(...skipping 12 matching lines...) Expand all Loading... |
3163 } else { | 3221 } else { |
3164 call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); | 3222 call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); |
3165 } | 3223 } |
3166 compiler->GenerateStaticCall(deopt_id(), | 3224 compiler->GenerateStaticCall(deopt_id(), |
3167 token_pos(), | 3225 token_pos(), |
3168 function(), | 3226 function(), |
3169 ArgumentCount(), | 3227 ArgumentCount(), |
3170 argument_names(), | 3228 argument_names(), |
3171 locs(), | 3229 locs(), |
3172 *call_ic_data); | 3230 *call_ic_data); |
| 3231 #else |
| 3232 const Array& arguments_descriptor = |
| 3233 (ic_data() == NULL) ? |
| 3234 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), |
| 3235 argument_names())) : |
| 3236 Array::Handle(ic_data()->arguments_descriptor()); |
| 3237 const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor); |
| 3238 |
| 3239 __ PushConstant(function()); |
| 3240 __ StaticCall(ArgumentCount(), argdesc_kidx); |
| 3241 compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall, |
| 3242 deopt_id(), |
| 3243 token_pos()); |
| 3244 #endif // !defined(TARGET_ARCH_DBC) |
3173 } | 3245 } |
3174 | 3246 |
3175 | 3247 |
3176 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3248 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3177 compiler->GenerateAssertAssignable(token_pos(), | 3249 compiler->GenerateAssertAssignable(token_pos(), |
3178 deopt_id(), | 3250 deopt_id(), |
3179 dst_type(), | 3251 dst_type(), |
3180 dst_name(), | 3252 dst_name(), |
3181 locs()); | 3253 locs()); |
| 3254 #if !defined(TARGET_ARCH_DBC) |
3182 ASSERT(locs()->in(0).reg() == locs()->out(0).reg()); | 3255 ASSERT(locs()->in(0).reg() == locs()->out(0).reg()); |
| 3256 #endif |
3183 } | 3257 } |
3184 | 3258 |
3185 | 3259 |
3186 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone, | 3260 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone, |
3187 bool opt) const { | 3261 bool opt) const { |
3188 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 3262 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
3189 } | 3263 } |
3190 | 3264 |
3191 | 3265 |
3192 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3266 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3283 intptr_t use_index = instr->env()->Length(); // Start index after inner. | 3357 intptr_t use_index = instr->env()->Length(); // Start index after inner. |
3284 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { | 3358 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { |
3285 Value* value = it.CurrentValue(); | 3359 Value* value = it.CurrentValue(); |
3286 value->set_instruction(instr); | 3360 value->set_instruction(instr); |
3287 value->set_use_index(use_index++); | 3361 value->set_use_index(use_index++); |
3288 value->definition()->AddEnvUse(value); | 3362 value->definition()->AddEnvUse(value); |
3289 } | 3363 } |
3290 } | 3364 } |
3291 | 3365 |
3292 | 3366 |
3293 static bool BindsToSmiConstant(Value* value) { | |
3294 return value->BindsToConstant() && value->BoundConstant().IsSmi(); | |
3295 } | |
3296 | |
3297 | |
3298 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left, | 3367 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left, |
3299 Value* new_right) { | 3368 Value* new_right) { |
3300 return new EqualityCompareInstr(token_pos(), | 3369 return new EqualityCompareInstr(token_pos(), |
3301 kind(), | 3370 kind(), |
3302 new_left, | 3371 new_left, |
3303 new_right, | 3372 new_right, |
3304 operation_cid(), | 3373 operation_cid(), |
3305 deopt_id()); | 3374 deopt_id()); |
3306 } | 3375 } |
3307 | 3376 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3355 } | 3424 } |
3356 for (intptr_t i = 0; i < cid_results().length(); i++) { | 3425 for (intptr_t i = 0; i < cid_results().length(); i++) { |
3357 if (cid_results()[i] != other_instr->cid_results()[i]) { | 3426 if (cid_results()[i] != other_instr->cid_results()[i]) { |
3358 return false; | 3427 return false; |
3359 } | 3428 } |
3360 } | 3429 } |
3361 return true; | 3430 return true; |
3362 } | 3431 } |
3363 | 3432 |
3364 | 3433 |
| 3434 #if !defined(TARGET_ARCH_DBC) |
| 3435 static bool BindsToSmiConstant(Value* value) { |
| 3436 return value->BindsToConstant() && value->BoundConstant().IsSmi(); |
| 3437 } |
| 3438 #endif |
| 3439 |
| 3440 |
3365 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, | 3441 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, |
3366 Value* v1, | 3442 Value* v1, |
3367 Value* v2) { | 3443 Value* v2) { |
| 3444 #if !defined(TARGET_ARCH_DBC) |
3368 bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2); | 3445 bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2); |
3369 if (comparison->IsStrictCompare()) { | 3446 if (comparison->IsStrictCompare()) { |
3370 // Strict comparison with number checks calls a stub and is not supported | 3447 // Strict comparison with number checks calls a stub and is not supported |
3371 // by if-conversion. | 3448 // by if-conversion. |
3372 return is_smi_result | 3449 return is_smi_result |
3373 && !comparison->AsStrictCompare()->needs_number_check(); | 3450 && !comparison->AsStrictCompare()->needs_number_check(); |
3374 } | 3451 } |
3375 if (comparison->operation_cid() != kSmiCid) { | 3452 if (comparison->operation_cid() != kSmiCid) { |
3376 // Non-smi comparisons are not supported by if-conversion. | 3453 // Non-smi comparisons are not supported by if-conversion. |
3377 return false; | 3454 return false; |
3378 } | 3455 } |
3379 return is_smi_result; | 3456 return is_smi_result; |
| 3457 #else |
| 3458 return false; |
| 3459 #endif // !defined(TARGET_ARCH_DBC) |
3380 } | 3460 } |
3381 | 3461 |
3382 | 3462 |
3383 bool PhiInstr::IsRedundant() const { | 3463 bool PhiInstr::IsRedundant() const { |
3384 ASSERT(InputCount() > 1); | 3464 ASSERT(InputCount() > 1); |
3385 Definition* first = InputAt(0)->definition(); | 3465 Definition* first = InputAt(0)->definition(); |
3386 for (intptr_t i = 1; i < InputCount(); ++i) { | 3466 for (intptr_t i = 1; i < InputCount(); ++i) { |
3387 Definition* def = InputAt(i)->definition(); | 3467 Definition* def = InputAt(i)->definition(); |
3388 if (def != first) return false; | 3468 if (def != first) return false; |
3389 } | 3469 } |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3734 set_native_c_function(native_function); | 3814 set_native_c_function(native_function); |
3735 function().SetIsNativeAutoSetupScope(auto_setup_scope); | 3815 function().SetIsNativeAutoSetupScope(auto_setup_scope); |
3736 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); | 3816 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); |
3737 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver); | 3817 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver); |
3738 set_is_bootstrap_native(is_bootstrap_native); | 3818 set_is_bootstrap_native(is_bootstrap_native); |
3739 } | 3819 } |
3740 | 3820 |
3741 #undef __ | 3821 #undef __ |
3742 | 3822 |
3743 } // namespace dart | 3823 } // namespace dart |
OLD | NEW |