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

Unified Diff: runtime/vm/object.cc

Issue 10578018: Fix type test elimination using static type propagation in new compiler. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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/object.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 8867)
+++ runtime/vm/object.cc (working copy)
@@ -1739,23 +1739,29 @@
}
-// Checks if the type S is a subtype of type T.
+// If test_kind == kIsSubtypeOf, checks if type S is a subtype of type T.
+// If test_kind == kIsMoreSpecificThan, checks if S is more specific than T.
// Type S is specified by this class parameterized with 'type_arguments', and
// type T by class 'other' parameterized with 'other_type_arguments'.
// This class and class 'other' do not need to be finalized, however, they must
// be resolved as well as their interfaces.
-bool Class::IsSubtypeOf(
+bool Class::TypeTest(
+ TypeTestKind test_kind,
const AbstractTypeArguments& type_arguments,
const Class& other,
const AbstractTypeArguments& other_type_arguments,
Error* malformed_error) const {
// Check for DynamicType.
- // The DynamicType on the lefthand side is replaced by the bottom type, which
- // is more specific than any type.
- // Any type is more specific than the DynamicType on the righthand side.
- if (IsDynamicClass() || other.IsDynamicClass()) {
+ // Each occurrence of DynamicType in type T is interpreted as the Dynamic
+ // type, a supertype of all types.
+ if (other.IsDynamicClass()) {
return true;
}
+ // In the case of a subtype test, each occurrence of DynamicType in type S is
+ // interpreted as the bottom type, a subtype of all types.
+ if (IsDynamicClass()) {
+ return test_kind == kIsSubtypeOf;
+ }
// Check for reflexivity.
if (raw() == other.raw()) {
const intptr_t len = NumTypeArguments();
@@ -1765,16 +1771,21 @@
// Since we do not truncate the type argument vector of a subclass (see
// below), we only check a prefix of the proper length.
// Check for covariance.
- if (type_arguments.IsNull() ||
- other_type_arguments.IsNull() ||
- type_arguments.IsRawInstantiatedRaw(len) ||
+ if (other_type_arguments.IsNull() ||
other_type_arguments.IsRawInstantiatedRaw(len)) {
return true;
}
- return type_arguments.IsSubtypeOf(other_type_arguments,
- len,
- malformed_error);
+ if (type_arguments.IsNull() ||
+ type_arguments.IsRawInstantiatedRaw(len)) {
+ return test_kind == kIsSubtypeOf;
+ }
+ return type_arguments.TypeTest(test_kind,
+ other_type_arguments,
+ len,
+ malformed_error);
}
+ // TODO(regis): Check for interface type S implementing method call() of
+ // function type T.
// Check for two function types.
if (IsSignatureClass() && other.IsSignatureClass()) {
const Function& fun = Function::Handle(signature_function());
@@ -1820,10 +1831,11 @@
}
}
}
- if (interface_class.IsSubtypeOf(interface_args,
- other,
- other_type_arguments,
- malformed_error)) {
+ if (interface_class.TypeTest(test_kind,
+ interface_args,
+ other,
+ other_type_arguments,
+ malformed_error)) {
return true;
}
}
@@ -1843,10 +1855,11 @@
// Instead of truncating the type argument vector to the length of the super
// type argument vector, we make sure that the code works with a vector that
// is longer than necessary.
- return super_class.IsSubtypeOf(type_arguments,
- other,
- other_type_arguments,
- malformed_error);
+ return super_class.TypeTest(test_kind,
+ type_arguments,
+ other,
+ other_type_arguments,
+ malformed_error);
}
@@ -2403,8 +2416,9 @@
}
-bool AbstractType::IsSubtypeOf(const AbstractType& other,
- Error* malformed_error) const {
+bool AbstractType::TypeTest(TypeTestKind test_kind,
+ const AbstractType& other,
+ Error* malformed_error) const {
ASSERT(IsFinalized());
ASSERT(other.IsFinalized());
// In case the type checked in a type test is malformed, the code generator
@@ -2426,7 +2440,7 @@
}
return false;
}
- // AbstractType parameters cannot be handled by Class::IsSubtypeOf().
+ // AbstractType parameters cannot be handled by Class::TypeTest().
// When comparing two uninstantiated function types, one returning type
// parameter K, the other returning type parameter V, we cannot assume that K
// is a subtype of V, or vice versa. We only return true if K == V, i.e. if
@@ -2438,15 +2452,25 @@
// For example, with class A<K, V extends K>, new A<T, T> called from within
// a class B<T> will never require a run time bounds check, even it T is
// uninstantiated at compile time.
- if (IsTypeParameter() || other.IsTypeParameter()) {
- return IsTypeParameter() && other.IsTypeParameter() &&
- (Index() == other.Index());
+ if (IsTypeParameter()) {
+ if (other.IsTypeParameter()) {
+ return Index() == other.Index();
+ } else {
+ // TODO(regis): In checked mode, if the other type is the upper bound of
+ // this type parameter, then return true.
+ // We would need to keep the upper bound associated to the type parameter.
+ }
+ return false;
}
+ if (other.IsTypeParameter()) {
+ return false;
+ }
const Class& cls = Class::Handle(type_class());
- return cls.IsSubtypeOf(AbstractTypeArguments::Handle(arguments()),
- Class::Handle(other.type_class()),
- AbstractTypeArguments::Handle(other.arguments()),
- malformed_error);
+ return cls.TypeTest(test_kind,
+ AbstractTypeArguments::Handle(arguments()),
+ Class::Handle(other.type_class()),
+ AbstractTypeArguments::Handle(other.arguments()),
+ malformed_error);
}
@@ -3181,10 +3205,10 @@
}
-bool AbstractTypeArguments::IsSubtypeOf(
- const AbstractTypeArguments& other,
- intptr_t len,
- Error* malformed_error) const {
+bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind,
+ const AbstractTypeArguments& other,
+ intptr_t len,
+ Error* malformed_error) const {
ASSERT(Length() >= len);
ASSERT(!other.IsNull());
ASSERT(other.Length() >= len);
@@ -3195,7 +3219,7 @@
ASSERT(!type.IsNull());
other_type = other.TypeAt(i);
ASSERT(!other_type.IsNull());
- if (!type.IsSubtypeOf(other_type, malformed_error)) {
+ if (!type.TypeTest(test_kind, other_type, malformed_error)) {
return false;
}
}
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698