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

Side by Side Diff: runtime/vm/class_finalizer.cc

Issue 81333003: Do not eagerly finalize classes in CHA, instead regard unfinalized classes as ’non-existent’ an… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/class_finalizer_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 19 matching lines...) Expand all
30 GrowableObjectArray::Handle(object_store->pending_classes()); 30 GrowableObjectArray::Handle(object_store->pending_classes());
31 return classes.Length() == 0; 31 return classes.Length() == 0;
32 } 32 }
33 33
34 34
35 // Removes optimized code once we load more classes, since --use_cha based 35 // Removes optimized code once we load more classes, since --use_cha based
36 // optimizations may have become invalid. 36 // optimizations may have become invalid.
37 // Only methods which owner classes where subclasses can be invalid. 37 // Only methods which owner classes where subclasses can be invalid.
38 // TODO(srdjan): Be even more precise by recording the exact CHA optimization. 38 // TODO(srdjan): Be even more precise by recording the exact CHA optimization.
39 static void RemoveOptimizedCode( 39 static void RemoveOptimizedCode(
40 const GrowableArray<intptr_t>& added_subclasses_to_cids) { 40 const GrowableArray<intptr_t>& added_subclass_to_cids) {
41 ASSERT(FLAG_use_cha); 41 ASSERT(FLAG_use_cha);
42 if (added_subclasses_to_cids.is_empty()) return; 42 if (added_subclass_to_cids.is_empty()) return;
43 // Deoptimize all live frames. 43 // Deoptimize all live frames.
44 DeoptimizeIfOwner(added_subclasses_to_cids); 44 DeoptimizeIfOwner(added_subclass_to_cids);
45 // Switch all functions' code to unoptimized. 45 // Switch all functions' code to unoptimized.
46 const ClassTable& class_table = *Isolate::Current()->class_table(); 46 const ClassTable& class_table = *Isolate::Current()->class_table();
47 Class& cls = Class::Handle(); 47 Class& cls = Class::Handle();
48 Array& array = Array::Handle(); 48 Array& array = Array::Handle();
49 Function& function = Function::Handle(); 49 Function& function = Function::Handle();
50 for (intptr_t i = 0; i < added_subclasses_to_cids.length(); i++) { 50 for (intptr_t i = 0; i < added_subclass_to_cids.length(); i++) {
51 intptr_t cid = added_subclasses_to_cids[i]; 51 intptr_t cid = added_subclass_to_cids[i];
52 cls = class_table.At(cid); 52 cls = class_table.At(cid);
53 ASSERT(!cls.IsNull()); 53 ASSERT(!cls.IsNull());
54 array = cls.functions(); 54 array = cls.functions();
55 const intptr_t num_functions = array.IsNull() ? 0 : array.Length(); 55 const intptr_t num_functions = array.IsNull() ? 0 : array.Length();
56 for (intptr_t f = 0; f < num_functions; f++) { 56 for (intptr_t f = 0; f < num_functions; f++) {
57 function ^= array.At(f); 57 function ^= array.At(f);
58 ASSERT(!function.IsNull()); 58 ASSERT(!function.IsNull());
59 if (function.HasOptimizedCode()) { 59 if (function.HasOptimizedCode()) {
60 function.SwitchToUnoptimizedCode(); 60 function.SwitchToUnoptimizedCode();
61 } 61 }
(...skipping 20 matching lines...) Expand all
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 // Type hierarchy 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::FinalizeTypeHierarchy() {
siva 2013/11/22 18:09:53 We collect all classes in a pending classes list (
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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 GrowableObjectArray::Handle(object_store->pending_classes()); 218 GrowableObjectArray::Handle(object_store->pending_classes());
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 type hierarchy for types that aren't pre-finalized
241 if (!FinalizePendingClasses()) { 229 // by Object::Init().
230 if (!FinalizeTypeHierarchy()) {
242 // TODO(srdjan): Exit like a real VM instead. 231 // TODO(srdjan): Exit like a real VM instead.
243 const Error& err = Error::Handle(object_store->sticky_error()); 232 const Error& err = Error::Handle(object_store->sticky_error());
244 OS::PrintErr("Could not verify bootstrap classes : %s\n", 233 OS::PrintErr("Could not verify bootstrap classes : %s\n",
245 err.ToErrorCString()); 234 err.ToErrorCString());
246 OS::Exit(255); 235 OS::Exit(255);
247 } 236 }
248 if (FLAG_trace_class_finalization) { 237 if (FLAG_trace_class_finalization) {
249 OS::Print("VerifyBootstrapClasses END.\n"); 238 OS::Print("VerifyBootstrapClasses END.\n");
250 } 239 }
251 Isolate::Current()->heap()->Verify(); 240 Isolate::Current()->heap()->Verify();
(...skipping 1796 matching lines...) Expand 10 before | Expand all | Expand 10 after
2048 } 2037 }
2049 if (FLAG_trace_class_finalization) { 2038 if (FLAG_trace_class_finalization) {
2050 OS::Print("Finalize %s\n", cls.ToCString()); 2039 OS::Print("Finalize %s\n", cls.ToCString());
2051 } 2040 }
2052 if (cls.IsMixinApplication()) { 2041 if (cls.IsMixinApplication()) {
2053 // Copy instance methods and fields from the mixin class. 2042 // Copy instance methods and fields from the mixin class.
2054 // This has to happen before the check whether the methods of 2043 // This has to happen before the check whether the methods of
2055 // the class conflict with inherited methods. 2044 // the class conflict with inherited methods.
2056 ApplyMixinMembers(cls); 2045 ApplyMixinMembers(cls);
2057 } 2046 }
2047 GrowableArray<intptr_t> added_subclass_to_cids;
2048 CollectFinalizedSuperClasses(cls, &added_subclass_to_cids);
2058 // Ensure super class is finalized. 2049 // Ensure super class is finalized.
2059 const Class& super = Class::Handle(cls.SuperClass()); 2050 const Class& super = Class::Handle(cls.SuperClass());
2060 if (!super.IsNull()) { 2051 if (!super.IsNull()) {
2061 FinalizeClass(super); 2052 FinalizeClass(super);
2062 } 2053 }
2063 // Mark as parsed and finalized. 2054 // Mark as parsed and finalized.
2064 cls.Finalize(); 2055 cls.Finalize();
2065 // Mixin app alias classes may still lack their forwarding constructor. 2056 // Mixin app alias classes may still lack their forwarding constructor.
2066 if (cls.is_mixin_app_alias() && 2057 if (cls.is_mixin_app_alias() &&
2067 (cls.functions() == Object::empty_array().raw())) { 2058 (cls.functions() == Object::empty_array().raw())) {
2068 const GrowableObjectArray& cloned_funcs = 2059 const GrowableObjectArray& cloned_funcs =
2069 GrowableObjectArray::Handle(GrowableObjectArray::New()); 2060 GrowableObjectArray::Handle(GrowableObjectArray::New());
2070 CreateForwardingConstructors(cls, cloned_funcs); 2061 CreateForwardingConstructors(cls, cloned_funcs);
2071 const Array& functions = Array::Handle(Array::MakeArray(cloned_funcs)); 2062 const Array& functions = Array::Handle(Array::MakeArray(cloned_funcs));
2072 cls.SetFunctions(functions); 2063 cls.SetFunctions(functions);
2073 } 2064 }
2074 // Every class should have at least a constructor, unless it is a top level 2065 // Every class should have at least a constructor, unless it is a top level
2075 // class or a signature class. 2066 // class or a signature class.
2076 ASSERT(cls.IsTopLevel() || 2067 ASSERT(cls.IsTopLevel() ||
2077 cls.IsSignatureClass() || 2068 cls.IsSignatureClass() ||
2078 (Array::Handle(cls.functions()).Length() > 0)); 2069 (Array::Handle(cls.functions()).Length() > 0));
2079 // Resolve and finalize all member types. 2070 // Resolve and finalize all member types.
2080 ResolveAndFinalizeMemberTypes(cls); 2071 ResolveAndFinalizeMemberTypes(cls);
2081 // Run additional checks after all types are finalized. 2072 // Run additional checks after all types are finalized.
2082 if (cls.is_const()) { 2073 if (cls.is_const()) {
2083 CheckForLegalConstClass(cls); 2074 CheckForLegalConstClass(cls);
2084 } 2075 }
2076 if (FLAG_use_cha) {
2077 RemoveOptimizedCode(added_subclass_to_cids);
2078 }
2085 } 2079 }
2086 2080
2087 2081
2088 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { 2082 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) {
2089 Class& test1 = Class::Handle(cls.raw()); 2083 Class& test1 = Class::Handle(cls.raw());
2090 Class& test2 = Class::Handle(cls.SuperClass()); 2084 Class& test2 = Class::Handle(cls.SuperClass());
2091 // A finalized class has been checked for cycles. 2085 // A finalized class has been checked for cycles.
2092 // Using the hare and tortoise algorithm for locating cycles. 2086 // Using the hare and tortoise algorithm for locating cycles.
2093 while (!test1.is_type_finalized() && 2087 while (!test1.is_type_finalized() &&
2094 !test2.IsNull() && !test2.is_type_finalized()) { 2088 !test2.IsNull() && !test2.is_type_finalized()) {
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after
2762 expected_name ^= String::New("_offset"); 2756 expected_name ^= String::New("_offset");
2763 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); 2757 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
2764 field ^= fields_array.At(2); 2758 field ^= fields_array.At(2);
2765 ASSERT(field.Offset() == TypedDataView::length_offset()); 2759 ASSERT(field.Offset() == TypedDataView::length_offset());
2766 name ^= field.name(); 2760 name ^= field.name();
2767 ASSERT(name.Equals("length")); 2761 ASSERT(name.Equals("length"));
2768 #endif 2762 #endif
2769 } 2763 }
2770 2764
2771 } // namespace dart 2765 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/class_finalizer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698