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

Unified Diff: runtime/vm/aot_optimizer.cc

Issue 2412653002: VM Propagate receiver type from calls to unique selectors in AOT compilation. (Closed)
Patch Set: addressed comments, added test Created 4 years, 2 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/vm/aot_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.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 208a2240fc853d3f771e61e847f7b873398de16c..c938bc3799a82e1860e3385892e05e7e663c503f 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -54,6 +54,42 @@ static bool CanConvertUnboxedMintToDouble() {
}
+// Returns named function that is a unique dynamic target, i.e.,
+// - the target is identified by its name alone, since it occurs only once.
+// - target's class has no subclasses, and neither is subclassed, i.e.,
+// the receiver type can be only the function's class.
+// Returns Function::null() if there is no unique dynamic target for
+// given 'fname'. 'fname' must be a symbol.
+static void GetUniqueDynamicTarget(Isolate* isolate,
+ const String& fname,
+ Object* function) {
+ UniqueFunctionsSet functions_set(
+ isolate->object_store()->unique_dynamic_targets());
+ ASSERT(fname.IsSymbol());
+ *function = functions_set.GetOrNull(fname);
+ ASSERT(functions_set.Release().raw() ==
+ isolate->object_store()->unique_dynamic_targets());
+}
+
+
+AotOptimizer::AotOptimizer(FlowGraph* flow_graph,
+ bool use_speculative_inlining,
+ GrowableArray<intptr_t>* inlining_black_list)
+ : FlowGraphVisitor(flow_graph->reverse_postorder()),
+ flow_graph_(flow_graph),
+ use_speculative_inlining_(use_speculative_inlining),
+ inlining_black_list_(inlining_black_list),
+ has_unique_no_such_method_(false) {
+ ASSERT(!use_speculative_inlining || (inlining_black_list != NULL));
+ Function& target_function = Function::Handle();
+ if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) {
+ GetUniqueDynamicTarget(
+ isolate(), Symbols::NoSuchMethod(), &target_function);
+ has_unique_no_such_method_ = !target_function.IsNull();
+ }
+}
+
+
// Optimize instance calls using ICData.
void AotOptimizer::ApplyICData() {
VisitBlocks();
@@ -123,24 +159,6 @@ static bool IsNumberCid(intptr_t cid) {
}
-// Returns named function that is a unique dynamic target, i.e.,
-// - the target is identified by its name alone, since it occurs only once.
-// - target's class has no subclasses, and neither is subclassed, i.e.,
-// the receiver type can be only the function's class.
-// Returns Function::null() if there is no unique dynamic target for
-// given 'fname'. 'fname' must be a symbol.
-static void GetUniqueDynamicTarget(Isolate* isolate,
- const String& fname,
- Object* function) {
- UniqueFunctionsSet functions_set(
- isolate->object_store()->unique_dynamic_targets());
- ASSERT(fname.IsSymbol());
- *function = functions_set.GetOrNull(fname);
- ASSERT(functions_set.Release().raw() ==
- isolate->object_store()->unique_dynamic_targets());
-}
-
-
bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
ASSERT(call->HasICData());
if (call->ic_data()->NumberOfUsedChecks() > 0) {
@@ -227,12 +245,17 @@ bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
!target_function.HasOptionalNamedParameters() &&
target_function.AreValidArgumentCounts(call->ArgumentCount(), 0,
/* error_message = */ NULL)) {
- const intptr_t cid = Class::Handle(Z, target_function.Owner()).id();
- const ICData& ic_data = ICData::ZoneHandle(Z,
- ICData::NewFrom(*call->ic_data(), 1));
- ic_data.AddReceiverCheck(cid, target_function);
- call->set_ic_data(&ic_data);
- return true;
+ const Class& cls = Class::Handle(Z, target_function.Owner());
+ if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) {
+ const ICData& ic_data = ICData::ZoneHandle(Z,
+ ICData::NewFrom(*call->ic_data(), 1));
+ ic_data.AddReceiverCheck(cls.id(), target_function);
+ call->set_ic_data(&ic_data);
+ if (has_unique_no_such_method_) {
+ call->set_has_unique_selector(true);
+ }
+ return true;
+ }
}
}
@@ -1995,6 +2018,32 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
}
+void AotOptimizer::VisitPolymorphicInstanceCall(
+ PolymorphicInstanceCallInstr* call) {
+ if (call->with_checks()) {
+ const intptr_t receiver_cid =
+ call->PushArgumentAt(0)->value()->Type()->ToCid();
+ if (receiver_cid != kDynamicCid) {
+ const Class& receiver_class = Class::Handle(Z,
+ isolate()->class_table()->At(receiver_cid));
+
+ const Array& args_desc_array = Array::Handle(Z,
+ ArgumentsDescriptor::New(call->ArgumentCount(),
+ call->instance_call()->argument_names()));
+ ArgumentsDescriptor args_desc(args_desc_array);
+ const Function& function = Function::Handle(Z,
+ Resolver::ResolveDynamicForReceiverClass(
+ receiver_class,
+ call->instance_call()->function_name(),
+ args_desc));
+ if (!function.IsNull()) {
+ call->set_with_checks(false);
+ }
+ }
+ }
+}
+
+
void AotOptimizer::VisitStaticCall(StaticCallInstr* call) {
if (!IsAllowedForInlining(call->deopt_id())) {
// Inlining disabled after a speculative inlining attempt.
« no previous file with comments | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698