| Index: runtime/vm/class_finalizer.cc
|
| ===================================================================
|
| --- runtime/vm/class_finalizer.cc (revision 11197)
|
| +++ runtime/vm/class_finalizer.cc (working copy)
|
| @@ -14,11 +14,11 @@
|
|
|
| namespace dart {
|
|
|
| +DEFINE_FLAG(bool, error_on_malformed_type, false,
|
| + "Report error for malformed types.");
|
| DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
|
| DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
|
| DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
|
| -DEFINE_FLAG(bool, verify_implements, false,
|
| - "Verify that all classes implement their interface.");
|
| DECLARE_FLAG(bool, enable_type_checks);
|
|
|
|
|
| @@ -33,7 +33,7 @@
|
| // Class finalization occurs:
|
| // a) when bootstrap process completes (VerifyBootstrapClasses).
|
| // b) after the user classes are loaded (dart_api).
|
| -bool ClassFinalizer::FinalizePendingClasses(bool generating_snapshot) {
|
| +bool ClassFinalizer::FinalizePendingClasses() {
|
| bool retval = true;
|
| Isolate* isolate = Isolate::Current();
|
| ASSERT(isolate != NULL);
|
| @@ -42,13 +42,16 @@
|
| if (!error.IsNull()) {
|
| return false;
|
| }
|
| + GrowableObjectArray& class_array = GrowableObjectArray::Handle();
|
| + class_array = object_store->pending_classes();
|
| + ASSERT(!class_array.IsNull());
|
| + if (class_array.Length() == 0) {
|
| + return true;
|
| + }
|
| LongJump* base = isolate->long_jump_base();
|
| LongJump jump;
|
| isolate->set_long_jump_base(&jump);
|
| if (setjmp(*jump.Set()) == 0) {
|
| - GrowableObjectArray& class_array = GrowableObjectArray::Handle();
|
| - class_array = object_store->pending_classes();
|
| - ASSERT(!class_array.IsNull());
|
| Class& cls = Class::Handle();
|
| // First resolve all superclasses.
|
| for (intptr_t i = 0; i < class_array.Length(); i++) {
|
| @@ -64,7 +67,7 @@
|
| // Finalize all classes.
|
| for (intptr_t i = 0; i < class_array.Length(); i++) {
|
| cls ^= class_array.At(i);
|
| - FinalizeClass(cls, generating_snapshot);
|
| + FinalizeClass(cls);
|
| }
|
| if (FLAG_print_classes) {
|
| for (intptr_t i = 0; i < class_array.Length(); i++) {
|
| @@ -72,14 +75,6 @@
|
| PrintClassInformation(cls);
|
| }
|
| }
|
| - if (FLAG_verify_implements) {
|
| - for (intptr_t i = 0; i < class_array.Length(); i++) {
|
| - cls ^= class_array.At(i);
|
| - if (!cls.is_interface()) {
|
| - VerifyClassImplements(cls);
|
| - }
|
| - }
|
| - }
|
| // Clear pending classes array.
|
| class_array = GrowableObjectArray::New();
|
| object_store->set_pending_classes(class_array);
|
| @@ -107,78 +102,6 @@
|
| }
|
|
|
|
|
| -#if defined (DEBUG)
|
| -// Collect all interfaces of the class 'cls' and check that every function
|
| -// defined in each interface can be found in the class.
|
| -// No need to check instance fields since they have been turned into
|
| -// getters/setters.
|
| -void ClassFinalizer::VerifyClassImplements(const Class& cls) {
|
| - ASSERT(!cls.is_interface());
|
| - const GrowableObjectArray& interfaces =
|
| - GrowableObjectArray::Handle(GrowableObjectArray::New());
|
| - CollectInterfaces(cls, interfaces);
|
| - const String& class_name = String::Handle(cls.Name());
|
| - Class& interface_class = Class::Handle();
|
| - String& interface_name = String::Handle();
|
| - Array& interface_functions = Array::Handle();
|
| - for (int i = 0; i < interfaces.Length(); i++) {
|
| - interface_class ^= interfaces.At(i);
|
| - interface_name = interface_class.Name();
|
| - interface_functions = interface_class.functions();
|
| - for (intptr_t f = 0; f < interface_functions.Length(); f++) {
|
| - Function& interface_function = Function::Handle();
|
| - interface_function ^= interface_functions.At(f);
|
| - const String& function_name = String::Handle(interface_function.name());
|
| - // Check for constructor/factory.
|
| - if (function_name.StartsWith(interface_name)) {
|
| - // TODO(srdjan): convert 'InterfaceName.' to 'ClassName.' and check.
|
| - continue;
|
| - }
|
| - if (interface_function.kind() == RawFunction::kConstImplicitGetter) {
|
| - // This interface constants are not overridable.
|
| - continue;
|
| - }
|
| - // Lookup function in 'cls' and all its super classes.
|
| - Class& test_class = Class::Handle(cls.raw());
|
| - Function& class_function =
|
| - Function::Handle(test_class.LookupDynamicFunction(function_name));
|
| - while (class_function.IsNull()) {
|
| - test_class = test_class.SuperClass();
|
| - if (test_class.IsNull()) break;
|
| - class_function = test_class.LookupDynamicFunction(function_name);
|
| - }
|
| - if (class_function.IsNull()) {
|
| - OS::PrintErr("%s implements '%s' missing: '%s'\n",
|
| - class_name.ToCString(),
|
| - interface_name.ToCString(),
|
| - function_name.ToCString());
|
| - } else {
|
| - Error& malformed_error = Error::Handle();
|
| - if (!class_function.IsSubtypeOf(TypeArguments::Handle(),
|
| - interface_function,
|
| - TypeArguments::Handle(),
|
| - &malformed_error)) {
|
| - if (!malformed_error.IsNull()) {
|
| - OS::PrintErr("%s\n", malformed_error.ToErrorCString());
|
| - }
|
| - OS::PrintErr("The type of instance method '%s' in class '%s' is not "
|
| - "a subtype of the type of '%s' in interface '%s'\n",
|
| - function_name.ToCString(),
|
| - class_name.ToCString(),
|
| - function_name.ToCString(),
|
| - interface_name.ToCString());
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -#else
|
| -
|
| -void ClassFinalizer::VerifyClassImplements(const Class& cls) {}
|
| -
|
| -#endif
|
| -
|
| -
|
| void ClassFinalizer::VerifyBootstrapClasses() {
|
| if (FLAG_trace_class_finalization) {
|
| OS::Print("VerifyBootstrapClasses START.\n");
|
| @@ -678,7 +601,7 @@
|
| if (type_argument.IsMalformed()) {
|
| // In production mode, malformed type arguments are mapped to Dynamic.
|
| // In checked mode, a type with malformed type arguments is malformed.
|
| - if (FLAG_enable_type_checks) {
|
| + if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) {
|
| const Error& error = Error::Handle(type_argument.malformed_error());
|
| const String& type_name =
|
| String::Handle(parameterized_type.UserVisibleName());
|
| @@ -813,7 +736,7 @@
|
| } else {
|
| // This type is a function type alias. Its class may need to be finalized
|
| // and checked for illegal self reference.
|
| - FinalizeClass(type_class, false);
|
| + FinalizeClass(type_class);
|
| // Finalizing the signature function here (as in the canonical case above)
|
| // would not mark the canonical signature type as finalized.
|
| const Type& signature_type = Type::Handle(type_class.SignatureType());
|
| @@ -1079,7 +1002,7 @@
|
| }
|
|
|
|
|
| -void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) {
|
| +void ClassFinalizer::FinalizeClass(const Class& cls) {
|
| if (cls.is_finalized()) {
|
| return;
|
| }
|
| @@ -1098,7 +1021,7 @@
|
| // Finalize super class.
|
| const Class& super_class = Class::Handle(cls.SuperClass());
|
| if (!super_class.IsNull()) {
|
| - FinalizeClass(super_class, generating_snapshot);
|
| + FinalizeClass(super_class);
|
| }
|
| // Finalize type parameters before finalizing the super type.
|
| FinalizeTypeParameters(cls);
|
| @@ -1132,7 +1055,7 @@
|
| if (cls.HasFactoryClass()) {
|
| const Class& factory_class = Class::Handle(cls.FactoryClass());
|
| if (!factory_class.is_finalized()) {
|
| - FinalizeClass(factory_class, generating_snapshot);
|
| + FinalizeClass(factory_class);
|
| // Finalizing the factory class may indirectly finalize this interface.
|
| if (cls.is_finalized()) {
|
| return;
|
| @@ -1159,7 +1082,7 @@
|
| }
|
| // Check to ensure we don't have classes with native fields in libraries
|
| // which do not have a native resolver.
|
| - if (!generating_snapshot && cls.num_native_fields() != 0) {
|
| + if (cls.num_native_fields() != 0) {
|
| const Library& lib = Library::Handle(cls.library());
|
| if (lib.native_entry_resolver() == NULL) {
|
| const String& cls_name = String::Handle(cls.Name());
|
| @@ -1254,36 +1177,6 @@
|
| }
|
|
|
|
|
| -bool ClassFinalizer::AddInterfaceIfUnique(
|
| - const GrowableObjectArray& interface_list,
|
| - const AbstractType& interface,
|
| - AbstractType* conflicting) {
|
| - String& interface_class_name = String::Handle(interface.ClassName());
|
| - String& existing_interface_class_name = String::Handle();
|
| - String& interface_name = String::Handle();
|
| - String& existing_interface_name = String::Handle();
|
| - AbstractType& other_interface = AbstractType::Handle();
|
| - for (intptr_t i = 0; i < interface_list.Length(); i++) {
|
| - other_interface ^= interface_list.At(i);
|
| - existing_interface_class_name = other_interface.ClassName();
|
| - if (interface_class_name.Equals(existing_interface_class_name)) {
|
| - // Same interface class name, now check names of type arguments.
|
| - interface_name = interface.Name();
|
| - existing_interface_name = other_interface.Name();
|
| - // TODO(regis): Revisit depending on the outcome of issue 4905685.
|
| - if (!interface_name.Equals(existing_interface_name)) {
|
| - *conflicting = other_interface.raw();
|
| - return false;
|
| - } else {
|
| - return true;
|
| - }
|
| - }
|
| - }
|
| - interface_list.Add(interface);
|
| - return true;
|
| -}
|
| -
|
| -
|
| // Walks the graph of explicitly declared interfaces of classes and
|
| // interfaces recursively. Resolves unresolved interfaces.
|
| // Returns false if there is an interface reference that cannot be
|
| @@ -1454,7 +1347,8 @@
|
| LanguageError& error = LanguageError::Handle();
|
| if (FLAG_enable_type_checks ||
|
| !type.HasResolvedTypeClass() ||
|
| - (finalization == kCanonicalizeWellFormed)) {
|
| + (finalization == kCanonicalizeWellFormed) ||
|
| + FLAG_error_on_malformed_type) {
|
| const Script& script = Script::Handle(cls.script());
|
| if (prev_error.IsNull()) {
|
| error ^= Parser::FormatError(
|
| @@ -1463,7 +1357,8 @@
|
| error ^= Parser::FormatErrorWithAppend(
|
| prev_error, script, type.token_pos(), "Error", format, args);
|
| }
|
| - if (finalization == kCanonicalizeWellFormed) {
|
| + if ((finalization == kCanonicalizeWellFormed) ||
|
| + FLAG_error_on_malformed_type) {
|
| ReportError(error);
|
| }
|
| }
|
|
|