Chromium Code Reviews| 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 if (!instance.raw()->IsHeapObject()) return; | |
|
srdjan
2015/10/14 21:04:11
Maybe more readable: if (instance.IsSmi()) return;
rmacnak
2015/10/14 22:22:41
Done.
| |
| 419 if (!instance.IsCanonical()) return; | |
|
srdjan
2015/10/14 21:04:11
Add brief comment when that is the case.
rmacnak
2015/10/14 22:22:41
Done.
| |
| 420 | |
| 421 class ConstObjectVisitor : public ObjectPointerVisitor { | |
|
srdjan
2015/10/14 21:04:11
We typically add classes outside the scope of a fu
| |
| 422 public: | |
| 423 ConstObjectVisitor(Precompiler* precompiler, Isolate* isolate) : | |
| 424 ObjectPointerVisitor(isolate), | |
| 425 precompiler_(precompiler), | |
| 426 subinstance_(Object::Handle()) {} | |
|
srdjan
2015/10/14 21:04:11
4 spaces indent.
rmacnak
2015/10/14 22:22:41
Done.
| |
| 427 | |
| 428 virtual void VisitPointers(RawObject** first, RawObject** last) { | |
| 429 for (RawObject** current = first; current <= last; current++) { | |
| 430 subinstance_ = *current; | |
| 431 if (subinstance_.IsInstance()) { | |
| 432 precompiler_->AddConstObject(Instance::Cast(subinstance_)); | |
| 433 } | |
| 434 } | |
|
srdjan
2015/10/14 21:04:11
clear subinstance_ to null (so that it does not ho
rmacnak
2015/10/14 22:22:41
Done.
| |
| 435 } | |
| 436 | |
| 437 private: | |
| 438 Precompiler* precompiler_; | |
| 439 Object& subinstance_; | |
| 440 }; | |
| 441 | |
| 442 ConstObjectVisitor visitor(this, I); | |
| 443 instance.raw()->VisitPointers(&visitor); | |
| 444 } | |
| 445 | |
| 446 | |
| 413 void Precompiler::AddClosureCall(const ICData& call_site) { | 447 void Precompiler::AddClosureCall(const ICData& call_site) { |
| 414 const Array& arguments_descriptor = | 448 const Array& arguments_descriptor = |
| 415 Array::Handle(Z, call_site.arguments_descriptor()); | 449 Array::Handle(Z, call_site.arguments_descriptor()); |
| 416 const Type& function_impl = | 450 const Type& function_impl = |
| 417 Type::Handle(Z, I->object_store()->function_impl_type()); | 451 Type::Handle(Z, I->object_store()->function_impl_type()); |
| 418 const Class& cache_class = | 452 const Class& cache_class = |
| 419 Class::Handle(Z, function_impl.type_class()); | 453 Class::Handle(Z, function_impl.type_class()); |
| 420 const Function& dispatcher = Function::Handle(Z, | 454 const Function& dispatcher = Function::Handle(Z, |
| 421 cache_class.GetInvocationDispatcher(Symbols::Call(), | 455 cache_class.GetInvocationDispatcher(Symbols::Call(), |
| 422 arguments_descriptor, | 456 arguments_descriptor, |
| 423 RawFunction::kInvokeFieldDispatcher, | 457 RawFunction::kInvokeFieldDispatcher, |
| 424 true /* create_if_absent */)); | 458 true /* create_if_absent */)); |
| 425 AddFunction(dispatcher); | 459 AddFunction(dispatcher); |
| 426 } | 460 } |
| 427 | 461 |
| 428 | 462 |
| 429 void Precompiler::AddField(const Field& field) { | 463 void Precompiler::AddField(const Field& field) { |
| 430 if (field.is_static()) { | 464 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()); | 465 const Object& value = Object::Handle(Z, field.StaticValue()); |
| 434 const Class& cls = Class::Handle(Z, value.clazz()); | 466 if (value.IsInstance()) { |
| 435 AddClass(cls); | 467 AddConstObject(Instance::Cast(value)); |
| 468 } | |
| 436 | 469 |
| 437 if (field.has_initializer()) { | 470 if (field.has_initializer()) { |
| 438 // Should not be in the middle of initialization while precompiling. | 471 // Should not be in the middle of initialization while precompiling. |
| 439 ASSERT(value.raw() != Object::transition_sentinel().raw()); | 472 ASSERT(value.raw() != Object::transition_sentinel().raw()); |
| 440 | 473 |
| 441 const bool is_initialized = value.raw() != Object::sentinel().raw(); | 474 const bool is_initialized = value.raw() != Object::sentinel().raw(); |
| 442 if (is_initialized && !reset_fields_) return; | 475 if (is_initialized && !reset_fields_) return; |
| 443 | 476 |
| 444 if (field.HasPrecompiledInitializer()) return; | 477 if (field.HasPrecompiledInitializer()) return; |
| 445 | 478 |
| 446 if (FLAG_trace_precompiler) { | 479 if (FLAG_trace_precompiler) { |
| 447 THR_Print("Precompiling initializer for %s\n", field.ToCString()); | 480 THR_Print("Precompiling initializer for %s\n", field.ToCString()); |
| 448 } | 481 } |
| 449 ASSERT(!Dart::IsRunningPrecompiledCode()); | 482 ASSERT(!Dart::IsRunningPrecompiledCode()); |
| 450 field.SetStaticValue(Instance::Handle(field.SavedInitialStaticValue())); | 483 field.SetStaticValue(Instance::Handle(field.SavedInitialStaticValue())); |
| 451 Compiler::CompileStaticInitializer(field); | 484 Compiler::CompileStaticInitializer(field); |
| 452 | 485 |
| 453 const Function& function = | 486 const Function& function = |
| 454 Function::Handle(Z, field.PrecompiledInitializer()); | 487 Function::Handle(Z, field.PrecompiledInitializer()); |
| 455 AddCalleesOf(function); | 488 AddCalleesOf(function); |
| 456 } | 489 } |
| 457 } | 490 } |
| 458 } | 491 } |
| 459 | 492 |
| 460 | 493 |
| 461 void Precompiler::AddFunction(const Function& function) { | 494 void Precompiler::AddFunction(const Function& function) { |
| 462 if (function.HasCode()) return; | 495 if (enqueued_functions_.Lookup(&function) != NULL) return; |
| 463 | 496 |
| 497 enqueued_functions_.Insert(&Function::ZoneHandle(Z, function.raw())); | |
| 464 pending_functions_.Add(function); | 498 pending_functions_.Add(function); |
| 465 changed_ = true; | 499 changed_ = true; |
| 466 } | 500 } |
| 467 | 501 |
| 468 | 502 |
| 469 bool Precompiler::IsSent(const String& selector) { | 503 bool Precompiler::IsSent(const String& selector) { |
| 470 if (selector.IsNull()) { | 504 if (selector.IsNull()) { |
| 471 return false; | 505 return false; |
| 472 } | 506 } |
| 473 return sent_selectors_.Lookup(&selector) != NULL; | 507 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); | 552 String& selector = String::Handle(Z); |
| 519 String& selector2 = String::Handle(Z); | 553 String& selector2 = String::Handle(Z); |
| 520 String& selector3 = String::Handle(Z); | 554 String& selector3 = String::Handle(Z); |
| 521 | 555 |
| 522 for (intptr_t i = 0; i < libraries_.Length(); i++) { | 556 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
| 523 lib ^= libraries_.At(i); | 557 lib ^= libraries_.At(i); |
| 524 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); | 558 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); |
| 525 while (it.HasNext()) { | 559 while (it.HasNext()) { |
| 526 cls = it.GetNextClass(); | 560 cls = it.GetNextClass(); |
| 527 | 561 |
| 528 if (!cls.is_allocated()) { | 562 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 | 563 |
| 566 functions = cls.functions(); | 564 functions = cls.functions(); |
| 567 for (intptr_t k = 0; k < functions.Length(); k++) { | 565 for (intptr_t k = 0; k < functions.Length(); k++) { |
| 568 function ^= functions.At(k); | 566 function ^= functions.At(k); |
| 569 | 567 |
| 570 if (function.is_static() || function.is_abstract()) continue; | 568 if (function.is_static() || function.is_abstract()) continue; |
| 571 | 569 |
| 572 // Don't bail out early if there is already code because we may discover | 570 // 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. | 571 // the corresponding getter selector is sent in some later iteration. |
| 574 // if (function.HasCode()) continue; | 572 // if (function.HasCode()) continue; |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 843 continue; // class 'dynamic' is in the read-only VM isolate. | 841 continue; // class 'dynamic' is in the read-only VM isolate. |
| 844 } | 842 } |
| 845 cls.EnsureIsFinalized(T); | 843 cls.EnsureIsFinalized(T); |
| 846 } | 844 } |
| 847 } | 845 } |
| 848 I->set_all_classes_finalized(true); | 846 I->set_all_classes_finalized(true); |
| 849 } | 847 } |
| 850 | 848 |
| 851 | 849 |
| 852 } // namespace dart | 850 } // namespace dart |
| OLD | NEW |