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

Unified Diff: runtime/vm/aot_optimizer.cc

Issue 2379733002: Recognize and optimize a.runtimeType == b.runtimeType pattern. (Closed)
Patch Set: Support polymorphic inlining of Object.get:runtimeType Created 4 years, 3 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
Index: runtime/vm/aot_optimizer.cc
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 208a2240fc853d3f771e61e847f7b873398de16c..0005a9d26ed7ac2ab9305e7722a5eaf528904cda 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -88,6 +88,47 @@ void AotOptimizer::PopulateWithICData() {
}
+bool AotOptimizer::RecognizeRuntimeTypeGetter(InstanceCallInstr* call) {
+ if ((precompiler_ == NULL) || !precompiler_->get_runtime_type_is_unique()) {
Florian Schneider 2016/09/29 18:03:29 Can we use existing CHA to detect overrides? This
Vyacheslav Egorov (Google) 2016/09/30 09:56:28 See above. CHA does not work with Object. We coul
Florian Schneider 2016/09/30 17:42:56 I think it would be out of scope for this CL. I w
+ return false;
+ }
+
+ if (call->function_name().raw() != Symbols::GetRuntimeType().raw()) {
+ return false;
+ }
+
+ // There is only a single function Object.get:runtimeType that can be invoked
+ // by this call. Convert dynamic invocation to a static one.
+ const Class& cls = Class::Handle(Z, I->object_store()->object_class());
+ const Array& args_desc_array = Array::Handle(Z,
+ ArgumentsDescriptor::New(call->ArgumentCount(),
+ call->argument_names()));
+ ArgumentsDescriptor args_desc(args_desc_array);
+ const Function& function = Function::Handle(Z,
+ Resolver::ResolveDynamicForReceiverClass(
+ cls,
+ call->function_name(),
+ args_desc));
+ ASSERT(!function.IsNull());
+
+ ZoneGrowableArray<PushArgumentInstr*>* args =
+ new (Z) ZoneGrowableArray<PushArgumentInstr*>(
+ call->ArgumentCount());
+ for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
+ args->Add(call->PushArgumentAt(i));
+ }
+ StaticCallInstr* static_call = new (Z) StaticCallInstr(
+ call->token_pos(),
+ Function::ZoneHandle(Z, function.raw()),
+ call->argument_names(),
+ args,
+ call->deopt_id());
+ static_call->set_result_cid(kTypeCid);
+ call->ReplaceWith(static_call, current_iterator());
+ return true;
+}
+
+
// Optimize instance calls using cid. This is called after optimizer
// converted instance calls to instructions. Any remaining
// instance calls are either megamorphic calls, cannot be optimized or
@@ -105,7 +146,9 @@ void AotOptimizer::ApplyClassIds() {
Instruction* instr = it.Current();
if (instr->IsInstanceCall()) {
InstanceCallInstr* call = instr->AsInstanceCall();
- if (call->HasICData()) {
+ if (RecognizeRuntimeTypeGetter(call)) {
+ continue;
+ } else if (call->HasICData()) {
if (TryCreateICData(call)) {
VisitInstanceCall(call);
}
@@ -606,6 +649,13 @@ bool AotOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call,
static bool SmiFitsInDouble() { return kSmiBits < 53; }
+static bool IsGetRuntimeType(Definition* defn) {
+ StaticCallInstr* call = defn->AsStaticCall();
+ return (call != NULL) &&
+ (call->function().recognized_kind() ==
+ MethodRecognizer::kObjectRuntimeType);
+}
+
bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
Token::Kind op_kind) {
const ICData& ic_data = *call->ic_data();
@@ -615,13 +665,39 @@ bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
Definition* left = call->ArgumentAt(0);
Definition* right = call->ArgumentAt(1);
+ // Recognize a.runtimeType == b.runtimeType and fold it into
+ // Object._haveSameRuntimeType(a, b).
+ if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() &&
+ IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) {
+ const Class& cls = Class::Handle(Z, I->object_store()->object_class());
+ const Function& have_same_runtime_type = Function::ZoneHandle(Z,
+ cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType()));
+ ASSERT(!have_same_runtime_type.IsNull());
+
+ ZoneGrowableArray<PushArgumentInstr*>* args =
+ new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
+ PushArgumentInstr* arg = new (Z) PushArgumentInstr(
+ new (Z) Value(left->ArgumentAt(0)));
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect);
+ args->Add(arg);
+ arg = new (Z) PushArgumentInstr(
+ new (Z) Value(right->ArgumentAt(0)));
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect);
+ args->Add(arg);
+ StaticCallInstr* static_call = new (Z) StaticCallInstr(
+ call->token_pos(),
+ have_same_runtime_type,
+ Object::null_array(), // argument_names
+ args,
+ call->deopt_id());
+ static_call->set_result_cid(kBoolCid);
+ ReplaceCall(call, static_call);
+ return true;
+ }
+
intptr_t cid = kIllegalCid;
if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
- if (TryStringLengthOneEquality(call, op_kind)) {
- return true;
- } else {
- return false;
- }
+ return TryStringLengthOneEquality(call, op_kind);
} else if (HasOnlyTwoOf(ic_data, kSmiCid)) {
InsertBefore(call,
new(Z) CheckSmiInstr(new(Z) Value(left),

Powered by Google App Engine
This is Rietveld 408576698