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