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

Unified Diff: runtime/vm/aot_optimizer.cc

Issue 1867913004: Specialize instance calls when the call receiver is the method receiver and the method class has a … (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/lib/string_patch.dart ('k') | runtime/vm/cha.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/aot_optimizer.cc
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index c39f74c88523fa12516a60d60113924011f46102..7d005b138fb5762444b59cd7c7b91299a07d6acb 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -29,6 +29,10 @@
namespace dart {
+DEFINE_FLAG(int, max_exhaustive_polymorphic_checks, 5,
+ "If a call receiver is known to be of at most this many classes, "
+ "generate exhaustive class tests instead of a megamorphic call");
+
// Quick access to the current isolate and zone.
#define I (isolate())
#define Z (zone())
@@ -281,11 +285,11 @@ void AotOptimizer::SpecializePolymorphicInstanceCall(
return;
}
- const bool with_checks = false;
PolymorphicInstanceCallInstr* specialized =
new(Z) PolymorphicInstanceCallInstr(call->instance_call(),
ic_data,
- with_checks);
+ /* with_checks = */ false,
+ /* complete = */ false);
call->ReplaceWith(specialized, current_iterator());
}
@@ -2441,7 +2445,8 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
instr, function_kind)) {
PolymorphicInstanceCallInstr* call =
new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
- /* with_checks = */ false);
+ /* with_checks = */ false,
+ /* complete = */ true);
instr->ReplaceWith(call, current_iterator());
return;
}
@@ -2514,13 +2519,71 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
ic_data.AddReceiverCheck(receiver_class.id(), function);
PolymorphicInstanceCallInstr* call =
new(Z) PolymorphicInstanceCallInstr(instr, ic_data,
- /* with_checks = */ false);
+ /* with_checks = */ false,
+ /* complete = */ true);
instr->ReplaceWith(call, current_iterator());
return;
}
}
}
+ Definition* callee_receiver = instr->ArgumentAt(0);
+ const Function& function = flow_graph_->function();
+ if (function.IsDynamicFunction() &&
+ flow_graph_->IsReceiver(callee_receiver)) {
+ // Call receiver is method receiver.
+ Class& receiver_class = Class::Handle(Z, function.Owner());
+ GrowableArray<intptr_t> class_ids(6);
+ if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) {
+ if (class_ids.length() <= FLAG_max_exhaustive_polymorphic_checks) {
+ if (FLAG_trace_cha) {
+ THR_Print(" **(CHA) Only %" Pd " concrete subclasses of %s for %s\n",
+ class_ids.length(),
+ receiver_class.ToCString(),
+ instr->function_name().ToCString());
+ }
+
+ const Array& args_desc_array = Array::Handle(Z,
+ ArgumentsDescriptor::New(instr->ArgumentCount(),
+ instr->argument_names()));
+ ArgumentsDescriptor args_desc(args_desc_array);
+
+ const ICData& ic_data = ICData::Handle(
+ ICData::New(function,
+ instr->function_name(),
+ args_desc_array,
+ Thread::kNoDeoptId,
+ /* args_tested = */ 1));
+
+ Function& target = Function::Handle(Z);
+ Class& cls = Class::Handle(Z);
+ bool includes_dispatcher_case = false;
+ for (intptr_t i = 0; i < class_ids.length(); i++) {
+ intptr_t cid = class_ids[i];
+ cls = isolate()->class_table()->At(cid);
+ target = Resolver::ResolveDynamicForReceiverClass(
+ cls,
+ instr->function_name(),
+ args_desc);
+ if (target.IsNull()) {
+ // noSuchMethod, call through getter or closurization
+ includes_dispatcher_case = true;
+ } else {
+ ic_data.AddReceiverCheck(cid, target);
+ }
+ }
+ if (!includes_dispatcher_case && (ic_data.NumberOfChecks() > 0)) {
+ PolymorphicInstanceCallInstr* call =
+ new(Z) PolymorphicInstanceCallInstr(instr, ic_data,
+ /* with_checks = */ true,
+ /* complete = */ true);
+ instr->ReplaceWith(call, current_iterator());
+ return;
+ }
+ }
+ }
+ }
+
// More than one targets. Generate generic polymorphic call without
// deoptimization.
if (instr->ic_data()->NumberOfUsedChecks() > 0) {
@@ -2529,7 +2592,8 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
// deoptimization is allowed.
PolymorphicInstanceCallInstr* call =
new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
- /* with_checks = */ true);
+ /* with_checks = */ true,
+ /* complete = */ false);
instr->ReplaceWith(call, current_iterator());
return;
}
« no previous file with comments | « runtime/lib/string_patch.dart ('k') | runtime/vm/cha.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698