Chromium Code Reviews| Index: runtime/vm/flow_graph_optimizer.cc |
| =================================================================== |
| --- runtime/vm/flow_graph_optimizer.cc (revision 16619) |
| +++ runtime/vm/flow_graph_optimizer.cc (working copy) |
| @@ -1249,6 +1249,41 @@ |
| } |
| +// Returns a Boolean constant if all classes in ic_data yield the same type-test |
| +// result and the type tests do not depend on type arguments. Otherwise return |
| +// Bool::null(). |
| +RawBool* FlowGraphOptimizer::InstanceOfAsBool(const ICData& ic_data, |
| + const AbstractType& type) const { |
| + ASSERT(ic_data.num_args_tested() == 1); // Unary checks only. |
| + if (!type.IsInstantiated() || type.IsMalformed()) return Bool::null(); |
| + const Class& type_class = Class::Handle(type.type_class()); |
| + if (type_class.HasTypeArguments()) return Bool::null(); |
| + const ClassTable& class_table = *Isolate::Current()->class_table(); |
| + Bool& prev = Bool::Handle(); |
| + Class& cls = Class::Handle(); |
| + for (int i = 0; i < ic_data.NumberOfChecks(); i++) { |
| + cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); |
| + if (cls.HasTypeArguments()) return Bool::null(); |
| + // TODO(regis): Fix Class::TypeTest to support NullClass. |
|
regis
2013/01/04 01:39:16
I am pretty sure that Class::TypeTest is supportin
srdjan
2013/01/04 21:10:25
Removed TODO. Discussed off-line changes to Class:
|
| + bool is_subtype = false; |
| + if (cls.IsNullClass()) { |
| + is_subtype = type_class.IsDynamicClass() || type_class.IsObjectClass(); |
| + } else { |
| + is_subtype = cls.IsSubtypeOf(TypeArguments::Handle(), |
| + type_class, |
| + TypeArguments::Handle(), |
| + NULL); |
| + } |
| + if (prev.IsNull()) { |
| + prev = is_subtype ? Bool::True() : Bool::False(); |
| + } else { |
| + if (is_subtype != prev.value()) return Bool::null(); |
| + } |
| + } |
| + return prev.raw(); |
| +} |
| + |
| + |
| // TODO(srdjan): Use ICData to check if always true or false. |
| void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
| ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
| @@ -1259,6 +1294,21 @@ |
| AbstractType::Cast(call->ArgumentAt(3)->value()->BoundConstant()); |
| const Bool& negate = |
|
Florian Schneider
2013/01/04 11:35:41
Maybe just
bool negate =
Bool::Cast(call->Argum
srdjan
2013/01/04 21:10:25
Done.
|
| Bool::Cast(call->ArgumentAt(4)->value()->BoundConstant()); |
| + const ICData& unary_checks = |
| + ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); |
| + if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
| + Bool& as_bool = Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type)); |
| + if (!as_bool.IsNull()) { |
| + AddCheckClass(call, left_val->Copy()); |
| + if (negate.value()) { |
| + as_bool = as_bool.value() ? Bool::False() : Bool::True(); |
| + } |
| + ConstantInstr* bool_const = new ConstantInstr(as_bool); |
| + call->ReplaceWith(bool_const, current_iterator()); |
| + RemovePushArguments(call); |
| + return; |
| + } |
| + } |
| InstanceOfInstr* instance_of = |
| new InstanceOfInstr(call->token_pos(), |
| left_val, |