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

Unified Diff: runtime/vm/object.cc

Issue 1674383002: Keep a trail while checking upper bounds in the VM in order to properly handle (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: address comments Created 4 years, 10 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') | runtime/vm/parser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ed737215e2b5f2c70108357d1470eab41711ddde..e6ec51a35d1dcbe05f6a0b2c7fa983aecbfe8fdc 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3615,6 +3615,7 @@ bool Class::TypeTestNonRecursive(const Class& cls,
const Class& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
+ TrailPtr bound_trail,
Heap::Space space) {
// Use the thsi object as if it was the receiver of this method, but instead
// of recursing reset it to the super class and loop.
@@ -3673,6 +3674,7 @@ bool Class::TypeTestNonRecursive(const Class& cls,
from_index,
num_type_params,
bound_error,
+ bound_trail,
space);
}
if (other.IsFunctionClass()) {
@@ -3733,7 +3735,11 @@ bool Class::TypeTestNonRecursive(const Class& cls,
// The index of the type parameters is adjusted upon finalization.
error = Error::null();
interface_args =
- interface_args.InstantiateFrom(type_arguments, &error, NULL, space);
+ interface_args.InstantiateFrom(type_arguments,
+ &error,
+ NULL,
+ bound_trail,
+ space);
if (!error.IsNull()) {
// Return the first bound error to the caller if it requests it.
if ((bound_error != NULL) && bound_error->IsNull()) {
@@ -3747,6 +3753,7 @@ bool Class::TypeTestNonRecursive(const Class& cls,
other,
other_type_arguments,
bound_error,
+ bound_trail,
space)) {
return true;
}
@@ -3773,6 +3780,7 @@ bool Class::TypeTest(TypeTestKind test_kind,
const Class& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
+ TrailPtr bound_trail,
Heap::Space space) const {
return TypeTestNonRecursive(*this,
test_kind,
@@ -3780,6 +3788,7 @@ bool Class::TypeTest(TypeTestKind test_kind,
other,
other_type_arguments,
bound_error,
+ bound_trail,
space);
}
@@ -4289,6 +4298,7 @@ bool TypeArguments::TypeTest(TypeTestKind test_kind,
intptr_t from_index,
intptr_t len,
Error* bound_error,
+ TrailPtr bound_trail,
Heap::Space space) const {
ASSERT(Length() >= (from_index + len));
ASSERT(!other.IsNull());
@@ -4300,7 +4310,11 @@ bool TypeArguments::TypeTest(TypeTestKind test_kind,
ASSERT(!type.IsNull());
other_type = other.TypeAt(from_index + i);
ASSERT(!other_type.IsNull());
- if (!type.TypeTest(test_kind, other_type, bound_error, space)) {
+ if (!type.TypeTest(test_kind,
+ other_type,
+ bound_error,
+ bound_trail,
+ space)) {
return false;
}
}
@@ -4350,6 +4364,7 @@ RawAbstractType* TypeArguments::TypeAt(intptr_t index) const {
void TypeArguments::SetTypeAt(intptr_t index,
const AbstractType& value) const {
+ ASSERT(!IsCanonical());
StorePointer(TypeAddr(index), value.raw());
}
@@ -4527,7 +4542,8 @@ bool TypeArguments::IsBounded() const {
RawTypeArguments* TypeArguments::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail,
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
Heap::Space space) const {
ASSERT(!IsInstantiated());
if (!instantiator_type_arguments.IsNull() &&
@@ -4550,7 +4566,8 @@ RawTypeArguments* TypeArguments::InstantiateFrom(
if (!type.IsNull() && !type.IsInstantiated()) {
type = type.InstantiateFrom(instantiator_type_arguments,
bound_error,
- trail,
+ instantiation_trail,
+ bound_trail,
space);
}
instantiated_array.SetTypeAt(i, type);
@@ -4584,7 +4601,7 @@ RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
// Cache lookup failed. Instantiate the type arguments.
TypeArguments& result = TypeArguments::Handle();
result = InstantiateFrom(
- instantiator_type_arguments, bound_error, NULL, Heap::kOld);
+ instantiator_type_arguments, bound_error, NULL, NULL, Heap::kOld);
if ((bound_error != NULL) && !bound_error->IsNull()) {
return result.raw();
}
@@ -4815,6 +4832,11 @@ RawTypeArguments* TypeArguments::Canonicalize(TrailPtr trail) const {
for (intptr_t i = 0; i < num_types; i++) {
type_arg = TypeAt(i);
type_arg = type_arg.Canonicalize(trail);
+ if (IsCanonical()) {
+ // Canonicalizing this type_arg canonicalized this type.
+ ASSERT(IsRecursive());
+ return this->raw();
+ }
SetTypeAt(i, type_arg);
}
// Canonicalization of a recursive type may change its hash.
@@ -5927,10 +5949,12 @@ bool Function::TestParameterType(
AbstractType& other_param_type =
AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
if (!other_param_type.IsInstantiated()) {
- other_param_type = other_param_type.InstantiateFrom(other_type_arguments,
- bound_error,
- NULL, // trail
- space);
+ other_param_type =
+ other_param_type.InstantiateFrom(other_type_arguments,
+ bound_error,
+ NULL, // instantiation_trail
+ NULL, // bound_trail
+ space);
ASSERT((bound_error == NULL) || bound_error->IsNull());
}
if (other_param_type.IsDynamicType()) {
@@ -5939,21 +5963,25 @@ bool Function::TestParameterType(
AbstractType& param_type =
AbstractType::Handle(ParameterTypeAt(parameter_position));
if (!param_type.IsInstantiated()) {
- param_type = param_type.InstantiateFrom(
- type_arguments, bound_error, NULL /*trail*/, space);
+ param_type = param_type.InstantiateFrom(type_arguments,
+ bound_error,
+ NULL, // instantiation_trail
+ NULL, // bound_trail
+ space);
ASSERT((bound_error == NULL) || bound_error->IsNull());
}
if (param_type.IsDynamicType()) {
return test_kind == kIsSubtypeOf;
}
if (test_kind == kIsSubtypeOf) {
- if (!param_type.IsSubtypeOf(other_param_type, bound_error, space) &&
- !other_param_type.IsSubtypeOf(param_type, bound_error, space)) {
+ if (!param_type.IsSubtypeOf(other_param_type, bound_error, NULL, space) &&
+ !other_param_type.IsSubtypeOf(param_type, bound_error, NULL, space)) {
return false;
}
} else {
ASSERT(test_kind == kIsMoreSpecificThan);
- if (!param_type.IsMoreSpecificThan(other_param_type, bound_error, space)) {
+ if (!param_type.IsMoreSpecificThan(
+ other_param_type, bound_error, NULL, space)) {
return false;
}
}
@@ -6376,7 +6404,9 @@ void Function::BuildSignatureParameters(
while (i < num_fixed_params) {
param_type = ParameterTypeAt(i);
ASSERT(!param_type.IsNull());
- if (instantiate && !param_type.IsInstantiated()) {
+ if (instantiate &&
+ param_type.IsFinalized() &&
+ !param_type.IsInstantiated()) {
param_type = param_type.InstantiateFrom(instantiator, NULL);
}
name = param_type.BuildName(name_visibility);
@@ -6401,7 +6431,9 @@ void Function::BuildSignatureParameters(
pieces->Add(Symbols::ColonSpace());
}
param_type = ParameterTypeAt(i);
- if (instantiate && !param_type.IsInstantiated()) {
+ if (instantiate &&
+ param_type.IsFinalized() &&
+ !param_type.IsInstantiated()) {
param_type = param_type.InstantiateFrom(instantiator, NULL);
}
ASSERT(!param_type.IsNull());
@@ -6499,7 +6531,7 @@ RawString* Function::BuildSignature(bool instantiate,
&pieces);
pieces.Add(Symbols::RParenArrow());
AbstractType& res_type = AbstractType::Handle(zone, result_type());
- if (instantiate && !res_type.IsInstantiated()) {
+ if (instantiate && res_type.IsFinalized() && !res_type.IsInstantiated()) {
res_type = res_type.InstantiateFrom(instantiator, NULL);
}
name = res_type.BuildName(name_visibility);
@@ -14269,7 +14301,7 @@ bool Instance::IsInstanceOf(const AbstractType& other,
}
other_class = instantiated_other.type_class();
return cls.IsSubtypeOf(type_arguments, other_class, other_type_arguments,
- bound_error, Heap::kOld);
+ bound_error, NULL, Heap::kOld);
}
@@ -14596,7 +14628,8 @@ bool AbstractType::IsRecursive() const {
RawAbstractType* AbstractType::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail,
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
Heap::Space space) const {
// AbstractType is an abstract class.
UNREACHABLE();
@@ -14656,6 +14689,47 @@ void AbstractType::AddOnlyBuddyToTrail(TrailPtr* trail,
}
+bool AbstractType::TestAndAddToTrail(TrailPtr* trail) const {
+ if (*trail == NULL) {
+ *trail = new Trail(Thread::Current()->zone(), 4);
+ } else {
+ const intptr_t len = (*trail)->length();
+ for (intptr_t i = 0; i < len; i++) {
+ if ((*trail)->At(i).raw() == this->raw()) {
+ return true;
+ }
+ }
+ }
+ (*trail)->Add(*this);
+ return false;
+}
+
+
+bool AbstractType::TestAndAddBuddyToTrail(TrailPtr* trail,
+ const AbstractType& buddy) const {
+ if (*trail == NULL) {
+ *trail = new Trail(Thread::Current()->zone(), 4);
+ } else {
+ const intptr_t len = (*trail)->length();
+ ASSERT((len % 2) == 0);
+ const bool this_is_typeref = IsTypeRef();
+ const bool buddy_is_typeref = buddy.IsTypeRef();
+ ASSERT(this_is_typeref || buddy_is_typeref);
+ for (intptr_t i = 0; i < len; i += 2) {
+ if ((((*trail)->At(i).raw() == this->raw()) ||
+ (buddy_is_typeref && (*trail)->At(i).Equals(*this))) &&
+ (((*trail)->At(i + 1).raw() == buddy.raw()) ||
+ (this_is_typeref && (*trail)->At(i + 1).Equals(buddy)))) {
+ return true;
+ }
+ }
+ }
+ (*trail)->Add(*this);
+ (*trail)->Add(buddy);
+ return false;
+}
+
+
RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
Zone* zone = Thread::Current()->zone();
if (IsBoundedType()) {
@@ -14862,6 +14936,7 @@ bool AbstractType::IsDartFunctionType() const {
bool AbstractType::TypeTest(TypeTestKind test_kind,
const AbstractType& other,
Error* bound_error,
+ TrailPtr bound_trail,
Heap::Space space) const {
ASSERT(IsFinalized());
ASSERT(other.IsFinalized());
@@ -14932,7 +15007,9 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
if (!bound.IsFinalized()) {
return false; // TODO(regis): Return "maybe after instantiation".
}
- if (bound.IsMoreSpecificThan(other, bound_error)) {
+ // The current bound_trail cannot be used, because operands are swapped and
+ // the test is different anyway (more specific vs. subtype).
+ if (bound.IsMoreSpecificThan(other, bound_error, NULL)) {
return true;
}
return false; // TODO(regis): We should return "maybe after instantiation".
@@ -14992,6 +15069,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
Class::Handle(zone, other.type_class()),
TypeArguments::Handle(zone, other.arguments()),
bound_error,
+ bound_trail,
space);
}
@@ -15236,7 +15314,8 @@ bool Type::IsInstantiated(TrailPtr trail) const {
RawAbstractType* Type::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail,
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
Heap::Space space) const {
Zone* zone = Thread::Current()->zone();
ASSERT(IsFinalized() || IsBeingFinalized());
@@ -15250,32 +15329,21 @@ RawAbstractType* Type::InstantiateFrom(
if (arguments() == instantiator_type_arguments.raw()) {
return raw();
}
- // If this type is recursive, we may already be instantiating it.
- Type& instantiated_type = Type::Handle(zone);
- instantiated_type ^= OnlyBuddyInTrail(trail);
- if (!instantiated_type.IsNull()) {
- ASSERT(IsRecursive());
- return instantiated_type.raw();
- }
// Note that the type class has to be resolved at this time, but not
// necessarily finalized yet. We may be checking bounds at compile time or
// finalizing the type argument vector of a recursive type.
const Class& cls = Class::Handle(zone, type_class());
-
- // This uninstantiated type is not modified, as it can be instantiated
- // with different instantiators. Allocate a new instantiated version of it.
- instantiated_type =
- Type::New(cls, TypeArguments::Handle(zone), token_pos(), space);
TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
ASSERT(type_arguments.Length() == cls.NumTypeArguments());
- if (type_arguments.IsRecursive()) {
- AddOnlyBuddyToTrail(&trail, instantiated_type);
- }
type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
bound_error,
- trail,
+ instantiation_trail,
+ bound_trail,
space);
- instantiated_type.set_arguments(type_arguments);
+ // This uninstantiated type is not modified, as it can be instantiated
+ // with different instantiators. Allocate a new instantiated version of it.
+ const Type& instantiated_type =
+ Type::Handle(zone, Type::New(cls, type_arguments, token_pos(), space));
if (IsFinalized()) {
instantiated_type.SetIsFinalized();
} else {
@@ -15439,6 +15507,11 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
// Canonicalize the type arguments of the supertype, if any.
TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
type_args = type_args.Canonicalize(trail);
+ if (IsCanonical()) {
+ // Canonicalizing type_args canonicalized this type.
+ ASSERT(IsRecursive());
+ return this->raw();
+ }
set_arguments(type_args);
type = cls.CanonicalType(); // May be set while canonicalizing type args.
if (type.IsNull()) {
@@ -15483,6 +15556,11 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
// vector may be longer than necessary. This is not an issue.
ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments()));
type_args = type_args.Canonicalize(trail);
+ if (IsCanonical()) {
+ // Canonicalizing type_args canonicalized this type as a side effect.
+ ASSERT(IsRecursive());
+ return this->raw();
+ }
set_arguments(type_args);
// Canonicalizing the type arguments may have changed the index, may have
@@ -15541,6 +15619,7 @@ void Type::set_type_class(const Object& value) const {
void Type::set_arguments(const TypeArguments& value) const {
+ ASSERT(!IsCanonical());
StorePointer(&raw_ptr()->arguments_, value.raw());
}
@@ -15705,7 +15784,8 @@ bool FunctionType::IsInstantiated(TrailPtr trail) const {
RawAbstractType* FunctionType::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail,
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
Heap::Space space) const {
Zone* zone = Thread::Current()->zone();
ASSERT(IsFinalized() || IsBeingFinalized());
@@ -15716,36 +15796,25 @@ RawAbstractType* FunctionType::InstantiateFrom(
if (arguments() == instantiator_type_arguments.raw()) {
return raw();
}
- // If this type is recursive, we may already be instantiating it.
- FunctionType& instantiated_type = FunctionType::Handle(zone);
- instantiated_type ^= OnlyBuddyInTrail(trail);
- if (!instantiated_type.IsNull()) {
- ASSERT(IsRecursive());
- return instantiated_type.raw();
- }
// Note that the scope class has to be resolved at this time, but not
// necessarily finalized yet. We may be checking bounds at compile time or
// finalizing the type argument vector of a recursive type.
const Class& cls = Class::Handle(zone, scope_class());
-
- // This uninstantiated type is not modified, as it can be instantiated
- // with different instantiators. Allocate a new instantiated version of it.
- instantiated_type =
- FunctionType::New(cls,
- TypeArguments::Handle(zone),
- Function::Handle(zone, signature()),
- token_pos(),
- space);
TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
ASSERT(type_arguments.Length() == cls.NumTypeArguments());
- if (type_arguments.IsRecursive()) {
- AddOnlyBuddyToTrail(&trail, instantiated_type);
- }
type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
bound_error,
- trail,
+ instantiation_trail,
+ bound_trail,
space);
- instantiated_type.set_arguments(type_arguments);
+ // This uninstantiated type is not modified, as it can be instantiated
+ // with different instantiators. Allocate a new instantiated version of it.
+ const FunctionType& instantiated_type = FunctionType::Handle(zone,
+ FunctionType::New(cls,
+ type_arguments,
+ Function::Handle(zone, signature()),
+ token_pos(),
+ space));
if (IsFinalized()) {
instantiated_type.SetIsFinalized();
} else {
@@ -15953,6 +16022,13 @@ RawAbstractType* FunctionType::Canonicalize(TrailPtr trail) const {
ASSERT(type_args.IsNull() ||
(type_args.Length() >= scope_cls.NumTypeArguments()));
type_args = type_args.Canonicalize(trail);
+ if (IsCanonical()) {
+ // Canonicalizing type_args canonicalized this type as a side effect.
+ ASSERT(IsRecursive());
+ // Cycles via typedefs are detected and disallowed, but a function type can
+ // be recursive due to a cycle in its type arguments.
+ return this->raw();
+ }
set_arguments(type_args);
// Replace the actual function by a signature function.
@@ -16050,6 +16126,7 @@ void FunctionType::set_scope_class(const Class& value) const {
void FunctionType::set_arguments(const TypeArguments& value) const {
+ ASSERT(!IsCanonical());
StorePointer(&raw_ptr()->arguments_, value.raw());
}
@@ -16150,21 +16227,28 @@ bool TypeRef::IsEquivalent(const Instance& other, TrailPtr trail) const {
RawTypeRef* TypeRef::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail,
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
Heap::Space space) const {
TypeRef& instantiated_type_ref = TypeRef::Handle();
- instantiated_type_ref ^= OnlyBuddyInTrail(trail);
+ instantiated_type_ref ^= OnlyBuddyInTrail(instantiation_trail);
if (!instantiated_type_ref.IsNull()) {
return instantiated_type_ref.raw();
}
+ instantiated_type_ref = TypeRef::New();
+ AddOnlyBuddyToTrail(&instantiation_trail, instantiated_type_ref);
+
AbstractType& ref_type = AbstractType::Handle(type());
ASSERT(!ref_type.IsTypeRef());
AbstractType& instantiated_ref_type = AbstractType::Handle();
instantiated_ref_type = ref_type.InstantiateFrom(
- instantiator_type_arguments, bound_error, trail, space);
+ instantiator_type_arguments,
+ bound_error,
+ instantiation_trail,
+ bound_trail,
+ space);
ASSERT(!instantiated_ref_type.IsTypeRef());
- instantiated_type_ref = TypeRef::New(instantiated_ref_type);
- AddOnlyBuddyToTrail(&trail, instantiated_type_ref);
+ instantiated_type_ref.set_type(instantiated_ref_type);
return instantiated_type_ref.raw();
}
@@ -16176,13 +16260,14 @@ RawTypeRef* TypeRef::CloneUninstantiated(const Class& new_owner,
if (!cloned_type_ref.IsNull()) {
return cloned_type_ref.raw();
}
+ cloned_type_ref = TypeRef::New();
+ AddOnlyBuddyToTrail(&trail, cloned_type_ref);
AbstractType& ref_type = AbstractType::Handle(type());
ASSERT(!ref_type.IsTypeRef());
AbstractType& cloned_ref_type = AbstractType::Handle();
cloned_ref_type = ref_type.CloneUninstantiated(new_owner, trail);
ASSERT(!cloned_ref_type.IsTypeRef());
- cloned_type_ref = TypeRef::New(cloned_ref_type);
- AddOnlyBuddyToTrail(&trail, cloned_type_ref);
+ cloned_type_ref.set_type(cloned_ref_type);
return cloned_type_ref.raw();
}
@@ -16219,42 +16304,6 @@ intptr_t TypeRef::Hash() const {
}
-bool TypeRef::TestAndAddToTrail(TrailPtr* trail) const {
- if (*trail == NULL) {
- *trail = new Trail(Thread::Current()->zone(), 4);
- } else {
- const intptr_t len = (*trail)->length();
- for (intptr_t i = 0; i < len; i++) {
- if ((*trail)->At(i).raw() == this->raw()) {
- return true;
- }
- }
- }
- (*trail)->Add(*this);
- return false;
-}
-
-
-bool TypeRef::TestAndAddBuddyToTrail(TrailPtr* trail,
- const AbstractType& buddy) const {
- if (*trail == NULL) {
- *trail = new Trail(Thread::Current()->zone(), 4);
- } else {
- const intptr_t len = (*trail)->length();
- ASSERT((len % 2) == 0);
- for (intptr_t i = 0; i < len; i += 2) {
- if (((*trail)->At(i).raw() == this->raw()) &&
- ((*trail)->At(i + 1).raw() == buddy.raw())) {
- return true;
- }
- }
- }
- (*trail)->Add(*this);
- (*trail)->Add(buddy);
- return false;
-}
-
-
RawTypeRef* TypeRef::New() {
RawObject* raw = Object::Allocate(TypeRef::kClassId,
TypeRef::InstanceSize(),
@@ -16343,7 +16392,8 @@ void TypeParameter::set_bound(const AbstractType& value) const {
RawAbstractType* TypeParameter::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail,
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
Heap::Space space) const {
ASSERT(IsFinalized());
if (instantiator_type_arguments.IsNull()) {
@@ -16355,6 +16405,12 @@ RawAbstractType* TypeParameter::InstantiateFrom(
// type arguments are canonicalized at type finalization time. It would be too
// early to canonicalize the returned type argument here, since instantiation
// not only happens at run time, but also during type finalization.
+
+ // If the instantiated type parameter type_arg is a BoundedType, it means that
+ // it is still uninstantiated and that we are instantiating at finalization
+ // time (i.e. compile time).
+ // Indeed, the instantiator (type arguments of an instance) is always
+ // instantiated at run time and any bounds were checked during allocation.
return type_arg.raw();
}
@@ -16362,12 +16418,21 @@ RawAbstractType* TypeParameter::InstantiateFrom(
bool TypeParameter::CheckBound(const AbstractType& bounded_type,
const AbstractType& upper_bound,
Error* bound_error,
+ TrailPtr bound_trail,
Heap::Space space) const {
ASSERT((bound_error != NULL) && bound_error->IsNull());
ASSERT(bounded_type.IsFinalized());
ASSERT(upper_bound.IsFinalized());
ASSERT(!bounded_type.IsMalformed());
- if (bounded_type.IsSubtypeOf(upper_bound, bound_error, space)) {
+ if (bounded_type.IsTypeRef() || upper_bound.IsTypeRef()) {
+ // Shortcut the bound check if the pair <bounded_type, upper_bound> is
+ // already in the trail.
+ if (bounded_type.TestAndAddBuddyToTrail(&bound_trail, upper_bound)) {
+ return true;
+ }
+ }
+
+ if (bounded_type.IsSubtypeOf(upper_bound, bound_error, bound_trail, space)) {
return true;
}
// Set bound_error if the caller is interested and if this is the first error.
@@ -16424,18 +16489,24 @@ RawAbstractType* TypeParameter::CloneUnfinalized() const {
RawAbstractType* TypeParameter::CloneUninstantiated(
const Class& new_owner, TrailPtr trail) const {
ASSERT(IsFinalized());
- AbstractType& upper_bound = AbstractType::Handle(bound());
- upper_bound = upper_bound.CloneUninstantiated(new_owner, trail);
+ TypeParameter& clone = TypeParameter::Handle();
+ clone ^= OnlyBuddyInTrail(trail);
+ if (!clone.IsNull()) {
+ return clone.raw();
+ }
const Class& old_owner = Class::Handle(parameterized_class());
const intptr_t new_index = index() +
new_owner.NumTypeArguments() - old_owner.NumTypeArguments();
- const TypeParameter& clone = TypeParameter::Handle(
- TypeParameter::New(new_owner,
- new_index,
- String::Handle(name()),
- upper_bound,
- token_pos()));
+ AbstractType& upper_bound = AbstractType::Handle(bound());
+ clone = TypeParameter::New(new_owner,
+ new_index,
+ String::Handle(name()),
+ upper_bound, // Not cloned yet.
+ token_pos());
clone.SetIsFinalized();
+ AddOnlyBuddyToTrail(&trail, clone);
+ upper_bound = upper_bound.CloneUninstantiated(new_owner, trail);
+ clone.set_bound(upper_bound);
return clone.raw();
}
@@ -16590,18 +16661,24 @@ void BoundedType::set_type_parameter(const TypeParameter& value) const {
RawAbstractType* BoundedType::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail,
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
Heap::Space space) const {
ASSERT(IsFinalized());
AbstractType& bounded_type = AbstractType::Handle(type());
ASSERT(bounded_type.IsFinalized());
+ AbstractType& instantiated_bounded_type =
+ AbstractType::Handle(bounded_type.raw());
if (!bounded_type.IsInstantiated()) {
- bounded_type = bounded_type.InstantiateFrom(instantiator_type_arguments,
- bound_error,
- trail,
- space);
- // In case types of instantiator_type_arguments are not finalized, then
- // the instantiated bounded_type is not finalized either.
+ instantiated_bounded_type =
+ bounded_type.InstantiateFrom(instantiator_type_arguments,
+ bound_error,
+ instantiation_trail,
+ bound_trail,
+ space);
+ // In case types of instantiator_type_arguments are not finalized
+ // (or instantiated), then the instantiated_bounded_type is not finalized
+ // (or instantiated) either.
// Note that instantiator_type_arguments must have the final length, though.
}
if ((Isolate::Current()->flags().type_checks()) &&
@@ -16609,34 +16686,49 @@ RawAbstractType* BoundedType::InstantiateFrom(
AbstractType& upper_bound = AbstractType::Handle(bound());
ASSERT(upper_bound.IsFinalized());
ASSERT(!upper_bound.IsObjectType() && !upper_bound.IsDynamicType());
- const TypeParameter& type_param = TypeParameter::Handle(type_parameter());
+ AbstractType& instantiated_upper_bound =
+ AbstractType::Handle(upper_bound.raw());
if (!upper_bound.IsInstantiated()) {
- upper_bound = upper_bound.InstantiateFrom(instantiator_type_arguments,
- bound_error,
- trail,
- space);
- // Instantiated upper_bound may not be finalized. See comment above.
+ instantiated_upper_bound =
+ upper_bound.InstantiateFrom(instantiator_type_arguments,
+ bound_error,
+ instantiation_trail,
+ bound_trail,
+ space);
+ // The instantiated_upper_bound may not be finalized or instantiated.
+ // See comment above.
}
if (bound_error->IsNull()) {
- if (bounded_type.IsBeingFinalized() ||
- upper_bound.IsBeingFinalized() ||
- (!type_param.CheckBound(bounded_type, upper_bound, bound_error) &&
+ // Shortcut the F-bounded case where we have reached a fixpoint.
+ if (instantiated_bounded_type.Equals(bounded_type) &&
+ instantiated_upper_bound.Equals(upper_bound)) {
+ return bounded_type.raw();
+ }
+ const TypeParameter& type_param = TypeParameter::Handle(type_parameter());
+ if (instantiated_bounded_type.IsBeingFinalized() ||
+ instantiated_upper_bound.IsBeingFinalized() ||
+ (!type_param.CheckBound(instantiated_bounded_type,
+ instantiated_upper_bound,
+ bound_error,
+ bound_trail) &&
bound_error->IsNull())) {
// We cannot determine yet whether the bounded_type is below the
// upper_bound, because one or both of them is still being finalized or
// uninstantiated.
- ASSERT(bounded_type.IsBeingFinalized() ||
- upper_bound.IsBeingFinalized() ||
- !bounded_type.IsInstantiated() ||
- !upper_bound.IsInstantiated());
+ ASSERT(instantiated_bounded_type.IsBeingFinalized() ||
+ instantiated_upper_bound.IsBeingFinalized() ||
+ !instantiated_bounded_type.IsInstantiated() ||
+ !instantiated_upper_bound.IsInstantiated());
// Postpone bound check by returning a new BoundedType with unfinalized
// or partially instantiated bounded_type and upper_bound, but keeping
// type_param.
- bounded_type = BoundedType::New(bounded_type, upper_bound, type_param);
+ instantiated_bounded_type = BoundedType::New(instantiated_bounded_type,
+ instantiated_upper_bound,
+ type_param);
}
}
}
- return bounded_type.raw();
+ return instantiated_bounded_type.raw();
}
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698