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

Unified Diff: runtime/vm/class_finalizer.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/class_finalizer.h ('k') | runtime/vm/code_generator.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/class_finalizer.cc
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index e2fd349fbca1303a46ee84d65af1ed2a07b80b2d..f2c7b12c60438f26ff4deb02f15007448172df37 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -440,7 +440,7 @@ void ClassFinalizer::ResolveRedirectingFactoryTarget(
const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
Error& bound_error = Error::Handle();
target_type ^= target_type.InstantiateFrom(
- type_args, &bound_error, NULL, Heap::kOld);
+ type_args, &bound_error, NULL, NULL, Heap::kOld);
if (bound_error.IsNull()) {
target_type ^= FinalizeType(cls, target_type, kCanonicalize);
} else {
@@ -624,13 +624,14 @@ void ClassFinalizer::CheckRecursiveType(const Class& cls,
TypeArguments& pending_arguments = TypeArguments::Handle(zone);
const intptr_t num_pending_types = pending_types->length();
for (intptr_t i = num_pending_types - 1; i >= 0; i--) {
- const Type& pending_type = Type::Cast(pending_types->At(i));
+ const AbstractType& pending_type = pending_types->At(i);
if (FLAG_trace_type_finalization) {
THR_Print(" Comparing with pending type '%s': %s\n",
String::Handle(pending_type.Name()).ToCString(),
pending_type.ToCString());
}
if ((pending_type.raw() != type.raw()) &&
+ pending_type.IsType() &&
(pending_type.type_class() == type_cls.raw())) {
pending_arguments = pending_type.arguments();
if (!pending_arguments.IsSubvectorEquivalent(arguments,
@@ -741,10 +742,10 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
}
}
if (offset > 0) {
- TrailPtr trail = new Trail(Z, 4);
- Error& bound_error = Error::Handle();
+ TrailPtr instantiation_trail = new Trail(Z, 4);
+ Error& bound_error = Error::Handle(Z);
FinalizeTypeArguments(type_class, full_arguments, offset,
- &bound_error, pending_types, trail);
+ &bound_error, pending_types, instantiation_trail);
}
if (full_arguments.IsRaw(0, num_type_arguments)) {
// The parameterized_type is raw. Set its argument vector to null, which
@@ -761,6 +762,11 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
if (!type.IsFinalized()) {
ASSERT(full_arguments.IsNull() ||
!full_arguments.IsRaw(0, num_type_arguments));
+ if (FLAG_trace_type_finalization) {
+ THR_Print("Marking type '%s' as finalized for class '%s'\n",
+ String::Handle(Z, type.Name()).ToCString(),
+ String::Handle(Z, cls.Name()).ToCString());
+ }
// Mark the type as finalized.
type.SetIsFinalized();
// Do not yet remove the type from the pending_types array.
@@ -808,7 +814,7 @@ void ClassFinalizer::FinalizeTypeArguments(
intptr_t num_uninitialized_arguments,
Error* bound_error,
PendingTypes* pending_types,
- TrailPtr trail) {
+ TrailPtr instantiation_trail) {
ASSERT(arguments.Length() >= cls.NumTypeArguments());
if (!cls.is_type_finalized()) {
FinalizeTypeParameters(cls, pending_types);
@@ -868,7 +874,7 @@ void ClassFinalizer::FinalizeTypeArguments(
}
Error& error = Error::Handle();
super_type_arg = super_type_arg.InstantiateFrom(
- arguments, &error, trail, Heap::kOld);
+ arguments, &error, instantiation_trail, NULL, Heap::kOld);
if (!error.IsNull()) {
// InstantiateFrom does not report an error if the type is still
// uninstantiated. Instead, it will return a new BoundedType so
@@ -895,7 +901,7 @@ void ClassFinalizer::FinalizeTypeArguments(
cls.NumTypeArguments() - cls.NumTypeParameters(),
bound_error,
pending_types,
- trail);
+ instantiation_trail);
Type::Cast(super_type_arg).SetIsFinalized();
}
}
@@ -903,7 +909,7 @@ void ClassFinalizer::FinalizeTypeArguments(
arguments.SetTypeAt(i, super_type_arg);
}
FinalizeTypeArguments(super_class, arguments, super_offset,
- bound_error, pending_types, trail);
+ bound_error, pending_types, instantiation_trail);
}
}
@@ -918,7 +924,7 @@ void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
Error* bound_error) {
if (!cls.is_type_finalized()) {
FinalizeTypeParameters(cls);
- FinalizeUpperBounds(cls);
+ FinalizeUpperBounds(cls, kFinalize); // No canonicalization yet.
}
// Note that when finalizing a type, we need to verify the bounds in both
// production mode and checked mode, because the finalized type may be written
@@ -970,8 +976,8 @@ void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
if (declared_bound.IsInstantiated()) {
instantiated_bound = declared_bound.raw();
} else {
- instantiated_bound =
- declared_bound.InstantiateFrom(arguments, &error, NULL, Heap::kOld);
+ instantiated_bound = declared_bound.InstantiateFrom(
+ arguments, &error, NULL, NULL, Heap::kOld);
}
if (!instantiated_bound.IsFinalized()) {
// The bound refers to type parameters, creating a cycle; postpone
@@ -1001,7 +1007,8 @@ void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
// This may be called only if type needs to be finalized, therefore
// seems OK to allocate finalized types in old space.
if (!type_param.CheckBound(type_arg, instantiated_bound,
- &error, Heap::kOld) && error.IsNull()) {
+ &error, NULL, Heap::kOld) &&
+ error.IsNull()) {
// The bound cannot be checked at compile time; postpone to run time.
type_arg = BoundedType::New(type_arg, instantiated_bound, type_param);
arguments.SetTypeAt(offset + i, type_arg);
@@ -1022,32 +1029,47 @@ void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
void ClassFinalizer::CheckTypeBounds(const Class& cls,
const AbstractType& type) {
+ Zone* Z = Thread::Current()->zone();
ASSERT(type.IsType() || type.IsFunctionType());
ASSERT(type.IsFinalized());
- TypeArguments& arguments = TypeArguments::Handle(type.arguments());
+ ASSERT(!type.IsCanonical());
+ TypeArguments& arguments = TypeArguments::Handle(Z, type.arguments());
if (arguments.IsNull()) {
return;
}
- const Class& type_class = Class::Handle(type.type_class());
- Error& bound_error = Error::Handle();
+ if (FLAG_trace_type_finalization) {
+ THR_Print("Checking bounds of type '%s' for class '%s'\n",
+ String::Handle(Z, type.Name()).ToCString(),
+ String::Handle(Z, cls.Name()).ToCString());
+ }
+ const Class& type_class = Class::Handle(Z, type.type_class());
+ Error& bound_error = Error::Handle(Z);
CheckTypeArgumentBounds(type_class, arguments, &bound_error);
- type.set_arguments(arguments);
- // If a bound error occurred, mark the type as malbounded.
- // The bound error will be ignored in production mode.
- if (!bound_error.IsNull()) {
- // No compile-time error during finalization.
- const String& type_name = String::Handle(type.UserVisibleName());
- FinalizeMalboundedType(bound_error,
- Script::Handle(cls.script()),
- type,
- "type '%s' has an out of bound type argument",
- type_name.ToCString());
- if (FLAG_trace_type_finalization) {
- THR_Print("Marking type '%s' as malbounded: %s\n",
- String::Handle(type.Name()).ToCString(),
- bound_error.ToCString());
+ // CheckTypeArgumentBounds may have indirectly canonicalized this type.
+ if (!type.IsCanonical()) {
+ type.set_arguments(arguments);
+ // If a bound error occurred, mark the type as malbounded.
+ // The bound error will be ignored in production mode.
+ if (!bound_error.IsNull()) {
+ // No compile-time error during finalization.
+ const String& type_name = String::Handle(Z, type.UserVisibleName());
+ FinalizeMalboundedType(bound_error,
+ Script::Handle(Z, cls.script()),
+ type,
+ "type '%s' has an out of bound type argument",
+ type_name.ToCString());
+ if (FLAG_trace_type_finalization) {
+ THR_Print("Marking type '%s' as malbounded: %s\n",
+ String::Handle(Z, type.Name()).ToCString(),
+ bound_error.ToCString());
+ }
}
}
+ if (FLAG_trace_type_finalization) {
+ THR_Print("Done checking bounds of type '%s': %s\n",
+ String::Handle(Z, type.Name()).ToCString(),
+ type.ToCString());
+ }
}
@@ -1062,7 +1084,11 @@ RawAbstractType* ClassFinalizer::FinalizeType(
if (type.IsFinalized()) {
// Ensure type is canonical if canonicalization is requested, unless type is
// malformed.
- if ((finalization >= kCanonicalize) && !type.IsMalformed()) {
+ if ((finalization >= kCanonicalize) &&
+ !type.IsMalformed() &&
+ !type.IsCanonical() &&
+ (type.IsType() || type.IsFunctionType())) {
+ CheckTypeBounds(cls, type);
return type.Canonicalize();
}
return type.raw();
@@ -1091,7 +1117,7 @@ RawAbstractType* ClassFinalizer::FinalizeType(
if (FLAG_trace_type_finalization) {
THR_Print("Finalizing type '%s' for class '%s'\n",
String::Handle(Z, resolved_type.Name()).ToCString(),
- cls.ToCString());
+ String::Handle(Z, cls.Name()).ToCString());
}
if (resolved_type.IsTypeParameter()) {
@@ -1142,11 +1168,9 @@ RawAbstractType* ClassFinalizer::FinalizeType(
// bounds.
if (is_root_type) {
for (intptr_t i = pending_types->length() - 1; i >= 0; i--) {
- CheckTypeBounds(cls, pending_types->At(i));
- if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) {
- THR_Print("Done finalizing recursive type '%s': %s\n",
- String::Handle(Z, resolved_type.Name()).ToCString(),
- resolved_type.ToCString());
+ const AbstractType& type = pending_types->At(i);
+ if (!type.IsMalformed() && !type.IsCanonical()) {
+ CheckTypeBounds(cls, type);
}
}
}
@@ -1178,13 +1202,14 @@ RawAbstractType* ClassFinalizer::FinalizeType(
}
if (finalization >= kCanonicalize) {
- if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) {
- AbstractType& recursive_type =
+ if (FLAG_trace_type_finalization) {
+ THR_Print("Canonicalizing type '%s'\n",
+ String::Handle(Z, resolved_type.Name()).ToCString());
+ AbstractType& canonical_type =
AbstractType::Handle(Z, resolved_type.Canonicalize());
- THR_Print("Done canonicalizing recursive type '%s': %s\n",
- String::Handle(Z, recursive_type.Name()).ToCString(),
- recursive_type.ToCString());
- return recursive_type.raw();
+ THR_Print("Done canonicalizing type '%s'\n",
+ String::Handle(Z, canonical_type.Name()).ToCString());
+ return canonical_type.raw();
}
return resolved_type.Canonicalize();
} else {
@@ -1308,7 +1333,8 @@ void ClassFinalizer::ResolveUpperBounds(const Class& cls) {
// Finalize the upper bounds of the type parameters of class cls.
-void ClassFinalizer::FinalizeUpperBounds(const Class& cls) {
+void ClassFinalizer::FinalizeUpperBounds(const Class& cls,
+ FinalizationKind finalization) {
const intptr_t num_type_params = cls.NumTypeParameters();
TypeParameter& type_param = TypeParameter::Handle();
AbstractType& bound = AbstractType::Handle();
@@ -1324,7 +1350,7 @@ void ClassFinalizer::FinalizeUpperBounds(const Class& cls) {
// A bound involved in F-bounded quantification may form a cycle.
continue;
}
- bound = FinalizeType(cls, bound, kCanonicalize);
+ bound = FinalizeType(cls, bound, finalization);
type_param.set_bound(bound);
}
}
@@ -1766,7 +1792,7 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
param.set_bound(param_bound); // In case part of recursive type.
}
param_bound = param_bound.InstantiateFrom(
- instantiator, &bound_error, NULL, Heap::kOld);
+ instantiator, &bound_error, NULL, NULL, Heap::kOld);
// The instantiator contains only TypeParameter objects and no
// BoundedType objects, so no bound error may occur.
ASSERT(!param_bound.IsBoundedType());
@@ -2000,20 +2026,20 @@ void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class,
if (type.IsBoundedType()) {
bounded_type = BoundedType::Cast(type).type();
bounded_type = bounded_type.InstantiateFrom(
- instantiator, &bound_error, NULL, Heap::kOld);
+ instantiator, &bound_error, NULL, NULL, Heap::kOld);
// The instantiator contains only TypeParameter objects and no
// BoundedType objects, so no bound error may occur.
ASSERT(bound_error.IsNull());
upper_bound = BoundedType::Cast(type).bound();
upper_bound = upper_bound.InstantiateFrom(
- instantiator, &bound_error, NULL, Heap::kOld);
+ instantiator, &bound_error, NULL, NULL, Heap::kOld);
ASSERT(bound_error.IsNull());
type_parameter = BoundedType::Cast(type).type_parameter();
// The type parameter that declared the bound does not change.
type = BoundedType::New(bounded_type, upper_bound, type_parameter);
} else {
type = type.InstantiateFrom(
- instantiator, &bound_error, NULL, Heap::kOld);
+ instantiator, &bound_error, NULL, NULL, Heap::kOld);
ASSERT(bound_error.IsNull());
}
}
@@ -2312,7 +2338,7 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
// unfinalized bounds. It is more efficient to finalize them early.
// Finalize bounds even if running in production mode, so that a snapshot
// contains them.
- FinalizeUpperBounds(cls);
+ FinalizeUpperBounds(cls, kCanonicalizeWellFormed);
// Finalize super type.
AbstractType& super_type = AbstractType::Handle(cls.super_type());
if (!super_type.IsNull()) {
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/code_generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698