Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: runtime/vm/intermediate_language.cc

Issue 2809583002: Use off-heap data for type feedback in PolymorphicInstanceCallInstr (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698