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

Unified Diff: runtime/vm/object.cc

Issue 2755723003: Make sure the signature of the call method is finalized before involving it (Closed)
Patch Set: Created 3 years, 9 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 6e3b4e9aa88b65a67e5db69527538e832836a4cf..0214fd9b87a2217fc8b7c5746a6189a67a4df9cc 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1996,8 +1996,7 @@ bool Class::IsInFullSnapshot() const {
RawAbstractType* Class::RareType() const {
const Type& type = Type::Handle(Type::New(
*this, Object::null_type_arguments(), TokenPosition::kNoSource));
- return ClassFinalizer::FinalizeType(*this, type,
- ClassFinalizer::kCanonicalize);
+ return ClassFinalizer::FinalizeType(*this, type);
}
@@ -2005,8 +2004,7 @@ RawAbstractType* Class::DeclarationType() const {
const TypeArguments& args = TypeArguments::Handle(type_parameters());
const Type& type =
Type::Handle(Type::New(*this, args, TokenPosition::kNoSource));
- return ClassFinalizer::FinalizeType(*this, type,
- ClassFinalizer::kCanonicalize);
+ return ClassFinalizer::FinalizeType(*this, type);
}
@@ -3834,17 +3832,9 @@ bool Class::TypeTestNonRecursive(const Class& cls,
}
if (other.IsDartFunctionClass()) {
// Check if type S has a call() method.
- Function& function = Function::Handle(
- zone, thsi.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
- if (function.IsNull()) {
- // Walk up the super_class chain.
- Class& cls = Class::Handle(zone, thsi.SuperClass());
- while (!cls.IsNull() && function.IsNull()) {
- function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
- cls = cls.SuperClass();
- }
- }
- if (!function.IsNull()) {
+ const Function& call_function =
+ Function::Handle(zone, thsi.LookupCallFunctionForTypeTest());
+ if (!call_function.IsNull()) {
return true;
}
}
@@ -3866,8 +3856,7 @@ bool Class::TypeTestNonRecursive(const Class& cls,
// runtime if this type test returns false at compile time.
continue;
}
- ClassFinalizer::FinalizeType(thsi, interface,
- ClassFinalizer::kCanonicalize);
+ ClassFinalizer::FinalizeType(thsi, interface);
interfaces.SetAt(i, interface);
}
if (interface.IsMalbounded()) {
@@ -4002,6 +3991,32 @@ RawFunction* Class::LookupFunctionAllowPrivate(const String& name) const {
}
+RawFunction* Class::LookupCallFunctionForTypeTest() const {
+ // If this class is not compiled yet, it is too early to lookup a call
+ // function. This case should only occur during bounds checking at compile
+ // time. Return null as if the call method did not exist, so the type test
+ // may return false, but without a bound error, and the bound check will get
+ // postponed to runtime.
+ if (!is_finalized()) {
+ return Function::null();
+ }
+ Zone* zone = Thread::Current()->zone();
+ Class& cls = Class::Handle(zone, raw());
+ Function& call_function = Function::Handle(zone);
+ do {
+ ASSERT(cls.is_finalized());
+ call_function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
+ cls = cls.SuperClass();
+ } while (call_function.IsNull() && !cls.IsNull());
+ if (!call_function.IsNull()) {
+ // Make sure the signature is finalized before using it in a type test.
+ ClassFinalizer::FinalizeSignature(
+ cls, call_function, ClassFinalizer::kFinalize); // No bounds checking.
+ }
+ return call_function.raw();
+}
+
+
// Returns true if 'prefix' and 'accessor_name' match 'name'.
static bool MatchesAccessorName(const String& name,
const char* prefix,
@@ -6797,8 +6812,7 @@ RawFunction* Function::ImplicitClosureFunction() const {
const Type& signature_type = Type::Handle(closure_function.SignatureType());
if (!signature_type.IsFinalized()) {
- ClassFinalizer::FinalizeType(Class::Handle(Owner()), signature_type,
- ClassFinalizer::kCanonicalize);
+ ClassFinalizer::FinalizeType(Class::Handle(Owner()), signature_type);
}
set_implicit_closure_function(closure_function);
ASSERT(closure_function.IsImplicitClosureFunction());
@@ -15762,24 +15776,17 @@ bool Instance::IsInstanceOf(const AbstractType& other,
const bool other_is_dart_function = instantiated_other.IsDartFunctionType();
if (other_is_dart_function || instantiated_other.IsFunctionType()) {
// Check if this instance understands a call() method of a compatible type.
- Function& call = Function::Handle(
- zone, cls.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
- if (call.IsNull()) {
- // Walk up the super_class chain.
- Class& super_cls = Class::Handle(zone, cls.SuperClass());
- while (!super_cls.IsNull() && call.IsNull()) {
- call = super_cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
- super_cls = super_cls.SuperClass();
- }
- }
- if (!call.IsNull()) {
+ const Function& call_function =
+ Function::Handle(zone, cls.LookupCallFunctionForTypeTest());
+ if (!call_function.IsNull()) {
if (other_is_dart_function) {
return true;
}
const Function& other_signature =
Function::Handle(zone, Type::Cast(instantiated_other).signature());
- if (call.IsSubtypeOf(type_arguments, other_signature,
- other_type_arguments, bound_error, Heap::kOld)) {
+ if (call_function.IsSubtypeOf(type_arguments, other_signature,
+ other_type_arguments, bound_error,
+ Heap::kOld)) {
return true;
}
}
@@ -16581,19 +16588,11 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
TypeArguments::Handle(zone, other.arguments()), bound_error, space);
}
// Check if type S has a call() method of function type T.
- Function& function = Function::Handle(
- zone, type_cls.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
- if (function.IsNull()) {
- // Walk up the super_class chain.
- Class& cls = Class::Handle(zone, type_cls.SuperClass());
- while (!cls.IsNull() && function.IsNull()) {
- function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
- cls = cls.SuperClass();
- }
- }
- if (!function.IsNull()) {
+ const Function& call_function =
+ Function::Handle(zone, type_cls.LookupCallFunctionForTypeTest());
+ if (!call_function.IsNull()) {
if (other_is_dart_function_type ||
- function.TypeTest(
+ call_function.TypeTest(
test_kind, TypeArguments::Handle(zone, arguments()),
Function::Handle(zone, Type::Cast(other).signature()),
TypeArguments::Handle(zone, other.arguments()), bound_error,
@@ -16884,7 +16883,8 @@ bool Type::IsInstantiated(TrailPtr trail) const {
const Class& cls = Class::Handle(type_class());
len = cls.NumTypeParameters(); // Check the type parameters only.
}
- return (len == 0) || args.IsSubvectorInstantiated(num_type_args - len, len);
+ return (len == 0) ||
+ args.IsSubvectorInstantiated(num_type_args - len, len, trail);
}
@@ -17864,6 +17864,15 @@ bool TypeParameter::CheckBound(const AbstractType& bounded_type,
// Report the bound error only if both the bounded type and the upper bound
// are instantiated. Otherwise, we cannot tell yet it is a bound error.
if (bounded_type.IsInstantiated() && upper_bound.IsInstantiated()) {
+ // There is another special case where we do not want to report a bound
+ // error yet: if the upper bound is a function type, but the bounded type
+ // is not and its class is not compiled yet, i.e. we cannot look for
+ // a call method yet.
+ if (!bounded_type.IsFunctionType() && upper_bound.IsFunctionType() &&
+ bounded_type.HasResolvedTypeClass() &&
+ !Class::Handle(bounded_type.type_class()).is_finalized()) {
+ return false; // Not a subtype yet, but no bound error yet.
+ }
const String& bounded_type_name =
String::Handle(bounded_type.UserVisibleName());
const String& upper_bound_name =
« 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