Index: runtime/vm/aot_optimizer.cc |
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc |
index 5dfe8f507c5c258647c1c4d08ef7533b7a01ab75..af4deeb6fc4fd82e7a9f4fc77189271e30970fcd 100644 |
--- a/runtime/vm/aot_optimizer.cc |
+++ b/runtime/vm/aot_optimizer.cc |
@@ -1565,6 +1565,122 @@ void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
const AbstractType& type = |
AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); |
ASSERT(!type.IsMalformedOrMalbounded()); |
+ |
+ if (TypeCheckAsClassEquality(type)) { |
+ LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left)); |
+ InsertBefore(call, left_cid, NULL, FlowGraph::kValue); |
+ const intptr_t type_cid = Class::ZoneHandle(Z, type.type_class()).id(); |
+ ConstantInstr* cid = |
+ flow_graph()->GetConstant(Smi::ZoneHandle(Z, Smi::New(type_cid))); |
+ ConstantInstr* pos = flow_graph()->GetConstant( |
+ Smi::ZoneHandle(Z, Smi::New(call->token_pos().Pos()))); |
+ |
+ ZoneGrowableArray<PushArgumentInstr*>* args = |
+ new (Z) ZoneGrowableArray<PushArgumentInstr*>(5); |
+ PushArgumentInstr* arg = new (Z) PushArgumentInstr(new (Z) Value(pos)); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ arg = new (Z) PushArgumentInstr(new (Z) Value(left)); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ arg = new (Z) |
+ PushArgumentInstr(new (Z) Value(flow_graph()->GetConstant(type))); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ arg = new (Z) PushArgumentInstr(new (Z) Value(left_cid)); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ arg = new (Z) PushArgumentInstr(new (Z) Value(cid)); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ |
+ const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary()); |
+ const String& target_name = Symbols::_classIdEqualsAssert(); |
+ const Function& target = Function::ZoneHandle( |
+ Z, dart_internal.LookupFunctionAllowPrivate(target_name)); |
+ ASSERT(!target.IsNull()); |
+ ASSERT(target.IsRecognized()); |
+ ASSERT(target.always_inline()); |
+ |
+ StaticCallInstr* new_call = |
+ new (Z) StaticCallInstr(call->token_pos(), target, |
+ Object::null_array(), // argument_names |
+ args, call->deopt_id()); |
+ Environment* copy = |
+ call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount()); |
+ for (intptr_t i = 0; i < args->length(); ++i) { |
+ copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); |
+ } |
+ call->RemoveEnvironment(); |
+ ReplaceCall(call, new_call); |
+ copy->DeepCopyTo(Z, new_call); |
siva
2017/04/13 17:01:04
Maybe not for this CL but in a follow up CL, this
|
+ return; |
+ } |
+ |
+ if (precompiler_ != NULL) { |
+ TypeRangeCache* cache = precompiler_->type_range_cache(); |
+ intptr_t lower_limit, upper_limit; |
+ if (cache != NULL && |
+ cache->InstanceOfHasClassRange(type, &lower_limit, &upper_limit)) { |
+ // left.instanceof(type) => |
+ // _classRangeCheck(left.cid, lower_limit, upper_limit) |
+ |
+ LoadClassIdInstr* left_cid = |
+ new (Z) LoadClassIdInstr(new (Z) Value(left)); |
+ InsertBefore(call, left_cid, NULL, FlowGraph::kValue); |
+ ConstantInstr* lower_cid = |
+ flow_graph()->GetConstant(Smi::ZoneHandle(Z, Smi::New(lower_limit))); |
+ ConstantInstr* upper_cid = |
+ flow_graph()->GetConstant(Smi::ZoneHandle(Z, Smi::New(upper_limit))); |
+ ConstantInstr* pos = flow_graph()->GetConstant( |
+ Smi::ZoneHandle(Z, Smi::New(call->token_pos().Pos()))); |
+ |
+ ZoneGrowableArray<PushArgumentInstr*>* args = |
+ new (Z) ZoneGrowableArray<PushArgumentInstr*>(6); |
+ PushArgumentInstr* arg = new (Z) PushArgumentInstr(new (Z) Value(pos)); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ arg = new (Z) PushArgumentInstr(new (Z) Value(left)); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ arg = new (Z) |
+ PushArgumentInstr(new (Z) Value(flow_graph()->GetConstant(type))); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ arg = new (Z) PushArgumentInstr(new (Z) Value(left_cid)); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ arg = new (Z) PushArgumentInstr(new (Z) Value(lower_cid)); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ arg = new (Z) PushArgumentInstr(new (Z) Value(upper_cid)); |
+ InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
+ args->Add(arg); |
+ |
+ const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary()); |
+ const String& target_name = Symbols::_classRangeAssert(); |
+ const Function& target = Function::ZoneHandle( |
+ Z, dart_internal.LookupFunctionAllowPrivate(target_name)); |
+ ASSERT(!target.IsNull()); |
+ ASSERT(target.IsRecognized()); |
+ ASSERT(target.always_inline()); |
+ |
+ StaticCallInstr* new_call = |
+ new (Z) StaticCallInstr(call->token_pos(), target, |
+ Object::null_array(), // argument_names |
+ args, call->deopt_id()); |
+ Environment* copy = call->env()->DeepCopy( |
+ Z, call->env()->Length() - call->ArgumentCount()); |
+ for (intptr_t i = 0; i < args->length(); ++i) { |
+ copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); |
+ } |
+ call->RemoveEnvironment(); |
+ ReplaceCall(call, new_call); |
+ copy->DeepCopyTo(Z, new_call); |
+ return; |
+ } |
+ } |
+ |
const ICData& unary_checks = |
ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |