Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
| 6 | 6 |
| 7 #include "vm/code_generator.h" | 7 #include "vm/code_generator.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
| 10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 } | 82 } |
| 83 finalized_super_classes->Add(cid); | 83 finalized_super_classes->Add(cid); |
| 84 const AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 84 const AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
| 85 AddSuperType(super_type, finalized_super_classes); | 85 AddSuperType(super_type, finalized_super_classes); |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 // Use array instead of set since we expect very few subclassed classes | 89 // Use array instead of set since we expect very few subclassed classes |
| 90 // to occur. | 90 // to occur. |
| 91 static void CollectFinalizedSuperClasses( | 91 static void CollectFinalizedSuperClasses( |
| 92 const GrowableObjectArray& pending_classes, | 92 const Class& cls_, GrowableArray<intptr_t>* finalized_super_classes) { |
| 93 GrowableArray<intptr_t>* finalized_super_classes) { | 93 Class& cls = Class::Handle(cls_.raw()); |
| 94 Class& cls = Class::Handle(); | |
| 95 AbstractType& super_type = Type::Handle(); | 94 AbstractType& super_type = Type::Handle(); |
| 96 for (intptr_t i = 0; i < pending_classes.Length(); i++) { | 95 super_type = cls.super_type(); |
| 97 cls ^= pending_classes.At(i); | 96 if (!super_type.IsNull()) { |
| 98 ASSERT(!cls.is_finalized()); | 97 if (!super_type.IsMalformed() && super_type.HasResolvedTypeClass()) { |
| 99 super_type = cls.super_type(); | 98 cls ^= super_type.type_class(); |
| 100 if (!super_type.IsNull()) { | 99 if (cls.is_finalized()) { |
| 101 if (!super_type.IsMalformed() && super_type.HasResolvedTypeClass()) { | 100 AddSuperType(super_type, finalized_super_classes); |
| 102 cls ^= super_type.type_class(); | |
| 103 if (cls.is_finalized()) { | |
| 104 AddSuperType(super_type, finalized_super_classes); | |
| 105 } | |
| 106 } | 101 } |
| 107 } | 102 } |
| 108 } | 103 } |
| 109 } | 104 } |
| 110 | 105 |
| 111 | 106 |
| 112 // Class finalization occurs: | 107 // Class finalization occurs: |
| 113 // a) when bootstrap process completes (VerifyBootstrapClasses). | 108 // a) when bootstrap process completes (VerifyBootstrapClasses). |
| 114 // b) after the user classes are loaded (dart_api). | 109 // b) after the user classes are loaded (dart_api). |
| 115 bool ClassFinalizer::FinalizePendingClasses() { | 110 bool ClassFinalizer::FinalizePendingClassInterfaces() { |
|
Ivan Posva
2013/11/21 23:04:09
This is not finalizing the class's interface. Actu
srdjan
2013/11/22 00:08:14
Renaming to FinalizeTypeHierarchy
| |
| 116 bool retval = true; | 111 bool retval = true; |
| 117 Isolate* isolate = Isolate::Current(); | 112 Isolate* isolate = Isolate::Current(); |
| 118 ASSERT(isolate != NULL); | 113 ASSERT(isolate != NULL); |
| 119 HANDLESCOPE(isolate); | 114 HANDLESCOPE(isolate); |
| 120 ObjectStore* object_store = isolate->object_store(); | 115 ObjectStore* object_store = isolate->object_store(); |
| 121 const Error& error = Error::Handle(isolate, object_store->sticky_error()); | 116 const Error& error = Error::Handle(isolate, object_store->sticky_error()); |
| 122 if (!error.IsNull()) { | 117 if (!error.IsNull()) { |
| 123 return false; | 118 return false; |
| 124 } | 119 } |
| 125 if (AllClassesFinalized()) { | 120 if (AllClassesFinalized()) { |
| 126 return true; | 121 return true; |
| 127 } | 122 } |
| 128 | 123 |
| 129 GrowableArray<intptr_t> added_subclasses_to_cids; | |
| 130 LongJump* base = isolate->long_jump_base(); | 124 LongJump* base = isolate->long_jump_base(); |
| 131 LongJump jump; | 125 LongJump jump; |
| 132 isolate->set_long_jump_base(&jump); | 126 isolate->set_long_jump_base(&jump); |
| 133 if (setjmp(*jump.Set()) == 0) { | 127 if (setjmp(*jump.Set()) == 0) { |
| 134 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); | 128 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); |
| 135 class_array = object_store->pending_classes(); | 129 class_array = object_store->pending_classes(); |
| 136 ASSERT(!class_array.IsNull()); | 130 ASSERT(!class_array.IsNull()); |
| 137 // Collect superclasses that were already finalized before this run of | |
| 138 // finalization. | |
| 139 CollectFinalizedSuperClasses(class_array, &added_subclasses_to_cids); | |
| 140 Class& cls = Class::Handle(); | 131 Class& cls = Class::Handle(); |
| 141 // First resolve all superclasses. | 132 // First resolve all superclasses. |
| 142 for (intptr_t i = 0; i < class_array.Length(); i++) { | 133 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 143 cls ^= class_array.At(i); | 134 cls ^= class_array.At(i); |
| 144 GrowableArray<intptr_t> visited_interfaces; | 135 GrowableArray<intptr_t> visited_interfaces; |
| 145 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); | 136 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); |
| 146 } | 137 } |
| 147 // Finalize all classes. | 138 // Finalize all classes. |
| 148 for (intptr_t i = 0; i < class_array.Length(); i++) { | 139 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 149 cls ^= class_array.At(i); | 140 cls ^= class_array.At(i); |
| 150 FinalizeTypesInClass(cls); | 141 FinalizeTypesInClass(cls); |
| 151 } | 142 } |
| 152 if (FLAG_print_classes) { | 143 if (FLAG_print_classes) { |
| 153 for (intptr_t i = 0; i < class_array.Length(); i++) { | 144 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 154 cls ^= class_array.At(i); | 145 cls ^= class_array.At(i); |
| 155 PrintClassInformation(cls); | 146 PrintClassInformation(cls); |
| 156 } | 147 } |
| 157 } | 148 } |
| 158 // Clear pending classes array. | 149 // Clear pending classes array. |
| 159 class_array = GrowableObjectArray::New(); | 150 class_array = GrowableObjectArray::New(); |
| 160 object_store->set_pending_classes(class_array); | 151 object_store->set_pending_classes(class_array); |
| 161 VerifyImplicitFieldOffsets(); // Verification after an error may fail. | 152 VerifyImplicitFieldOffsets(); // Verification after an error may fail. |
| 162 } else { | 153 } else { |
| 163 retval = false; | 154 retval = false; |
| 164 } | 155 } |
| 165 isolate->set_long_jump_base(base); | 156 isolate->set_long_jump_base(base); |
| 166 if (FLAG_use_cha) { | |
| 167 RemoveOptimizedCode(added_subclasses_to_cids); | |
| 168 } | |
| 169 return retval; | 157 return retval; |
| 170 } | 158 } |
| 171 | 159 |
| 172 | 160 |
| 173 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. | 161 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. |
| 174 // No cycles are allowed. | 162 // No cycles are allowed. |
| 175 void ClassFinalizer::CollectInterfaces(const Class& cls, | 163 void ClassFinalizer::CollectInterfaces(const Class& cls, |
| 176 const GrowableObjectArray& collected) { | 164 const GrowableObjectArray& collected) { |
| 177 const Array& interface_array = Array::Handle(cls.interfaces()); | 165 const Array& interface_array = Array::Handle(cls.interfaces()); |
| 178 AbstractType& interface = AbstractType::Handle(); | 166 AbstractType& interface = AbstractType::Handle(); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 for (intptr_t i = 0; i < class_array.Length(); i++) { | 219 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 232 // TODO(iposva): Add real checks. | 220 // TODO(iposva): Add real checks. |
| 233 cls ^= class_array.At(i); | 221 cls ^= class_array.At(i); |
| 234 if (cls.is_finalized() || cls.is_prefinalized()) { | 222 if (cls.is_finalized() || cls.is_prefinalized()) { |
| 235 // Pre-finalized bootstrap classes must not define any fields. | 223 // Pre-finalized bootstrap classes must not define any fields. |
| 236 ASSERT(!cls.HasInstanceFields()); | 224 ASSERT(!cls.HasInstanceFields()); |
| 237 } | 225 } |
| 238 } | 226 } |
| 239 | 227 |
| 240 // Finalize classes that aren't pre-finalized by Object::Init(). | 228 // Finalize classes that aren't pre-finalized by Object::Init(). |
| 241 if (!FinalizePendingClasses()) { | 229 if (!FinalizePendingClassInterfaces()) { |
| 242 // TODO(srdjan): Exit like a real VM instead. | 230 // TODO(srdjan): Exit like a real VM instead. |
| 243 const Error& err = Error::Handle(object_store->sticky_error()); | 231 const Error& err = Error::Handle(object_store->sticky_error()); |
| 244 OS::PrintErr("Could not verify bootstrap classes : %s\n", | 232 OS::PrintErr("Could not verify bootstrap classes : %s\n", |
| 245 err.ToErrorCString()); | 233 err.ToErrorCString()); |
| 246 OS::Exit(255); | 234 OS::Exit(255); |
| 247 } | 235 } |
| 248 if (FLAG_trace_class_finalization) { | 236 if (FLAG_trace_class_finalization) { |
| 249 OS::Print("VerifyBootstrapClasses END.\n"); | 237 OS::Print("VerifyBootstrapClasses END.\n"); |
| 250 } | 238 } |
| 251 Isolate::Current()->heap()->Verify(); | 239 Isolate::Current()->heap()->Verify(); |
| (...skipping 1795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2047 } | 2035 } |
| 2048 if (FLAG_trace_class_finalization) { | 2036 if (FLAG_trace_class_finalization) { |
| 2049 OS::Print("Finalize %s\n", cls.ToCString()); | 2037 OS::Print("Finalize %s\n", cls.ToCString()); |
| 2050 } | 2038 } |
| 2051 if (cls.IsMixinApplication()) { | 2039 if (cls.IsMixinApplication()) { |
| 2052 // Copy instance methods and fields from the mixin class. | 2040 // Copy instance methods and fields from the mixin class. |
| 2053 // This has to happen before the check whether the methods of | 2041 // This has to happen before the check whether the methods of |
| 2054 // the class conflict with inherited methods. | 2042 // the class conflict with inherited methods. |
| 2055 ApplyMixinMembers(cls); | 2043 ApplyMixinMembers(cls); |
| 2056 } | 2044 } |
| 2045 GrowableArray<intptr_t> added_subclasses_to_cids; | |
| 2046 CollectFinalizedSuperClasses(cls, &added_subclasses_to_cids); | |
| 2057 // Ensure super class is finalized. | 2047 // Ensure super class is finalized. |
| 2058 const Class& super = Class::Handle(cls.SuperClass()); | 2048 const Class& super = Class::Handle(cls.SuperClass()); |
| 2059 if (!super.IsNull()) { | 2049 if (!super.IsNull()) { |
| 2060 FinalizeClass(super); | 2050 FinalizeClass(super); |
| 2061 } | 2051 } |
| 2062 // Mark as parsed and finalized. | 2052 // Mark as parsed and finalized. |
| 2063 cls.Finalize(); | 2053 cls.Finalize(); |
| 2064 // Mixin app alias classes may still lack their forwarding constructor. | 2054 // Mixin app alias classes may still lack their forwarding constructor. |
| 2065 if (cls.is_mixin_app_alias() && | 2055 if (cls.is_mixin_app_alias() && |
| 2066 (cls.functions() == Object::empty_array().raw())) { | 2056 (cls.functions() == Object::empty_array().raw())) { |
| 2067 const GrowableObjectArray& cloned_funcs = | 2057 const GrowableObjectArray& cloned_funcs = |
| 2068 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 2058 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 2069 CreateForwardingConstructors(cls, cloned_funcs); | 2059 CreateForwardingConstructors(cls, cloned_funcs); |
| 2070 const Array& functions = Array::Handle(Array::MakeArray(cloned_funcs)); | 2060 const Array& functions = Array::Handle(Array::MakeArray(cloned_funcs)); |
| 2071 cls.SetFunctions(functions); | 2061 cls.SetFunctions(functions); |
| 2072 } | 2062 } |
| 2073 // Every class should have at least a constructor, unless it is a top level | 2063 // Every class should have at least a constructor, unless it is a top level |
| 2074 // class or a signature class. | 2064 // class or a signature class. |
| 2075 ASSERT(cls.IsTopLevel() || | 2065 ASSERT(cls.IsTopLevel() || |
| 2076 cls.IsSignatureClass() || | 2066 cls.IsSignatureClass() || |
| 2077 (Array::Handle(cls.functions()).Length() > 0)); | 2067 (Array::Handle(cls.functions()).Length() > 0)); |
| 2078 // Resolve and finalize all member types. | 2068 // Resolve and finalize all member types. |
| 2079 ResolveAndFinalizeMemberTypes(cls); | 2069 ResolveAndFinalizeMemberTypes(cls); |
| 2080 // Run additional checks after all types are finalized. | 2070 // Run additional checks after all types are finalized. |
| 2081 if (cls.is_const()) { | 2071 if (cls.is_const()) { |
| 2082 CheckForLegalConstClass(cls); | 2072 CheckForLegalConstClass(cls); |
| 2083 } | 2073 } |
| 2074 if (FLAG_use_cha) { | |
| 2075 RemoveOptimizedCode(added_subclasses_to_cids); | |
|
Ivan Posva
2013/11/21 23:04:09
This will add Object to the list, but Object never
srdjan
2013/11/22 00:08:14
Modified CollectFinalizedSuperClasses to exclude o
| |
| 2076 } | |
| 2084 } | 2077 } |
| 2085 | 2078 |
| 2086 | 2079 |
| 2087 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { | 2080 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { |
| 2088 Class& test1 = Class::Handle(cls.raw()); | 2081 Class& test1 = Class::Handle(cls.raw()); |
| 2089 Class& test2 = Class::Handle(cls.SuperClass()); | 2082 Class& test2 = Class::Handle(cls.SuperClass()); |
| 2090 // A finalized class has been checked for cycles. | 2083 // A finalized class has been checked for cycles. |
| 2091 // Using the hare and tortoise algorithm for locating cycles. | 2084 // Using the hare and tortoise algorithm for locating cycles. |
| 2092 while (!test1.is_type_finalized() && | 2085 while (!test1.is_type_finalized() && |
| 2093 !test2.IsNull() && !test2.is_type_finalized()) { | 2086 !test2.IsNull() && !test2.is_type_finalized()) { |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2761 expected_name ^= String::New("_offset"); | 2754 expected_name ^= String::New("_offset"); |
| 2762 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2755 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 2763 field ^= fields_array.At(2); | 2756 field ^= fields_array.At(2); |
| 2764 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2757 ASSERT(field.Offset() == TypedDataView::length_offset()); |
| 2765 name ^= field.name(); | 2758 name ^= field.name(); |
| 2766 ASSERT(name.Equals("length")); | 2759 ASSERT(name.Equals("length")); |
| 2767 #endif | 2760 #endif |
| 2768 } | 2761 } |
| 2769 | 2762 |
| 2770 } // namespace dart | 2763 } // namespace dart |
| OLD | NEW |