Chromium Code Reviews| 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 3149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3160 } | 3160 } |
| 3161 | 3161 |
| 3162 | 3162 |
| 3163 bool InstanceCallInstr::MatchesCoreName(const String& name) { | 3163 bool InstanceCallInstr::MatchesCoreName(const String& name) { |
| 3164 return function_name().raw() == Library::PrivateCoreLibName(name).raw(); | 3164 return function_name().raw() == Library::PrivateCoreLibName(name).raw(); |
| 3165 } | 3165 } |
| 3166 | 3166 |
| 3167 | 3167 |
| 3168 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { | 3168 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { |
| 3169 if (FLAG_precompiled_mode && with_checks()) return false; | 3169 if (FLAG_precompiled_mode && with_checks()) return false; |
| 3170 | 3170 return targets_.HasSingleRecognizedTarget(); |
| 3171 return ic_data().HasOneTarget() && | |
| 3172 (MethodRecognizer::RecognizeKind(Function::Handle( | |
| 3173 ic_data().GetTargetAt(0))) != MethodRecognizer::kUnknown); | |
| 3174 } | 3171 } |
| 3175 | 3172 |
| 3176 | 3173 |
| 3174 bool PolymorphicTargets::HasSingleRecognizedTarget() const { | |
|
Vyacheslav Egorov (Google)
2017/04/10 10:59:28
Please don't intersperse implementations of two di
erikcorry
2017/04/19 15:06:40
Done.
| |
| 3175 if (!HasSingleTarget()) return false; | |
| 3176 return MethodRecognizer::RecognizeKind(FirstTarget()) != | |
|
Vyacheslav Egorov (Google)
2017/04/10 10:59:28
I think FirstTarget() should better be named Singl
erikcorry
2017/04/19 15:06:40
I'd like to leave it because it is sometimes used
| |
| 3177 MethodRecognizer::kUnknown; | |
| 3178 } | |
| 3179 | |
| 3180 | |
| 3181 bool PolymorphicTargets::HasSingleTarget() const { | |
| 3182 ASSERT(length() != 0); | |
| 3183 for (int i = 0; i < length(); i++) { | |
| 3184 if (cid_ranges_[i].target->raw() != cid_ranges_[0].target->raw()) | |
| 3185 return false; | |
| 3186 } | |
| 3187 return true; | |
| 3188 } | |
| 3189 | |
| 3190 | |
| 3191 bool PolymorphicInstanceCallInstr::HasOnlyDispatcherOrImplicitAccessorTargets() | |
| 3192 const { | |
| 3193 const intptr_t len = targets_.length(); | |
| 3194 Function& target = Function::Handle(); | |
| 3195 for (intptr_t i = 0; i < len; i++) { | |
| 3196 target ^= targets_[i].target->raw(); | |
| 3197 if (!target.IsDispatcherOrImplicitAccessor()) { | |
| 3198 return false; | |
| 3199 } | |
| 3200 } | |
| 3201 return true; | |
| 3202 } | |
| 3203 | |
| 3204 | |
| 3205 bool PolymorphicInstanceCallInstr::HasSingleRecognizedCid() const { | |
|
Vyacheslav Egorov (Google)
2017/04/10 10:59:28
Why is this function called HasSingleRecognizedCid
erikcorry
2017/04/19 15:06:40
Done.
| |
| 3206 if (targets_.length() != 1) return false; | |
| 3207 return targets_[0].cid_start == targets_[0].cid_end; | |
| 3208 } | |
| 3209 | |
| 3210 | |
| 3211 intptr_t PolymorphicInstanceCallInstr::SingleCid() const { | |
|
Vyacheslav Egorov (Google)
2017/04/10 10:59:28
Better name would be MonomorphicReceiverCid().
erikcorry
2017/04/19 15:06:40
Done.
| |
| 3212 ASSERT(HasSingleRecognizedCid()); | |
| 3213 return targets_[0].cid_start; | |
| 3214 } | |
| 3215 | |
| 3216 | |
| 3217 Function& PolymorphicTargets::FirstTarget() const { | |
|
Vyacheslav Egorov (Google)
2017/04/10 10:59:28
This should probably be SingleTarget()
erikcorry
2017/04/19 15:06:40
See above.
| |
| 3218 ASSERT(length() != 0); | |
| 3219 ASSERT(cid_ranges_[0].target->IsZoneHandle()); | |
| 3220 return *cid_ranges_[0].target; | |
| 3221 } | |
| 3222 | |
| 3223 | |
| 3224 intptr_t PolymorphicInstanceCallInstr::CallCount() const { | |
|
Vyacheslav Egorov (Google)
2017/04/10 10:59:28
This should probably be just calling the method on
erikcorry
2017/04/19 15:06:40
Done.
| |
| 3225 intptr_t sum = 0; | |
| 3226 for (int i = 0; i < targets_.length(); i++) { | |
| 3227 sum += targets_[i].count; | |
| 3228 } | |
| 3229 return sum; | |
| 3230 } | |
| 3231 | |
| 3232 | |
| 3177 // DBC does not support optimizing compiler and thus doesn't emit | 3233 // DBC does not support optimizing compiler and thus doesn't emit |
| 3178 // PolymorphicInstanceCallInstr. | 3234 // PolymorphicInstanceCallInstr. |
| 3179 #if !defined(TARGET_ARCH_DBC) | 3235 #if !defined(TARGET_ARCH_DBC) |
| 3180 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3236 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3181 ASSERT(ic_data().NumArgsTested() == 1); | |
| 3182 if (!with_checks()) { | 3237 if (!with_checks()) { |
| 3183 ASSERT(ic_data().HasOneTarget()); | 3238 ASSERT(HasSingleTarget()); |
| 3184 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); | 3239 const Function& target = Function::ZoneHandle(targets_[0].target->raw()); |
|
Vyacheslav Egorov (Google)
2017/04/10 10:59:28
Instead of the targets[0].target access use target
erikcorry
2017/04/19 15:06:40
Done.
| |
| 3185 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), | 3240 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), |
| 3186 target, instance_call()->ArgumentCount(), | 3241 target, instance_call()->ArgumentCount(), |
| 3187 instance_call()->argument_names(), locs(), | 3242 instance_call()->argument_names(), locs(), |
| 3188 ICData::Handle()); | 3243 ICData::Handle()); |
| 3189 return; | 3244 return; |
| 3190 } | 3245 } |
| 3191 | 3246 |
| 3192 compiler->EmitPolymorphicInstanceCall( | 3247 compiler->EmitPolymorphicInstanceCall( |
| 3193 ic_data(), instance_call()->ArgumentCount(), | 3248 targets_, *instance_call(), instance_call()->ArgumentCount(), |
| 3194 instance_call()->argument_names(), deopt_id(), | 3249 instance_call()->argument_names(), deopt_id(), |
| 3195 instance_call()->token_pos(), locs(), complete(), total_call_count()); | 3250 instance_call()->token_pos(), locs(), complete(), total_call_count()); |
| 3196 } | 3251 } |
| 3197 #endif | 3252 #endif |
| 3198 | 3253 |
| 3199 | 3254 |
| 3200 RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType( | 3255 RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType( |
| 3201 const ICData& ic_data) { | 3256 const PolymorphicTargets& targets) { |
| 3202 bool is_string = true; | 3257 bool is_string = true; |
| 3203 bool is_integer = true; | 3258 bool is_integer = true; |
| 3204 bool is_double = true; | 3259 bool is_double = true; |
| 3205 | 3260 |
| 3206 const intptr_t num_checks = ic_data.NumberOfChecks(); | 3261 const intptr_t num_checks = targets.length(); |
| 3207 for (intptr_t i = 0; i < num_checks; i++) { | 3262 for (intptr_t i = 0; i < num_checks; i++) { |
| 3208 const intptr_t cid = ic_data.GetReceiverClassIdAt(i); | 3263 ASSERT(targets[i].target->raw() == targets[0].target->raw()); |
| 3209 is_string = is_string && RawObject::IsStringClassId(cid); | 3264 const intptr_t start = targets[i].cid_start; |
| 3210 is_integer = is_integer && RawObject::IsIntegerClassId(cid); | 3265 const intptr_t end = targets[i].cid_end; |
| 3211 is_double = is_double && (cid == kDoubleCid); | 3266 for (intptr_t cid = start; cid <= end; cid++) { |
| 3267 is_string = is_string && RawObject::IsStringClassId(cid); | |
| 3268 is_integer = is_integer && RawObject::IsIntegerClassId(cid); | |
| 3269 is_double = is_double && (cid == kDoubleCid); | |
| 3270 } | |
| 3212 } | 3271 } |
| 3213 | 3272 |
| 3214 if (is_string) { | 3273 if (is_string) { |
| 3274 ASSERT(!is_integer); | |
| 3275 ASSERT(!is_double); | |
| 3215 return Type::StringType(); | 3276 return Type::StringType(); |
| 3216 } else if (is_integer) { | 3277 } else if (is_integer) { |
| 3278 ASSERT(!is_double); | |
| 3217 return Type::IntType(); | 3279 return Type::IntType(); |
| 3218 } else if (is_double) { | 3280 } else if (is_double) { |
| 3219 return Type::Double(); | 3281 return Type::Double(); |
| 3220 } | 3282 } |
| 3221 | 3283 |
| 3222 return Type::null(); | 3284 return Type::null(); |
| 3223 } | 3285 } |
| 3224 | 3286 |
| 3225 | 3287 |
| 3226 Definition* InstanceCallInstr::Canonicalize(FlowGraph* flow_graph) { | 3288 Definition* InstanceCallInstr::Canonicalize(FlowGraph* flow_graph) { |
| 3227 const intptr_t receiver_cid = PushArgumentAt(0)->value()->Type()->ToCid(); | 3289 const intptr_t receiver_cid = PushArgumentAt(0)->value()->Type()->ToCid(); |
| 3228 | 3290 |
| 3229 if (!HasICData()) return this; | 3291 if (ic_data()->NumArgsTested() != 1) return this; |
|
Vyacheslav Egorov (Google)
2017/04/10 10:59:28
Please elaborate why this check is here so that th
erikcorry
2017/04/19 15:06:40
I can't remember :-/. I have the benchmarking ser
| |
| 3230 | 3292 |
| 3231 const ICData& new_ic_data = | 3293 // TODO(erikcorry): Even for cold call sites we could still try to look up |
| 3232 FlowGraphCompiler::TrySpecializeICDataByReceiverCid(*ic_data(), | 3294 // methods when we know the receiver cid. We don't currently do this because |
| 3233 receiver_cid); | 3295 // it turns the InstanceCall into a PolymorphicInstanceCall which doesn't get |
| 3234 if (new_ic_data.raw() == ic_data()->raw()) { | 3296 // recognized or inlined when it is cold. |
|
Vyacheslav Egorov (Google)
2017/04/10 10:59:28
I don't think coldness has anything to do with it.
erikcorry
2017/04/19 15:06:40
Things seem to work with this check here, that che
| |
| 3297 if (ic_data()->NumberOfUsedChecks() == 0) return this; | |
| 3298 | |
| 3299 const PolymorphicTargets* new_target = | |
| 3300 FlowGraphCompiler::TrySpecializeByReceiverCid( | |
| 3301 Array::Handle(flow_graph->zone(), ic_data()->arguments_descriptor()), | |
| 3302 String::Handle(flow_graph->zone(), ic_data()->target_name()), | |
| 3303 receiver_cid); | |
| 3304 if (new_target == NULL) { | |
| 3235 // No specialization. | 3305 // No specialization. |
| 3236 return this; | 3306 return this; |
| 3237 } | 3307 } |
| 3238 | 3308 |
| 3239 const bool with_checks = false; | 3309 const bool with_checks = false; |
| 3240 const bool complete = false; | 3310 const bool complete = false; |
| 3241 PolymorphicInstanceCallInstr* specialized = new PolymorphicInstanceCallInstr( | 3311 PolymorphicInstanceCallInstr* specialized = new PolymorphicInstanceCallInstr( |
| 3242 this, new_ic_data, with_checks, complete); | 3312 this, *new_target, with_checks, complete); |
| 3243 flow_graph->InsertBefore(this, specialized, env(), FlowGraph::kValue); | 3313 flow_graph->InsertBefore(this, specialized, env(), FlowGraph::kValue); |
| 3244 return specialized; | 3314 return specialized; |
| 3245 } | 3315 } |
| 3246 | 3316 |
| 3247 | 3317 |
| 3248 Definition* PolymorphicInstanceCallInstr::Canonicalize(FlowGraph* flow_graph) { | 3318 Definition* PolymorphicInstanceCallInstr::Canonicalize(FlowGraph* flow_graph) { |
| 3249 if (!HasSingleRecognizedTarget() || with_checks()) { | 3319 if (!HasSingleRecognizedTarget()) { |
| 3250 return this; | 3320 return this; |
| 3251 } | 3321 } |
| 3252 | 3322 |
| 3253 const Function& target = Function::Handle(ic_data().GetTargetAt(0)); | 3323 const Function& target = FirstTarget(); |
| 3254 if (target.recognized_kind() == MethodRecognizer::kObjectRuntimeType) { | 3324 if (target.recognized_kind() == MethodRecognizer::kObjectRuntimeType) { |
| 3255 const AbstractType& type = | 3325 const AbstractType& type = |
| 3256 AbstractType::Handle(ComputeRuntimeType(ic_data())); | 3326 AbstractType::Handle(ComputeRuntimeType(targets_)); |
| 3257 if (!type.IsNull()) { | 3327 if (!type.IsNull()) { |
| 3258 return flow_graph->GetConstant(type); | 3328 return flow_graph->GetConstant(type); |
| 3259 } | 3329 } |
| 3260 } | 3330 } |
| 3261 | 3331 |
| 3262 return this; | 3332 return this; |
| 3263 } | 3333 } |
| 3264 | 3334 |
| 3265 | 3335 |
| 3266 Definition* StaticCallInstr::Canonicalize(FlowGraph* flow_graph) { | 3336 Definition* StaticCallInstr::Canonicalize(FlowGraph* flow_graph) { |
| (...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3998 "native function '%s' (%" Pd " arguments) cannot be found", | 4068 "native function '%s' (%" Pd " arguments) cannot be found", |
| 3999 native_name().ToCString(), function().NumParameters()); | 4069 native_name().ToCString(), function().NumParameters()); |
| 4000 } | 4070 } |
| 4001 set_is_auto_scope(auto_setup_scope); | 4071 set_is_auto_scope(auto_setup_scope); |
| 4002 set_native_c_function(native_function); | 4072 set_native_c_function(native_function); |
| 4003 } | 4073 } |
| 4004 | 4074 |
| 4005 #undef __ | 4075 #undef __ |
| 4006 | 4076 |
| 4007 } // namespace dart | 4077 } // namespace dart |
| OLD | NEW |