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 DECLARE_FLAG(bool, support_externalizable_strings); | 39 DECLARE_FLAG(bool, support_externalizable_strings); |
40 | 40 |
41 | 41 |
42 #if defined(DEBUG) | 42 #if defined(DEBUG) |
43 void Instruction::CheckField(const Field& field) const { | 43 void Instruction::CheckField(const Field& field) const { |
44 ASSERT(field.IsZoneHandle()); | 44 ASSERT(field.IsZoneHandle()); |
45 ASSERT(!Compiler::IsBackgroundCompilation() || !field.IsOriginal()); | 45 ASSERT(!Compiler::IsBackgroundCompilation() || !field.IsOriginal()); |
46 } | 46 } |
(...skipping 2712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2759 LocationSummary* TargetEntryInstr::MakeLocationSummary(Zone* zone, | 2759 LocationSummary* TargetEntryInstr::MakeLocationSummary(Zone* zone, |
2760 bool optimizing) const { | 2760 bool optimizing) const { |
2761 UNREACHABLE(); | 2761 UNREACHABLE(); |
2762 return NULL; | 2762 return NULL; |
2763 } | 2763 } |
2764 | 2764 |
2765 | 2765 |
2766 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2766 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2767 __ Bind(compiler->GetJumpLabel(this)); | 2767 __ Bind(compiler->GetJumpLabel(this)); |
2768 if (!compiler->is_optimizing()) { | 2768 if (!compiler->is_optimizing()) { |
| 2769 #if !defined(TARGET_ARCH_DBC) |
| 2770 // TODO(vegorov) re-enable edge counters on DBC if we consider them |
| 2771 // beneficial for the quality of the optimized bytecode. |
2769 if (compiler->NeedsEdgeCounter(this)) { | 2772 if (compiler->NeedsEdgeCounter(this)) { |
2770 compiler->EmitEdgeCounter(preorder_number()); | 2773 compiler->EmitEdgeCounter(preorder_number()); |
2771 } | 2774 } |
| 2775 #endif |
| 2776 |
2772 // The deoptimization descriptor points after the edge counter code for | 2777 // The deoptimization descriptor points after the edge counter code for |
2773 // uniformity with ARM and MIPS, where we can reuse pattern matching | 2778 // uniformity with ARM and MIPS, where we can reuse pattern matching |
2774 // code that matches backwards from the end of the pattern. | 2779 // code that matches backwards from the end of the pattern. |
2775 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2780 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, |
2776 GetDeoptId(), | 2781 GetDeoptId(), |
2777 TokenPosition::kNoSource); | 2782 TokenPosition::kNoSource); |
2778 } | 2783 } |
2779 if (HasParallelMove()) { | 2784 if (HasParallelMove()) { |
2780 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2785 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
2781 } | 2786 } |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2961 Location::SameAsFirstInput(), | 2966 Location::SameAsFirstInput(), |
2962 LocationSummary::kNoCall) | 2967 LocationSummary::kNoCall) |
2963 : LocationSummary::Make(zone, | 2968 : LocationSummary::Make(zone, |
2964 0, | 2969 0, |
2965 Location::NoLocation(), | 2970 Location::NoLocation(), |
2966 LocationSummary::kNoCall); | 2971 LocationSummary::kNoCall); |
2967 } | 2972 } |
2968 | 2973 |
2969 | 2974 |
2970 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2975 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2976 #if defined(TARGET_ARCH_DBC) |
| 2977 // On DBC the action of poping the TOS value and then pushing it |
| 2978 // after all intermediates are poped is folded into a special |
| 2979 // bytecode (DropR). On other architectures this is handled by |
| 2980 // instruction prologue/epilogues. |
| 2981 ASSERT(!compiler->is_optimizing()); |
| 2982 if ((InputCount() != 0) && HasTemp()) { |
| 2983 __ DropR(num_temps()); |
| 2984 } else { |
| 2985 __ Drop(num_temps() + ((InputCount() != 0) ? 1 : 0)); |
| 2986 } |
| 2987 #else |
2971 ASSERT(!compiler->is_optimizing()); | 2988 ASSERT(!compiler->is_optimizing()); |
2972 // Assert that register assignment is correct. | 2989 // Assert that register assignment is correct. |
2973 ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg())); | 2990 ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg())); |
2974 __ Drop(num_temps()); | 2991 __ Drop(num_temps()); |
| 2992 #endif // defined(TARGET_ARCH_DBC) |
2975 } | 2993 } |
2976 | 2994 |
2977 | 2995 |
2978 StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos, | 2996 StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos, |
2979 Token::Kind kind, | 2997 Token::Kind kind, |
2980 Value* left, | 2998 Value* left, |
2981 Value* right, | 2999 Value* right, |
2982 bool needs_number_check) | 3000 bool needs_number_check) |
2983 : ComparisonInstr(token_pos, | 3001 : ComparisonInstr(token_pos, |
2984 kind, | 3002 kind, |
2985 left, | 3003 left, |
2986 right, | 3004 right, |
2987 Thread::Current()->GetNextDeoptId()), | 3005 Thread::Current()->GetNextDeoptId()), |
2988 needs_number_check_(needs_number_check) { | 3006 needs_number_check_(needs_number_check) { |
2989 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); | 3007 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); |
2990 } | 3008 } |
2991 | 3009 |
2992 | 3010 |
2993 LocationSummary* InstanceCallInstr::MakeLocationSummary(Zone* zone, | 3011 LocationSummary* InstanceCallInstr::MakeLocationSummary(Zone* zone, |
2994 bool optimizing) const { | 3012 bool optimizing) const { |
2995 return MakeCallSummary(zone); | 3013 return MakeCallSummary(zone); |
2996 } | 3014 } |
2997 | 3015 |
2998 | 3016 |
| 3017 // DBC does not use specialized inline cache stubs for smi operations. |
| 3018 #if !defined(TARGET_ARCH_DBC) |
2999 static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) { | 3019 static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) { |
3000 if (!FLAG_two_args_smi_icd) { | 3020 if (!FLAG_two_args_smi_icd) { |
3001 return 0; | 3021 return 0; |
3002 } | 3022 } |
3003 switch (kind) { | 3023 switch (kind) { |
3004 case Token::kADD: return StubCode::SmiAddInlineCache_entry(); | 3024 case Token::kADD: return StubCode::SmiAddInlineCache_entry(); |
3005 case Token::kSUB: return StubCode::SmiSubInlineCache_entry(); | 3025 case Token::kSUB: return StubCode::SmiSubInlineCache_entry(); |
3006 case Token::kEQ: return StubCode::SmiEqualInlineCache_entry(); | 3026 case Token::kEQ: return StubCode::SmiEqualInlineCache_entry(); |
3007 default: return NULL; | 3027 default: return NULL; |
3008 } | 3028 } |
3009 } | 3029 } |
| 3030 #endif |
3010 | 3031 |
3011 | 3032 |
3012 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3033 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3013 Zone* zone = compiler->zone(); | 3034 Zone* zone = compiler->zone(); |
3014 const ICData* call_ic_data = NULL; | 3035 const ICData* call_ic_data = NULL; |
3015 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || | 3036 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || |
3016 (ic_data() == NULL)) { | 3037 (ic_data() == NULL)) { |
3017 const Array& arguments_descriptor = | 3038 const Array& arguments_descriptor = |
3018 Array::Handle(zone, ArgumentsDescriptor::New(ArgumentCount(), | 3039 Array::Handle(zone, ArgumentsDescriptor::New(ArgumentCount(), |
3019 argument_names())); | 3040 argument_names())); |
3020 call_ic_data = compiler->GetOrAddInstanceCallICData( | 3041 call_ic_data = compiler->GetOrAddInstanceCallICData( |
3021 deopt_id(), function_name(), arguments_descriptor, | 3042 deopt_id(), function_name(), arguments_descriptor, |
3022 checked_argument_count()); | 3043 checked_argument_count()); |
3023 } else { | 3044 } else { |
3024 call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw()); | 3045 call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw()); |
3025 } | 3046 } |
| 3047 |
| 3048 #if !defined(TARGET_ARCH_DBC) |
3026 if (compiler->is_optimizing() && HasICData()) { | 3049 if (compiler->is_optimizing() && HasICData()) { |
3027 ASSERT(HasICData()); | 3050 ASSERT(HasICData()); |
3028 if (ic_data()->NumberOfUsedChecks() > 0) { | 3051 if (ic_data()->NumberOfUsedChecks() > 0) { |
3029 const ICData& unary_ic_data = | 3052 const ICData& unary_ic_data = |
3030 ICData::ZoneHandle(zone, ic_data()->AsUnaryClassChecks()); | 3053 ICData::ZoneHandle(zone, ic_data()->AsUnaryClassChecks()); |
3031 compiler->GenerateInstanceCall(deopt_id(), | 3054 compiler->GenerateInstanceCall(deopt_id(), |
3032 token_pos(), | 3055 token_pos(), |
3033 ArgumentCount(), | 3056 ArgumentCount(), |
3034 locs(), | 3057 locs(), |
3035 unary_ic_data); | 3058 unary_ic_data); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3089 compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(), | 3112 compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(), |
3090 deopt_id(), token_pos(), locs()); | 3113 deopt_id(), token_pos(), locs()); |
3091 } else { | 3114 } else { |
3092 compiler->GenerateInstanceCall(deopt_id(), | 3115 compiler->GenerateInstanceCall(deopt_id(), |
3093 token_pos(), | 3116 token_pos(), |
3094 ArgumentCount(), | 3117 ArgumentCount(), |
3095 locs(), | 3118 locs(), |
3096 *call_ic_data); | 3119 *call_ic_data); |
3097 } | 3120 } |
3098 } | 3121 } |
| 3122 #else |
| 3123 // Emit smi fast path instruction. If fast-path succeeds it skips the next |
| 3124 // instruction otherwise it falls through. |
| 3125 if (function_name().raw() == Symbols::Plus().raw()) { |
| 3126 __ AddTOS(); |
| 3127 } else if (function_name().raw() == Symbols::EqualOperator().raw()) { |
| 3128 __ EqualTOS(); |
| 3129 } else if (function_name().raw() == Symbols::LAngleBracket().raw()) { |
| 3130 __ LessThanTOS(); |
| 3131 } else if (function_name().raw() == Symbols::RAngleBracket().raw()) { |
| 3132 __ GreaterThanTOS(); |
| 3133 } else if (function_name().raw() == Symbols::BitAnd().raw()) { |
| 3134 __ BitAndTOS(); |
| 3135 } else if (function_name().raw() == Symbols::BitOr().raw()) { |
| 3136 __ BitOrTOS(); |
| 3137 } else if (function_name().raw() == Symbols::Star().raw()) { |
| 3138 __ MulTOS(); |
| 3139 } |
| 3140 |
| 3141 const intptr_t call_ic_data_kidx = __ AddConstant(*call_ic_data); |
| 3142 switch (call_ic_data->NumArgsTested()) { |
| 3143 case 1: |
| 3144 __ InstanceCall(ArgumentCount(), call_ic_data_kidx); |
| 3145 break; |
| 3146 case 2: |
| 3147 __ InstanceCall2(ArgumentCount(), call_ic_data_kidx); |
| 3148 break; |
| 3149 case 3: |
| 3150 __ InstanceCall3(ArgumentCount(), call_ic_data_kidx); |
| 3151 break; |
| 3152 default: |
| 3153 UNIMPLEMENTED(); |
| 3154 break; |
| 3155 } |
| 3156 compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, |
| 3157 deopt_id(), |
| 3158 token_pos()); |
| 3159 #endif // !defined(TARGET_ARCH_DBC) |
3099 } | 3160 } |
3100 | 3161 |
3101 | 3162 |
3102 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { | 3163 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { |
3103 return ic_data().HasOneTarget() && | 3164 return ic_data().HasOneTarget() && |
3104 (MethodRecognizer::RecognizeKind( | 3165 (MethodRecognizer::RecognizeKind( |
3105 Function::Handle(ic_data().GetTargetAt(0))) != | 3166 Function::Handle(ic_data().GetTargetAt(0))) != |
3106 MethodRecognizer::kUnknown); | 3167 MethodRecognizer::kUnknown); |
3107 } | 3168 } |
3108 | 3169 |
3109 | 3170 |
3110 bool PolymorphicInstanceCallInstr::HasOnlyDispatcherTargets() const { | 3171 bool PolymorphicInstanceCallInstr::HasOnlyDispatcherTargets() const { |
3111 for (intptr_t i = 0; i < ic_data().NumberOfChecks(); ++i) { | 3172 for (intptr_t i = 0; i < ic_data().NumberOfChecks(); ++i) { |
3112 const Function& target = Function::Handle(ic_data().GetTargetAt(i)); | 3173 const Function& target = Function::Handle(ic_data().GetTargetAt(i)); |
3113 if (!target.IsNoSuchMethodDispatcher() && | 3174 if (!target.IsNoSuchMethodDispatcher() && |
3114 !target.IsInvokeFieldDispatcher()) { | 3175 !target.IsInvokeFieldDispatcher()) { |
3115 return false; | 3176 return false; |
3116 } | 3177 } |
3117 } | 3178 } |
3118 return true; | 3179 return true; |
3119 } | 3180 } |
3120 | 3181 |
| 3182 |
| 3183 // DBC does not support optimizing compiler and thus doesn't emit |
| 3184 // PolymorphicInstanceCallInstr. |
| 3185 #if !defined(TARGET_ARCH_DBC) |
3121 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3186 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3122 ASSERT(ic_data().NumArgsTested() == 1); | 3187 ASSERT(ic_data().NumArgsTested() == 1); |
3123 if (!with_checks()) { | 3188 if (!with_checks()) { |
3124 ASSERT(ic_data().HasOneTarget()); | 3189 ASSERT(ic_data().HasOneTarget()); |
3125 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); | 3190 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); |
3126 compiler->GenerateStaticCall(deopt_id(), | 3191 compiler->GenerateStaticCall(deopt_id(), |
3127 instance_call()->token_pos(), | 3192 instance_call()->token_pos(), |
3128 target, | 3193 target, |
3129 instance_call()->ArgumentCount(), | 3194 instance_call()->ArgumentCount(), |
3130 instance_call()->argument_names(), | 3195 instance_call()->argument_names(), |
3131 locs(), | 3196 locs(), |
3132 ICData::Handle()); | 3197 ICData::Handle()); |
3133 return; | 3198 return; |
3134 } | 3199 } |
3135 | 3200 |
3136 compiler->EmitPolymorphicInstanceCall(ic_data(), | 3201 compiler->EmitPolymorphicInstanceCall(ic_data(), |
3137 instance_call()->ArgumentCount(), | 3202 instance_call()->ArgumentCount(), |
3138 instance_call()->argument_names(), | 3203 instance_call()->argument_names(), |
3139 deopt_id(), | 3204 deopt_id(), |
3140 instance_call()->token_pos(), | 3205 instance_call()->token_pos(), |
3141 locs(), | 3206 locs(), |
3142 complete()); | 3207 complete()); |
3143 } | 3208 } |
| 3209 #endif |
3144 | 3210 |
3145 | 3211 |
3146 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone, | 3212 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone, |
3147 bool optimizing) const { | 3213 bool optimizing) const { |
3148 return MakeCallSummary(zone); | 3214 return MakeCallSummary(zone); |
3149 } | 3215 } |
3150 | 3216 |
3151 | 3217 |
3152 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3218 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3219 #if !defined(TARGET_ARCH_DBC) |
3153 const ICData* call_ic_data = NULL; | 3220 const ICData* call_ic_data = NULL; |
3154 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || | 3221 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || |
3155 (ic_data() == NULL)) { | 3222 (ic_data() == NULL)) { |
3156 const Array& arguments_descriptor = | 3223 const Array& arguments_descriptor = |
3157 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), | 3224 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), |
3158 argument_names())); | 3225 argument_names())); |
3159 MethodRecognizer::Kind recognized_kind = | 3226 MethodRecognizer::Kind recognized_kind = |
3160 MethodRecognizer::RecognizeKind(function()); | 3227 MethodRecognizer::RecognizeKind(function()); |
3161 int num_args_checked = 0; | 3228 int num_args_checked = 0; |
3162 switch (recognized_kind) { | 3229 switch (recognized_kind) { |
(...skipping 12 matching lines...) Expand all Loading... |
3175 } else { | 3242 } else { |
3176 call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); | 3243 call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); |
3177 } | 3244 } |
3178 compiler->GenerateStaticCall(deopt_id(), | 3245 compiler->GenerateStaticCall(deopt_id(), |
3179 token_pos(), | 3246 token_pos(), |
3180 function(), | 3247 function(), |
3181 ArgumentCount(), | 3248 ArgumentCount(), |
3182 argument_names(), | 3249 argument_names(), |
3183 locs(), | 3250 locs(), |
3184 *call_ic_data); | 3251 *call_ic_data); |
| 3252 #else |
| 3253 const Array& arguments_descriptor = |
| 3254 (ic_data() == NULL) ? |
| 3255 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), |
| 3256 argument_names())) : |
| 3257 Array::Handle(ic_data()->arguments_descriptor()); |
| 3258 const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor); |
| 3259 |
| 3260 __ PushConstant(function()); |
| 3261 __ StaticCall(ArgumentCount(), argdesc_kidx); |
| 3262 compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall, |
| 3263 deopt_id(), |
| 3264 token_pos()); |
| 3265 #endif // !defined(TARGET_ARCH_DBC) |
3185 } | 3266 } |
3186 | 3267 |
3187 | 3268 |
3188 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3269 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3189 compiler->GenerateAssertAssignable(token_pos(), | 3270 compiler->GenerateAssertAssignable(token_pos(), |
3190 deopt_id(), | 3271 deopt_id(), |
3191 dst_type(), | 3272 dst_type(), |
3192 dst_name(), | 3273 dst_name(), |
3193 locs()); | 3274 locs()); |
| 3275 |
| 3276 // DBC does not use LocationSummaries in the same way as other architectures. |
| 3277 #if !defined(TARGET_ARCH_DBC) |
3194 ASSERT(locs()->in(0).reg() == locs()->out(0).reg()); | 3278 ASSERT(locs()->in(0).reg() == locs()->out(0).reg()); |
| 3279 #endif |
3195 } | 3280 } |
3196 | 3281 |
3197 | 3282 |
3198 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone, | 3283 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone, |
3199 bool opt) const { | 3284 bool opt) const { |
3200 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 3285 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
3201 } | 3286 } |
3202 | 3287 |
3203 | 3288 |
3204 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3289 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3295 intptr_t use_index = instr->env()->Length(); // Start index after inner. | 3380 intptr_t use_index = instr->env()->Length(); // Start index after inner. |
3296 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { | 3381 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { |
3297 Value* value = it.CurrentValue(); | 3382 Value* value = it.CurrentValue(); |
3298 value->set_instruction(instr); | 3383 value->set_instruction(instr); |
3299 value->set_use_index(use_index++); | 3384 value->set_use_index(use_index++); |
3300 value->definition()->AddEnvUse(value); | 3385 value->definition()->AddEnvUse(value); |
3301 } | 3386 } |
3302 } | 3387 } |
3303 | 3388 |
3304 | 3389 |
3305 static bool BindsToSmiConstant(Value* value) { | |
3306 return value->BindsToConstant() && value->BoundConstant().IsSmi(); | |
3307 } | |
3308 | |
3309 | |
3310 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left, | 3390 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left, |
3311 Value* new_right) { | 3391 Value* new_right) { |
3312 return new EqualityCompareInstr(token_pos(), | 3392 return new EqualityCompareInstr(token_pos(), |
3313 kind(), | 3393 kind(), |
3314 new_left, | 3394 new_left, |
3315 new_right, | 3395 new_right, |
3316 operation_cid(), | 3396 operation_cid(), |
3317 deopt_id()); | 3397 deopt_id()); |
3318 } | 3398 } |
3319 | 3399 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3367 } | 3447 } |
3368 for (intptr_t i = 0; i < cid_results().length(); i++) { | 3448 for (intptr_t i = 0; i < cid_results().length(); i++) { |
3369 if (cid_results()[i] != other_instr->cid_results()[i]) { | 3449 if (cid_results()[i] != other_instr->cid_results()[i]) { |
3370 return false; | 3450 return false; |
3371 } | 3451 } |
3372 } | 3452 } |
3373 return true; | 3453 return true; |
3374 } | 3454 } |
3375 | 3455 |
3376 | 3456 |
| 3457 #if !defined(TARGET_ARCH_DBC) |
| 3458 static bool BindsToSmiConstant(Value* value) { |
| 3459 return value->BindsToConstant() && value->BoundConstant().IsSmi(); |
| 3460 } |
| 3461 #endif |
| 3462 |
| 3463 |
3377 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, | 3464 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, |
3378 Value* v1, | 3465 Value* v1, |
3379 Value* v2) { | 3466 Value* v2) { |
| 3467 #if !defined(TARGET_ARCH_DBC) |
3380 bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2); | 3468 bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2); |
3381 if (comparison->IsStrictCompare()) { | 3469 if (comparison->IsStrictCompare()) { |
3382 // Strict comparison with number checks calls a stub and is not supported | 3470 // Strict comparison with number checks calls a stub and is not supported |
3383 // by if-conversion. | 3471 // by if-conversion. |
3384 return is_smi_result | 3472 return is_smi_result |
3385 && !comparison->AsStrictCompare()->needs_number_check(); | 3473 && !comparison->AsStrictCompare()->needs_number_check(); |
3386 } | 3474 } |
3387 if (comparison->operation_cid() != kSmiCid) { | 3475 if (comparison->operation_cid() != kSmiCid) { |
3388 // Non-smi comparisons are not supported by if-conversion. | 3476 // Non-smi comparisons are not supported by if-conversion. |
3389 return false; | 3477 return false; |
3390 } | 3478 } |
3391 return is_smi_result; | 3479 return is_smi_result; |
| 3480 #else |
| 3481 return false; |
| 3482 #endif // !defined(TARGET_ARCH_DBC) |
3392 } | 3483 } |
3393 | 3484 |
3394 | 3485 |
3395 bool PhiInstr::IsRedundant() const { | 3486 bool PhiInstr::IsRedundant() const { |
3396 ASSERT(InputCount() > 1); | 3487 ASSERT(InputCount() > 1); |
3397 Definition* first = InputAt(0)->definition(); | 3488 Definition* first = InputAt(0)->definition(); |
3398 for (intptr_t i = 1; i < InputCount(); ++i) { | 3489 for (intptr_t i = 1; i < InputCount(); ++i) { |
3399 Definition* def = InputAt(i)->definition(); | 3490 Definition* def = InputAt(i)->definition(); |
3400 if (def != first) return false; | 3491 if (def != first) return false; |
3401 } | 3492 } |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3753 set_native_c_function(native_function); | 3844 set_native_c_function(native_function); |
3754 function().SetIsNativeAutoSetupScope(auto_setup_scope); | 3845 function().SetIsNativeAutoSetupScope(auto_setup_scope); |
3755 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); | 3846 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); |
3756 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver); | 3847 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver); |
3757 set_is_bootstrap_native(is_bootstrap_native); | 3848 set_is_bootstrap_native(is_bootstrap_native); |
3758 } | 3849 } |
3759 | 3850 |
3760 #undef __ | 3851 #undef __ |
3761 | 3852 |
3762 } // namespace dart | 3853 } // namespace dart |
OLD | NEW |