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

Unified Diff: runtime/vm/object.cc

Issue 26955002: Overlap type arguments of a type with the type arguments of its super type (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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/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 28492)
+++ runtime/vm/object.cc (working copy)
@@ -48,6 +48,9 @@
"Huge method cutoff in unoptimized code size (in bytes).");
DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000,
"Huge method cutoff in tokens: Disables optimizations for huge methods.");
+DEFINE_FLAG(bool, overlap_type_arguments, true,
+ "When possible, partially or fully overlap the type arguments of a type "
+ "with the type arguments of its super type.");
DEFINE_FLAG(bool, show_internal_names, false,
"Show names of internal classes (e.g. \"OneByteString\") in error messages "
"instead of showing the corresponding interface names (e.g. \"String\")");
@@ -1704,17 +1707,79 @@
}
+intptr_t Class::NumOwnTypeArguments() const {
hausner 2013/10/11 18:00:58 As discussed offline, it may be worth it to cache
regis 2013/10/11 18:36:09 Yes, it is worth doing (in another change).
+ Isolate* isolate = Isolate::Current();
+ const intptr_t num_type_params = NumTypeParameters();
+ if (!FLAG_overlap_type_arguments ||
+ (num_type_params == 0) ||
+ (super_type() == AbstractType::null()) ||
+ (super_type() == isolate->object_store()->object_type())) {
+ return num_type_params;
+ }
+ ASSERT(!IsMixinApplication() || is_mixin_type_applied());
+ const AbstractType& sup_type = AbstractType::Handle(isolate, super_type());
+ ASSERT(sup_type.IsResolved());
+ const AbstractTypeArguments& sup_type_args =
+ AbstractTypeArguments::Handle(isolate, sup_type.arguments());
+ if (sup_type_args.IsNull()) {
+ // The super type is raw or the super class is non generic.
+ // In either case, overlapping is not possible.
+ return num_type_params;
+ }
+ const intptr_t num_sup_type_args = sup_type_args.Length();
+ // At this point, the super type may or may not be finalized. In either case,
+ // the result of this function must remain the same.
+ // The value of num_sup_type_args may increase when the super type is
+ // finalized, but the last num_sup_type_args type arguments will not be
+ // modified by finalization, only shifted to higher indices in the vector.
+ // They may however get wrapped in a BoundedType, which we skip.
+ const AbstractTypeArguments& type_params =
+ AbstractTypeArguments::Handle(isolate, type_parameters());
+ // Determine the maximum overlap of a prefix of the vector consisting of the
+ // type parameters of this class with a suffix of the vector consisting of the
+ // type arguments of the super type of this class.
+ // The number of own type arguments of this class is the number of its type
+ // parameters minus the number of type arguments in the overlap.
+ // Attempt to overlap the whole vector of type parameters; reduce the size
+ // of the vector (keeping the first type parameter) until it fits or until
+ // its size is zero.
+ TypeParameter& type_param = TypeParameter::Handle(isolate);
+ AbstractType& sup_type_arg = AbstractType::Handle(isolate);
+ for (intptr_t num_overlapping_type_args =
+ (num_type_params < num_sup_type_args) ?
+ num_type_params : num_sup_type_args;
+ num_overlapping_type_args > 0; num_overlapping_type_args--) {
+ intptr_t i = 0;
+ for (; i < num_overlapping_type_args; i++) {
+ type_param ^= type_params.TypeAt(i);
+ sup_type_arg = sup_type_args.TypeAt(
+ num_sup_type_args - num_overlapping_type_args + i);
+ // BoundedType can nest in case the finalized super type has bounded type
+ // arguments that overlap multiple times in its own super class chain.
+ while (sup_type_arg.IsBoundedType()) {
+ sup_type_arg = BoundedType::Cast(sup_type_arg).type();
+ }
+ if (!type_param.Equals(sup_type_arg)) break;
+ }
+ if (i == num_overlapping_type_args) {
+ // Overlap found.
+ return num_type_params - num_overlapping_type_args;
+ }
+ }
+ // No overlap found.
+ return num_type_params;
+}
+
+
intptr_t Class::NumTypeArguments() const {
// To work properly, this call requires the super class of this class to be
// resolved, which is checked by the type_class() call on the super type.
// Note that calling type_class() on a MixinAppType fails.
Isolate* isolate = Isolate::Current();
Class& cls = Class::Handle(isolate);
- TypeArguments& type_params = TypeArguments::Handle(isolate);
AbstractType& sup_type = AbstractType::Handle(isolate);
cls = raw();
intptr_t num_type_args = 0;
-
do {
if (cls.IsSignatureClass()) {
Function& signature_fun = Function::Handle(isolate);
@@ -1724,15 +1789,12 @@
cls = signature_fun.Owner();
}
}
- // Calling NumTypeParameters() on a mixin application class will setup the
+ // Calling NumOwnTypeArguments() on a mixin application class will setup the
// type parameters if not already done.
- if (cls.NumTypeParameters() > 0) {
- type_params ^= cls.type_parameters();
- num_type_args += type_params.Length();
- }
+ num_type_args += cls.NumOwnTypeArguments();
// Super type of Object class is null.
- if (cls.super_type() == AbstractType::null() ||
- cls.super_type() == isolate->object_store()->object_type()) {
+ if ((cls.super_type() == AbstractType::null()) ||
+ (cls.super_type() == isolate->object_store()->object_type())) {
break;
}
sup_type = cls.super_type();
@@ -3399,25 +3461,39 @@
}
+// Return true if this uninstantiated type argument vector, once instantiated
+// at runtime, is a prefix of the type argument vector of its instantiator.
bool TypeArguments::CanShareInstantiatorTypeArguments(
const Class& instantiator_class) const {
ASSERT(!IsInstantiated());
+ const intptr_t num_type_args = Length();
const intptr_t num_instantiator_type_args =
instantiator_class.NumTypeArguments();
+ if (num_type_args > num_instantiator_type_args) {
+ // This vector cannot be a prefix of a shorter vector.
+ return false;
+ }
const intptr_t num_instantiator_type_params =
instantiator_class.NumTypeParameters();
- const intptr_t num_super_instantiator_type_args =
+ const intptr_t first_type_param_offset =
num_instantiator_type_args - num_instantiator_type_params;
- const intptr_t num_type_args = Length();
- // As a first requirement in order to share the instantiator type argument
- // vector, this type argument vector must refer to the type parameters of the
- // instantiator class in declaration order. It does not need to contain all
- // type parameters.
- if (num_type_args < num_super_instantiator_type_args) {
- return false;
- }
+ // At compile time, the type argument vector of the instantiator consists of
+ // the type argument vector of its super type, which may refer to the type
+ // parameters of the instantiator class, followed by (or overlapping partially
+ // or fully with) the type parameters of the instantiator class in declaration
+ // order.
+ // In other words, the only variables are the type parameters of the
+ // instantiator class.
+ // This uninstantiated type argument vector is also expressed in terms of the
+ // type parameters of the instantiator class. Therefore, in order to be a
+ // prefix once instantiated at runtime, every one of its type argument must be
+ // equal to the type argument of the instantiator vector at the same index.
+
+ // As a first requirement, the last num_instantiator_type_params type
+ // arguments of this type argument vector must refer to the corresponding type
+ // parameters of the instantiator class.
AbstractType& type_arg = AbstractType::Handle();
- for (intptr_t i = num_super_instantiator_type_args; i < num_type_args; i++) {
+ for (intptr_t i = first_type_param_offset; i < num_type_args; i++) {
type_arg = TypeAt(i);
if (!type_arg.IsTypeParameter()) {
return false;
@@ -3429,8 +3505,9 @@
}
}
// As a second requirement, the type arguments corresponding to the super type
- // must be identical.
- if (num_super_instantiator_type_args == 0) {
+ // must be identical. Overlapping ones have already been checked starting at
+ // first_type_param_offset.
+ if (first_type_param_offset == 0) {
return true;
}
AbstractType& super_type = AbstractType::Handle(
@@ -3441,7 +3518,8 @@
return false;
}
AbstractType& super_type_arg = AbstractType::Handle();
- for (intptr_t i = 0; i < num_super_instantiator_type_args; i++) {
+ for (intptr_t i = 0;
+ (i < first_type_param_offset) && (i < num_type_args); i++) {
type_arg = TypeAt(i);
super_type_arg = super_type_args.TypeAt(i);
if (!type_arg.Equals(super_type_arg)) {
@@ -11627,17 +11705,13 @@
return false;
}
const TypeParameter& other_type_param = TypeParameter::Cast(other);
- ASSERT(other_type_param.IsFinalized());
if (parameterized_class() != other_type_param.parameterized_class()) {
return false;
}
- if (IsFinalized() != other_type_param.IsFinalized()) {
- return false;
+ if (IsFinalized() == other_type_param.IsFinalized()) {
+ return index() == other_type_param.index();
}
- if (index() != other_type_param.index()) {
- return false;
- }
- return true;
+ return String::Handle(name()).Equals(String::Handle(other_type_param.name()));
hausner 2013/10/11 18:00:58 Can't you just compare raw pointers here? The name
regis 2013/10/11 18:36:09 Done.
}
« 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