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

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

Issue 2485993002: VM: Support bootstrapping core libraries from Kernel binaries instead of source. (Closed)
Patch Set: Done Created 4 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
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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 } 110 }
111 } 111 }
112 cids->Add(ifc.id()); 112 cids->Add(ifc.id());
113 } 113 }
114 } 114 }
115 115
116 116
117 // Processing ObjectStore::pending_classes_ occurs: 117 // Processing ObjectStore::pending_classes_ occurs:
118 // a) when bootstrap process completes (VerifyBootstrapClasses). 118 // a) when bootstrap process completes (VerifyBootstrapClasses).
119 // b) after the user classes are loaded (dart_api). 119 // b) after the user classes are loaded (dart_api).
120 bool ClassFinalizer::ProcessPendingClasses() { 120 bool ClassFinalizer::ProcessPendingClasses(bool from_kernel) {
121 Thread* thread = Thread::Current(); 121 Thread* thread = Thread::Current();
122 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(), 122 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(),
123 "ProcessPendingClasses")); 123 "ProcessPendingClasses"));
124 Isolate* isolate = thread->isolate(); 124 Isolate* isolate = thread->isolate();
125 ASSERT(isolate != NULL); 125 ASSERT(isolate != NULL);
126 HANDLESCOPE(thread); 126 HANDLESCOPE(thread);
127 ObjectStore* object_store = isolate->object_store(); 127 ObjectStore* object_store = isolate->object_store();
128 const Error& error = Error::Handle(thread->zone(), thread->sticky_error()); 128 const Error& error = Error::Handle(thread->zone(), thread->sticky_error());
129 if (!error.IsNull()) { 129 if (!error.IsNull()) {
130 return false; 130 return false;
(...skipping 11 matching lines...) Expand all
142 // First resolve all superclasses. 142 // First resolve all superclasses.
143 for (intptr_t i = 0; i < class_array.Length(); i++) { 143 for (intptr_t i = 0; i < class_array.Length(); i++) {
144 cls ^= class_array.At(i); 144 cls ^= class_array.At(i);
145 GrowableArray<intptr_t> visited_interfaces; 145 GrowableArray<intptr_t> visited_interfaces;
146 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); 146 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces);
147 } 147 }
148 // Finalize all classes. 148 // Finalize all classes.
149 for (intptr_t i = 0; i < class_array.Length(); i++) { 149 for (intptr_t i = 0; i < class_array.Length(); i++) {
150 cls ^= class_array.At(i); 150 cls ^= class_array.At(i);
151 FinalizeTypesInClass(cls); 151 FinalizeTypesInClass(cls);
152 // Classes compiled from Dart sources are finalized more lazily, classes
153 // compiled from Kernel binaries can be finalized now (and should be,
154 // since we will not revisit them).
hausner 2016/11/09 00:42:49 Why? Would be nice to have a brief explanation.
Vyacheslav Egorov (Google) 2016/11/09 14:43:16 The original idea behind Kernel was to be an AOT r
155 if (from_kernel) {
156 FinalizeClass(cls);
157 }
152 } 158 }
153 if (FLAG_print_classes) { 159 if (FLAG_print_classes) {
154 for (intptr_t i = 0; i < class_array.Length(); i++) { 160 for (intptr_t i = 0; i < class_array.Length(); i++) {
155 cls ^= class_array.At(i); 161 cls ^= class_array.At(i);
156 PrintClassInformation(cls); 162 PrintClassInformation(cls);
157 } 163 }
158 } 164 }
159 // Clear pending classes array. 165 // Clear pending classes array.
160 class_array = GrowableObjectArray::New(); 166 class_array = GrowableObjectArray::New();
161 object_store->set_pending_classes(class_array); 167 object_store->set_pending_classes(class_array);
(...skipping 18 matching lines...) Expand all
180 Class& interface_class = Class::Handle(zone); 186 Class& interface_class = Class::Handle(zone);
181 for (intptr_t i = 0; i < interface_array.Length(); i++) { 187 for (intptr_t i = 0; i < interface_array.Length(); i++) {
182 interface ^= interface_array.At(i); 188 interface ^= interface_array.At(i);
183 interface_class = interface.type_class(); 189 interface_class = interface.type_class();
184 collected->Add(&Class::ZoneHandle(zone, interface_class.raw())); 190 collected->Add(&Class::ZoneHandle(zone, interface_class.raw()));
185 CollectInterfaces(interface_class, collected); 191 CollectInterfaces(interface_class, collected);
186 } 192 }
187 } 193 }
188 194
189 195
190 #if defined(DART_NO_SNAPSHOT)
191 void ClassFinalizer::VerifyBootstrapClasses() { 196 void ClassFinalizer::VerifyBootstrapClasses() {
192 if (FLAG_trace_class_finalization) { 197 if (FLAG_trace_class_finalization) {
193 OS::Print("VerifyBootstrapClasses START.\n"); 198 OS::Print("VerifyBootstrapClasses START.\n");
194 } 199 }
195 ObjectStore* object_store = Isolate::Current()->object_store(); 200 ObjectStore* object_store = Isolate::Current()->object_store();
196 201
197 Class& cls = Class::Handle(); 202 Class& cls = Class::Handle();
198 #if defined(DEBUG) 203 #if defined(DEBUG)
199 // Basic checking. 204 // Basic checking.
200 cls = object_store->object_class(); 205 cls = object_store->object_class();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 const Error& err = Error::Handle(Thread::Current()->sticky_error()); 251 const Error& err = Error::Handle(Thread::Current()->sticky_error());
247 OS::PrintErr("Could not verify bootstrap classes : %s\n", 252 OS::PrintErr("Could not verify bootstrap classes : %s\n",
248 err.ToErrorCString()); 253 err.ToErrorCString());
249 OS::Exit(255); 254 OS::Exit(255);
250 } 255 }
251 if (FLAG_trace_class_finalization) { 256 if (FLAG_trace_class_finalization) {
252 OS::Print("VerifyBootstrapClasses END.\n"); 257 OS::Print("VerifyBootstrapClasses END.\n");
253 } 258 }
254 Isolate::Current()->heap()->Verify(); 259 Isolate::Current()->heap()->Verify();
255 } 260 }
256 #endif // defined(DART_NO_SNAPSHOT).
257 261
258 262
259 static bool IsLoaded(const Type& type) { 263 static bool IsLoaded(const Type& type) {
260 if (type.HasResolvedTypeClass()) { 264 if (type.HasResolvedTypeClass()) {
261 return true; 265 return true;
262 } 266 }
263 const UnresolvedClass& unresolved_class = 267 const UnresolvedClass& unresolved_class =
264 UnresolvedClass::Handle(type.unresolved_class()); 268 UnresolvedClass::Handle(type.unresolved_class());
265 const LibraryPrefix& prefix = 269 const Object& prefix =
266 LibraryPrefix::Handle(unresolved_class.library_prefix()); 270 Object::Handle(unresolved_class.library_or_library_prefix());
267 return prefix.IsNull() || prefix.is_loaded(); 271 if (prefix.IsNull()) {
272 return true;
273 } else if (prefix.IsLibraryPrefix()) {
274 return LibraryPrefix::Cast(prefix).is_loaded();
275 } else {
276 return true;
277 }
268 } 278 }
269 279
270 280
271 // Resolve unresolved_class in the library of cls, or return null. 281 // Resolve unresolved_class in the library of cls, or return null.
272 RawClass* ClassFinalizer::ResolveClass( 282 RawClass* ClassFinalizer::ResolveClass(
273 const Class& cls, 283 const Class& cls,
274 const UnresolvedClass& unresolved_class) { 284 const UnresolvedClass& unresolved_class) {
275 const String& class_name = String::Handle(unresolved_class.ident()); 285 const String& class_name = String::Handle(unresolved_class.ident());
276 Library& lib = Library::Handle(); 286 Library& lib = Library::Handle();
277 Class& resolved_class = Class::Handle(); 287 Class& resolved_class = Class::Handle();
278 if (unresolved_class.library_prefix() == LibraryPrefix::null()) { 288 if (unresolved_class.library_or_library_prefix() == Object::null()) {
279 lib = cls.library(); 289 lib = cls.library();
280 ASSERT(!lib.IsNull()); 290 ASSERT(!lib.IsNull());
281 resolved_class = lib.LookupClass(class_name); 291 resolved_class = lib.LookupClass(class_name);
282 } else { 292 } else {
283 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); 293 const Object& prefix =
284 lib_prefix = unresolved_class.library_prefix(); 294 Object::Handle(unresolved_class.library_or_library_prefix());
285 ASSERT(!lib_prefix.IsNull()); 295
286 resolved_class = lib_prefix.LookupClass(class_name); 296 if (prefix.IsLibraryPrefix()) {
297 resolved_class = LibraryPrefix::Cast(prefix).LookupClass(class_name);
298 } else {
299 resolved_class = Library::Cast(prefix).LookupClass(class_name);
300 }
287 } 301 }
288 return resolved_class.raw(); 302 return resolved_class.raw();
289 } 303 }
290 304
291 305
292 306
293 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, 307 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls,
294 const Function& factory) { 308 const Function& factory) {
295 const Function& target = Function::Handle(factory.RedirectionTarget()); 309 const Function& target = Function::Handle(factory.RedirectionTarget());
296 if (target.IsNull()) { 310 if (target.IsNull()) {
(...skipping 1940 matching lines...) Expand 10 before | Expand all | Expand 10 after
2237 if (FLAG_trace_class_finalization) { 2251 if (FLAG_trace_class_finalization) {
2238 THR_Print("Applying mixin members of %s to %s at pos %s\n", 2252 THR_Print("Applying mixin members of %s to %s at pos %s\n",
2239 mixin_cls.ToCString(), 2253 mixin_cls.ToCString(),
2240 cls.ToCString(), 2254 cls.ToCString(),
2241 cls.token_pos().ToCString()); 2255 cls.token_pos().ToCString());
2242 } 2256 }
2243 2257
2244 const GrowableObjectArray& cloned_funcs = 2258 const GrowableObjectArray& cloned_funcs =
2245 GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); 2259 GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
2246 2260
2247 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs);
2248
2249 Array& functions = Array::Handle(zone); 2261 Array& functions = Array::Handle(zone);
2250 Function& func = Function::Handle(zone); 2262 Function& func = Function::Handle(zone);
2263
2251 // The parser creates the mixin application class with no functions. 2264 // The parser creates the mixin application class with no functions.
2252 ASSERT((functions = cls.functions(), functions.Length() == 0)); 2265 // But the Kernel frontend will generate mixin classes with only
2266 // constructors inside them, which forward to the base class constructors.
2267 //
2268 // => We generate the constructors if they are not already there.
2269 functions = cls.functions();
2270 if (functions.Length() == 0) {
2271 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs);
2272 } else {
2273 for (intptr_t i = 0; i < functions.Length(); i++) {
2274 func ^= functions.At(i);
2275 ASSERT(func.kernel_function() != 0);
2276 cloned_funcs.Add(func);
2277 }
2278 }
2279
2253 // Now clone the functions from the mixin class. 2280 // Now clone the functions from the mixin class.
2254 functions = mixin_cls.functions(); 2281 functions = mixin_cls.functions();
2255 const intptr_t num_functions = functions.Length(); 2282 const intptr_t num_functions = functions.Length();
2256 for (intptr_t i = 0; i < num_functions; i++) { 2283 for (intptr_t i = 0; i < num_functions; i++) {
2257 func ^= functions.At(i); 2284 func ^= functions.At(i);
2258 if (func.IsGenerativeConstructor()) { 2285 if (func.IsGenerativeConstructor()) {
2259 // A mixin class must not have explicit constructors. 2286 // A mixin class must not have explicit constructors.
2260 if (!func.IsImplicitConstructor()) { 2287 if (!func.IsImplicitConstructor()) {
2261 const Script& script = Script::Handle(cls.script()); 2288 const Script& script = Script::Handle(cls.script());
2262 const Error& error = Error::Handle( 2289 const Error& error = Error::Handle(
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
2437 } else { 2464 } else {
2438 // This class should not contain any functions or user-defined fields yet, 2465 // This class should not contain any functions or user-defined fields yet,
2439 // because it has not been compiled yet. There may however be metadata 2466 // because it has not been compiled yet. There may however be metadata
2440 // fields because type parameters are parsed before the class body. Since 2467 // fields because type parameters are parsed before the class body. Since
2441 // 'ResolveAndFinalizeMemberTypes(cls)' has not been called yet, unfinalized 2468 // 'ResolveAndFinalizeMemberTypes(cls)' has not been called yet, unfinalized
2442 // member types could choke the snapshotter. 2469 // member types could choke the snapshotter.
2443 // Or 2470 // Or
2444 // if the class is being refinalized because a patch is being applied 2471 // if the class is being refinalized because a patch is being applied
2445 // after the class has been finalized then it is ok for the class to have 2472 // after the class has been finalized then it is ok for the class to have
2446 // functions. 2473 // functions.
2447 ASSERT((Array::Handle(cls.functions()).Length() == 0) || 2474 //
2448 cls.is_refinalize_after_patch()); 2475 // TODO(kmillikin): This ASSERT will fail when bootstrapping from Kernel
2476 // because classes are first created, methods are added, and then classes
2477 // are finalized. It is not easy to finalize classes earlier because not
2478 // all bootstrap classes have been created yet. It would be possible to
2479 // create all classes, delay adding methods, finalize the classes, and then
2480 // reprocess all classes to add methods, but that seems unnecessary.
2481 // Marking the bootstrap classes as is_refinalize_after_patch seems cute but
2482 // it causes other things to fail by violating their assumptions. Reenable
2483 // this ASSERT if it's important, remove it if it's just a sanity check and
2484 // not required for correctness.
2485 //
2486 // ASSERT((Array::Handle(cls.functions()).Length() == 0) ||
2487 // cls.is_refinalize_after_patch());
2449 } 2488 }
2450 } 2489 }
2451 2490
2452 2491
2453 void ClassFinalizer::FinalizeClass(const Class& cls) { 2492 void ClassFinalizer::FinalizeClass(const Class& cls) {
2454 Thread* thread = Thread::Current(); 2493 Thread* thread = Thread::Current();
2455 HANDLESCOPE(thread); 2494 HANDLESCOPE(thread);
2456 ASSERT(cls.is_type_finalized()); 2495 ASSERT(cls.is_type_finalized());
2457 if (cls.is_finalized()) { 2496 if (cls.is_finalized()) {
2458 return; 2497 return;
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after
3345 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); 3384 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields());
3346 field ^= fields_array.At(0); 3385 field ^= fields_array.At(0);
3347 ASSERT(field.Offset() == ByteBuffer::data_offset()); 3386 ASSERT(field.Offset() == ByteBuffer::data_offset());
3348 name ^= field.name(); 3387 name ^= field.name();
3349 expected_name ^= String::New("_data"); 3388 expected_name ^= String::New("_data");
3350 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); 3389 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
3351 #endif 3390 #endif
3352 } 3391 }
3353 3392
3354 } // namespace dart 3393 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698