OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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/precompiler.h" | 5 #include "vm/precompiler.h" |
6 | 6 |
7 #include "vm/code_patcher.h" | 7 #include "vm/code_patcher.h" |
8 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
10 #include "vm/log.h" | 10 #include "vm/log.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 isolate_(thread->isolate()), | 53 isolate_(thread->isolate()), |
54 reset_fields_(reset_fields), | 54 reset_fields_(reset_fields), |
55 changed_(false), | 55 changed_(false), |
56 function_count_(0), | 56 function_count_(0), |
57 class_count_(0), | 57 class_count_(0), |
58 selector_count_(0), | 58 selector_count_(0), |
59 dropped_function_count_(0), | 59 dropped_function_count_(0), |
60 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())), | 60 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())), |
61 pending_functions_( | 61 pending_functions_( |
62 GrowableObjectArray::Handle(Z, GrowableObjectArray::New())), | 62 GrowableObjectArray::Handle(Z, GrowableObjectArray::New())), |
63 collected_closures_( | |
64 GrowableObjectArray::Handle(Z, GrowableObjectArray::New())), | |
65 sent_selectors_(), | 63 sent_selectors_(), |
| 64 enqueued_functions_(), |
66 error_(Error::Handle(Z)) { | 65 error_(Error::Handle(Z)) { |
67 I->set_collected_closures(collected_closures_); | |
68 } | 66 } |
69 | 67 |
70 | 68 |
71 void Precompiler::DoCompileAll( | 69 void Precompiler::DoCompileAll( |
72 Dart_QualifiedFunctionName embedder_entry_points[]) { | 70 Dart_QualifiedFunctionName embedder_entry_points[]) { |
73 // Drop all existing code so we can use the presence of code as an indicator | |
74 // that we have already looked for the function's callees. | |
75 ClearAllCode(); | 71 ClearAllCode(); |
76 | 72 |
77 // Make sure class hierarchy is stable before compilation so that CHA | 73 // Make sure class hierarchy is stable before compilation so that CHA |
78 // can be used. | 74 // can be used. Also ensures lookup of entry points won't miss functions |
| 75 // because their class hasn't been finalized yet. |
79 FinalizeAllClasses(); | 76 FinalizeAllClasses(); |
80 | 77 |
81 // Start with the allocations and invocations that happen from C++. | 78 // Start with the allocations and invocations that happen from C++. |
82 AddRoots(embedder_entry_points); | 79 AddRoots(embedder_entry_points); |
83 | 80 |
84 // TODO(rmacnak): Eagerly add field-invocation functions to all signature | |
85 // classes so closure calls don't go through the runtime. | |
86 | |
87 // Compile newly found targets and add their callees until we reach a fixed | 81 // Compile newly found targets and add their callees until we reach a fixed |
88 // point. | 82 // point. |
89 Iterate(); | 83 Iterate(); |
90 | 84 |
91 CleanUp(); | 85 DropUncompiledFunctions(); |
| 86 |
| 87 // TODO(rmacnak): DropEmptyClasses(); |
| 88 |
| 89 BindStaticCalls(); |
| 90 |
| 91 DedupStackmaps(); |
92 | 92 |
93 if (FLAG_trace_precompiler) { | 93 if (FLAG_trace_precompiler) { |
94 THR_Print("Precompiled %" Pd " functions, %" Pd " dynamic types," | 94 THR_Print("Precompiled %" Pd " functions, %" Pd " dynamic types," |
95 " %" Pd " dynamic selectors.\n Dropped %" Pd " functions.\n", | 95 " %" Pd " dynamic selectors.\n Dropped %" Pd " functions.\n", |
96 function_count_, | 96 function_count_, |
97 class_count_, | 97 class_count_, |
98 selector_count_, | 98 selector_count_, |
99 dropped_function_count_); | 99 dropped_function_count_); |
100 } | 100 } |
101 | 101 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 }; | 184 }; |
185 | 185 |
186 Class& cls = Class::Handle(Z); | 186 Class& cls = Class::Handle(Z); |
187 for (intptr_t i = 0; kExternallyAllocatedCids[i] != kIllegalCid; i++) { | 187 for (intptr_t i = 0; kExternallyAllocatedCids[i] != kIllegalCid; i++) { |
188 cls = isolate()->class_table()->At(kExternallyAllocatedCids[i]); | 188 cls = isolate()->class_table()->At(kExternallyAllocatedCids[i]); |
189 AddClass(cls); | 189 AddClass(cls); |
190 } | 190 } |
191 | 191 |
192 Dart_QualifiedFunctionName vm_entry_points[] = { | 192 Dart_QualifiedFunctionName vm_entry_points[] = { |
193 { "dart:async", "::", "_setScheduleImmediateClosure" }, | 193 { "dart:async", "::", "_setScheduleImmediateClosure" }, |
| 194 { "dart:core", "::", "_completeDeferredLoads"}, |
194 { "dart:core", "AbstractClassInstantiationError", | 195 { "dart:core", "AbstractClassInstantiationError", |
195 "AbstractClassInstantiationError._create" }, | 196 "AbstractClassInstantiationError._create" }, |
196 { "dart:core", "ArgumentError", "ArgumentError." }, | 197 { "dart:core", "ArgumentError", "ArgumentError." }, |
197 { "dart:core", "AssertionError", "AssertionError." }, | 198 { "dart:core", "AssertionError", "AssertionError." }, |
198 { "dart:core", "CyclicInitializationError", | 199 { "dart:core", "CyclicInitializationError", |
199 "CyclicInitializationError." }, | 200 "CyclicInitializationError." }, |
200 { "dart:core", "FallThroughError", "FallThroughError._create" }, | 201 { "dart:core", "FallThroughError", "FallThroughError._create" }, |
201 { "dart:core", "FormatException", "FormatException." }, | 202 { "dart:core", "FormatException", "FormatException." }, |
202 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" }, | 203 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" }, |
203 { "dart:core", "NullThrownError", "NullThrownError." }, | 204 { "dart:core", "NullThrownError", "NullThrownError." }, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 | 291 |
291 while (changed_) { | 292 while (changed_) { |
292 changed_ = false; | 293 changed_ = false; |
293 | 294 |
294 while (pending_functions_.Length() > 0) { | 295 while (pending_functions_.Length() > 0) { |
295 function ^= pending_functions_.RemoveLast(); | 296 function ^= pending_functions_.RemoveLast(); |
296 ProcessFunction(function); | 297 ProcessFunction(function); |
297 } | 298 } |
298 | 299 |
299 CheckForNewDynamicFunctions(); | 300 CheckForNewDynamicFunctions(); |
300 | |
301 // Drain collected_closures last because additions to this list come from | |
302 // outside the Precompiler and so do not flip our changed_ flag. | |
303 while (collected_closures_.Length() > 0) { | |
304 function ^= collected_closures_.RemoveLast(); | |
305 ProcessFunction(function); | |
306 } | |
307 } | 301 } |
308 } | 302 } |
309 | 303 |
310 | 304 |
311 void Precompiler::CleanUp() { | |
312 I->set_collected_closures(GrowableObjectArray::Handle(Z)); | |
313 | |
314 DropUncompiledFunctions(); | |
315 | |
316 // TODO(rmacnak): DropEmptyClasses(); | |
317 | |
318 BindStaticCalls(); | |
319 | |
320 DedupStackmaps(); | |
321 } | |
322 | |
323 | |
324 void Precompiler::ProcessFunction(const Function& function) { | 305 void Precompiler::ProcessFunction(const Function& function) { |
325 if (!function.HasCode()) { | 306 if (!function.HasCode()) { |
326 function_count_++; | 307 function_count_++; |
327 | 308 |
328 if (FLAG_trace_precompiler) { | 309 if (FLAG_trace_precompiler) { |
329 THR_Print("Precompiling %" Pd " %s (%" Pd ", %s)\n", | 310 THR_Print("Precompiling %" Pd " %s (%" Pd ", %s)\n", |
330 function_count_, | 311 function_count_, |
331 function.ToLibNamePrefixedQualifiedCString(), | 312 function.ToLibNamePrefixedQualifiedCString(), |
332 function.token_pos(), | 313 function.token_pos(), |
333 Function::KindToCString(function.kind())); | 314 Function::KindToCString(function.kind())); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 | 346 |
366 #if defined(TARGET_ARCH_IA32) | 347 #if defined(TARGET_ARCH_IA32) |
367 FATAL("Callee scanning unimplemented for IA32"); | 348 FATAL("Callee scanning unimplemented for IA32"); |
368 #endif | 349 #endif |
369 | 350 |
370 const ObjectPool& pool = ObjectPool::Handle(Z, code.GetObjectPool()); | 351 const ObjectPool& pool = ObjectPool::Handle(Z, code.GetObjectPool()); |
371 ICData& call_site = ICData::Handle(Z); | 352 ICData& call_site = ICData::Handle(Z); |
372 String& selector = String::Handle(Z); | 353 String& selector = String::Handle(Z); |
373 Field& field = Field::Handle(Z); | 354 Field& field = Field::Handle(Z); |
374 Class& cls = Class::Handle(Z); | 355 Class& cls = Class::Handle(Z); |
| 356 Instance& instance = Instance::Handle(Z); |
| 357 Code& target_code = Code::Handle(Z); |
375 for (intptr_t i = 0; i < pool.Length(); i++) { | 358 for (intptr_t i = 0; i < pool.Length(); i++) { |
376 if (pool.InfoAt(i) == ObjectPool::kTaggedObject) { | 359 if (pool.InfoAt(i) == ObjectPool::kTaggedObject) { |
377 entry = pool.ObjectAt(i); | 360 entry = pool.ObjectAt(i); |
378 if (entry.IsICData()) { | 361 if (entry.IsICData()) { |
379 call_site ^= entry.raw(); | 362 call_site ^= entry.raw(); |
380 if (call_site.NumberOfChecks() == 1) { | 363 if (call_site.NumberOfChecks() == 1) { |
381 // Probably a static call. | 364 // Probably a static call. |
382 target = call_site.GetTargetAt(0); | 365 target = call_site.GetTargetAt(0); |
383 AddFunction(target); | 366 AddFunction(target); |
384 if (!target.is_static()) { | 367 if (!target.is_static()) { |
385 // Super call (should not enqueue selector) or dynamic call with a | 368 // Super call (should not enqueue selector) or dynamic call with a |
386 // CHA prediction (should enqueue selector). | 369 // CHA prediction (should enqueue selector). |
387 selector = call_site.target_name(); | 370 selector = call_site.target_name(); |
388 AddSelector(selector); | 371 AddSelector(selector); |
389 } | 372 } |
390 } else { | 373 } else { |
391 // A dynamic call. | 374 // A dynamic call. |
392 selector = call_site.target_name(); | 375 selector = call_site.target_name(); |
393 AddSelector(selector); | 376 AddSelector(selector); |
394 if (selector.raw() == Symbols::Call().raw()) { | 377 if (selector.raw() == Symbols::Call().raw()) { |
395 // Potential closure call. | 378 // Potential closure call. |
396 AddClosureCall(call_site); | 379 AddClosureCall(call_site); |
397 } | 380 } |
398 } | 381 } |
399 } else if (entry.IsField()) { | 382 } else if (entry.IsField()) { |
400 // Potential need for field initializer. | 383 // Potential need for field initializer. |
401 field ^= entry.raw(); | 384 field ^= entry.raw(); |
402 AddField(field); | 385 AddField(field); |
403 } else if (entry.IsInstance()) { | 386 } else if (entry.IsInstance()) { |
404 // Potential const object. | 387 // Const object, literal or args descriptor. |
405 cls = entry.clazz(); | 388 instance ^= entry.raw(); |
406 AddClass(cls); | 389 AddConstObject(instance); |
| 390 } else if (entry.IsFunction()) { |
| 391 // Local closure function. |
| 392 target ^= entry.raw(); |
| 393 AddFunction(target); |
| 394 } else if (entry.IsCode()) { |
| 395 target_code ^= entry.raw(); |
| 396 if (target_code.IsAllocationStubCode()) { |
| 397 cls ^= target_code.owner(); |
| 398 AddClass(cls); |
| 399 } |
407 } | 400 } |
408 } | 401 } |
409 } | 402 } |
410 } | 403 } |
411 | 404 |
412 | 405 |
| 406 void Precompiler::AddConstObject(const Instance& instance) { |
| 407 const Class& cls = Class::Handle(Z, instance.clazz()); |
| 408 AddClass(cls); |
| 409 |
| 410 if (instance.IsClosure()) { |
| 411 // An implicit static closure. |
| 412 const Function& func = Function::Handle(Z, Closure::function(instance)); |
| 413 ASSERT(func.is_static()); |
| 414 AddFunction(func); |
| 415 return; |
| 416 } |
| 417 |
| 418 // Can't ask immediate objects if they're canoncial. |
| 419 if (instance.IsSmi()) return; |
| 420 |
| 421 // Some Instances in the ObjectPool aren't const objects, such as |
| 422 // argument descriptors. |
| 423 if (!instance.IsCanonical()) return; |
| 424 |
| 425 class ConstObjectVisitor : public ObjectPointerVisitor { |
| 426 public: |
| 427 ConstObjectVisitor(Precompiler* precompiler, Isolate* isolate) : |
| 428 ObjectPointerVisitor(isolate), |
| 429 precompiler_(precompiler), |
| 430 subinstance_(Object::Handle()) {} |
| 431 |
| 432 virtual void VisitPointers(RawObject** first, RawObject** last) { |
| 433 for (RawObject** current = first; current <= last; current++) { |
| 434 subinstance_ = *current; |
| 435 if (subinstance_.IsInstance()) { |
| 436 precompiler_->AddConstObject(Instance::Cast(subinstance_)); |
| 437 } |
| 438 } |
| 439 subinstance_ = Object::null(); |
| 440 } |
| 441 |
| 442 private: |
| 443 Precompiler* precompiler_; |
| 444 Object& subinstance_; |
| 445 }; |
| 446 |
| 447 ConstObjectVisitor visitor(this, I); |
| 448 instance.raw()->VisitPointers(&visitor); |
| 449 } |
| 450 |
| 451 |
413 void Precompiler::AddClosureCall(const ICData& call_site) { | 452 void Precompiler::AddClosureCall(const ICData& call_site) { |
414 const Array& arguments_descriptor = | 453 const Array& arguments_descriptor = |
415 Array::Handle(Z, call_site.arguments_descriptor()); | 454 Array::Handle(Z, call_site.arguments_descriptor()); |
416 const Type& function_impl = | 455 const Type& function_impl = |
417 Type::Handle(Z, I->object_store()->function_impl_type()); | 456 Type::Handle(Z, I->object_store()->function_impl_type()); |
418 const Class& cache_class = | 457 const Class& cache_class = |
419 Class::Handle(Z, function_impl.type_class()); | 458 Class::Handle(Z, function_impl.type_class()); |
420 const Function& dispatcher = Function::Handle(Z, | 459 const Function& dispatcher = Function::Handle(Z, |
421 cache_class.GetInvocationDispatcher(Symbols::Call(), | 460 cache_class.GetInvocationDispatcher(Symbols::Call(), |
422 arguments_descriptor, | 461 arguments_descriptor, |
423 RawFunction::kInvokeFieldDispatcher, | 462 RawFunction::kInvokeFieldDispatcher, |
424 true /* create_if_absent */)); | 463 true /* create_if_absent */)); |
425 AddFunction(dispatcher); | 464 AddFunction(dispatcher); |
426 } | 465 } |
427 | 466 |
428 | 467 |
429 void Precompiler::AddField(const Field& field) { | 468 void Precompiler::AddField(const Field& field) { |
430 if (field.is_static()) { | 469 if (field.is_static()) { |
431 // Potential const object. Uninitialized field will harmlessly do a | |
432 // redundant add of the Null class. | |
433 const Object& value = Object::Handle(Z, field.StaticValue()); | 470 const Object& value = Object::Handle(Z, field.StaticValue()); |
434 const Class& cls = Class::Handle(Z, value.clazz()); | 471 if (value.IsInstance()) { |
435 AddClass(cls); | 472 AddConstObject(Instance::Cast(value)); |
| 473 } |
436 | 474 |
437 if (field.has_initializer()) { | 475 if (field.has_initializer()) { |
438 // Should not be in the middle of initialization while precompiling. | 476 // Should not be in the middle of initialization while precompiling. |
439 ASSERT(value.raw() != Object::transition_sentinel().raw()); | 477 ASSERT(value.raw() != Object::transition_sentinel().raw()); |
440 | 478 |
441 const bool is_initialized = value.raw() != Object::sentinel().raw(); | 479 const bool is_initialized = value.raw() != Object::sentinel().raw(); |
442 if (is_initialized && !reset_fields_) return; | 480 if (is_initialized && !reset_fields_) return; |
443 | 481 |
444 if (field.HasPrecompiledInitializer()) return; | 482 if (field.HasPrecompiledInitializer()) return; |
445 | 483 |
446 if (FLAG_trace_precompiler) { | 484 if (FLAG_trace_precompiler) { |
447 THR_Print("Precompiling initializer for %s\n", field.ToCString()); | 485 THR_Print("Precompiling initializer for %s\n", field.ToCString()); |
448 } | 486 } |
449 ASSERT(!Dart::IsRunningPrecompiledCode()); | 487 ASSERT(!Dart::IsRunningPrecompiledCode()); |
450 field.SetStaticValue(Instance::Handle(field.SavedInitialStaticValue())); | 488 field.SetStaticValue(Instance::Handle(field.SavedInitialStaticValue())); |
451 Compiler::CompileStaticInitializer(field); | 489 Compiler::CompileStaticInitializer(field); |
452 | 490 |
453 const Function& function = | 491 const Function& function = |
454 Function::Handle(Z, field.PrecompiledInitializer()); | 492 Function::Handle(Z, field.PrecompiledInitializer()); |
455 AddCalleesOf(function); | 493 AddCalleesOf(function); |
456 } | 494 } |
457 } | 495 } |
458 } | 496 } |
459 | 497 |
460 | 498 |
461 void Precompiler::AddFunction(const Function& function) { | 499 void Precompiler::AddFunction(const Function& function) { |
462 if (function.HasCode()) return; | 500 if (enqueued_functions_.Lookup(&function) != NULL) return; |
463 | 501 |
| 502 enqueued_functions_.Insert(&Function::ZoneHandle(Z, function.raw())); |
464 pending_functions_.Add(function); | 503 pending_functions_.Add(function); |
465 changed_ = true; | 504 changed_ = true; |
466 } | 505 } |
467 | 506 |
468 | 507 |
469 bool Precompiler::IsSent(const String& selector) { | 508 bool Precompiler::IsSent(const String& selector) { |
470 if (selector.IsNull()) { | 509 if (selector.IsNull()) { |
471 return false; | 510 return false; |
472 } | 511 } |
473 return sent_selectors_.Lookup(&selector) != NULL; | 512 return sent_selectors_.Lookup(&selector) != NULL; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 String& selector = String::Handle(Z); | 557 String& selector = String::Handle(Z); |
519 String& selector2 = String::Handle(Z); | 558 String& selector2 = String::Handle(Z); |
520 String& selector3 = String::Handle(Z); | 559 String& selector3 = String::Handle(Z); |
521 | 560 |
522 for (intptr_t i = 0; i < libraries_.Length(); i++) { | 561 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
523 lib ^= libraries_.At(i); | 562 lib ^= libraries_.At(i); |
524 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); | 563 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); |
525 while (it.HasNext()) { | 564 while (it.HasNext()) { |
526 cls = it.GetNextClass(); | 565 cls = it.GetNextClass(); |
527 | 566 |
528 if (!cls.is_allocated()) { | 567 if (!cls.is_allocated()) continue; |
529 bool has_compiled_constructor = false; | |
530 if (cls.allocation_stub() != Code::null()) { | |
531 // Regular objects. | |
532 has_compiled_constructor = true; | |
533 } else if (cls.is_synthesized_class()) { | |
534 // Enums. | |
535 has_compiled_constructor = true; | |
536 } else { | |
537 // Objects only allocated via const constructors, and not stored in a | |
538 // static field or code. | |
539 // E.g. A in | |
540 // class A { | |
541 // const A(); | |
542 // toString() => "Don't drop me!"; | |
543 // } | |
544 // class B { | |
545 // const a = const A(); | |
546 // const B(); | |
547 // static const theB = const B(); | |
548 // } | |
549 // main() => print(B.theB.a); | |
550 functions = cls.functions(); | |
551 for (intptr_t k = 0; k < functions.Length(); k++) { | |
552 function ^= functions.At(k); | |
553 if (function.IsGenerativeConstructor() && | |
554 function.HasCode()) { | |
555 has_compiled_constructor = true; | |
556 break; | |
557 } | |
558 } | |
559 } | |
560 if (!has_compiled_constructor) { | |
561 continue; | |
562 } | |
563 AddClass(cls); | |
564 } | |
565 | 568 |
566 functions = cls.functions(); | 569 functions = cls.functions(); |
567 for (intptr_t k = 0; k < functions.Length(); k++) { | 570 for (intptr_t k = 0; k < functions.Length(); k++) { |
568 function ^= functions.At(k); | 571 function ^= functions.At(k); |
569 | 572 |
570 if (function.is_static() || function.is_abstract()) continue; | 573 if (function.is_static() || function.is_abstract()) continue; |
571 | 574 |
572 // Don't bail out early if there is already code because we may discover | 575 // Don't bail out early if there is already code because we may discover |
573 // the corresponding getter selector is sent in some later iteration. | 576 // the corresponding getter selector is sent in some later iteration. |
574 // if (function.HasCode()) continue; | 577 // if (function.HasCode()) continue; |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 while (it.HasNext()) { | 812 while (it.HasNext()) { |
810 cls = it.GetNextClass(); | 813 cls = it.GetNextClass(); |
811 if (cls.IsDynamicClass()) { | 814 if (cls.IsDynamicClass()) { |
812 continue; // class 'dynamic' is in the read-only VM isolate. | 815 continue; // class 'dynamic' is in the read-only VM isolate. |
813 } | 816 } |
814 | 817 |
815 functions = cls.functions(); | 818 functions = cls.functions(); |
816 for (intptr_t j = 0; j < functions.Length(); j++) { | 819 for (intptr_t j = 0; j < functions.Length(); j++) { |
817 function ^= functions.At(j); | 820 function ^= functions.At(j); |
818 visitor->VisitFunction(function); | 821 visitor->VisitFunction(function); |
| 822 if (function.HasImplicitClosureFunction()) { |
| 823 function = function.ImplicitClosureFunction(); |
| 824 visitor->VisitFunction(function); |
| 825 } |
819 } | 826 } |
820 | 827 |
821 closures = cls.closures(); | 828 closures = cls.closures(); |
822 if (!closures.IsNull()) { | 829 if (!closures.IsNull()) { |
823 for (intptr_t j = 0; j < closures.Length(); j++) { | 830 for (intptr_t j = 0; j < closures.Length(); j++) { |
824 function ^= closures.At(j); | 831 function ^= closures.At(j); |
825 visitor->VisitFunction(function); | 832 visitor->VisitFunction(function); |
826 } | 833 } |
827 } | 834 } |
828 } | 835 } |
(...skipping 14 matching lines...) Expand all Loading... |
843 continue; // class 'dynamic' is in the read-only VM isolate. | 850 continue; // class 'dynamic' is in the read-only VM isolate. |
844 } | 851 } |
845 cls.EnsureIsFinalized(T); | 852 cls.EnsureIsFinalized(T); |
846 } | 853 } |
847 } | 854 } |
848 I->set_all_classes_finalized(true); | 855 I->set_all_classes_finalized(true); |
849 } | 856 } |
850 | 857 |
851 | 858 |
852 } // namespace dart | 859 } // namespace dart |
OLD | NEW |