| 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/compiler.h" | 7 #include "vm/compiler.h" |
| 8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
| 9 #include "vm/log.h" |
| 9 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| 10 #include "vm/object.h" | 11 #include "vm/object.h" |
| 11 #include "vm/object_store.h" | 12 #include "vm/object_store.h" |
| 12 #include "vm/resolver.h" | 13 #include "vm/resolver.h" |
| 13 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
| 14 | 15 |
| 15 namespace dart { | 16 namespace dart { |
| 16 | 17 |
| 17 | 18 |
| 18 #define I (isolate()) | 19 #define I (isolate()) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 42 } | 43 } |
| 43 | 44 |
| 44 | 45 |
| 45 Precompiler::Precompiler(Thread* thread) : | 46 Precompiler::Precompiler(Thread* thread) : |
| 46 thread_(thread), | 47 thread_(thread), |
| 47 zone_(thread->zone()), | 48 zone_(thread->zone()), |
| 48 isolate_(thread->isolate()), | 49 isolate_(thread->isolate()), |
| 49 changed_(false), | 50 changed_(false), |
| 50 function_count_(0), | 51 function_count_(0), |
| 51 class_count_(0), | 52 class_count_(0), |
| 53 selector_count_(0), |
| 54 dropped_function_count_(0), |
| 52 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())), | 55 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())), |
| 53 pending_functions_(GrowableObjectArray::Handle(Z, | 56 pending_functions_(GrowableObjectArray::Handle(Z, |
| 54 GrowableObjectArray::New())), | 57 GrowableObjectArray::New())), |
| 55 collected_closures_(GrowableObjectArray::Handle(Z, I->collected_closures())), | 58 collected_closures_(GrowableObjectArray::Handle(Z, I->collected_closures())), |
| 56 sent_selectors_(GrowableObjectArray::Handle(Z, GrowableObjectArray::New())), | 59 sent_selectors_(Z), |
| 57 error_(Error::Handle(Z)) { | 60 error_(Error::Handle(Z)) { |
| 58 } | 61 } |
| 59 | 62 |
| 60 | 63 |
| 61 void Precompiler::DoCompileAll() { | 64 void Precompiler::DoCompileAll() { |
| 65 LogBlock lb(thread_); |
| 66 |
| 62 // Drop all existing code so we can use the presence of code as an indicator | 67 // Drop all existing code so we can use the presence of code as an indicator |
| 63 // that we have already looked for the function's callees. | 68 // that we have already looked for the function's callees. |
| 64 ClearAllCode(); | 69 ClearAllCode(); |
| 65 | 70 |
| 66 // Start with the allocations and invocations that happen from C++. | 71 // Start with the allocations and invocations that happen from C++. |
| 67 AddRoots(); | 72 AddRoots(); |
| 68 | 73 |
| 69 // TODO(rmacnak): Eagerly add field-invocation functions to all signature | 74 // TODO(rmacnak): Eagerly add field-invocation functions to all signature |
| 70 // classes so closure calls don't go through the runtime. | 75 // classes so closure calls don't go through the runtime. |
| 71 | 76 |
| 72 // Compile newly found targets and add their callees until we reach a fixed | 77 // Compile newly found targets and add their callees until we reach a fixed |
| 73 // point. | 78 // point. |
| 74 Iterate(); | 79 Iterate(); |
| 75 | 80 |
| 76 CleanUp(); | 81 CleanUp(); |
| 77 | 82 |
| 78 if (FLAG_trace_precompiler) { | 83 if (FLAG_trace_precompiler) { |
| 79 OS::Print("Precompiled %" Pd " functions, %" Pd " dynamic types," | 84 ISL_Print("Precompiled %" Pd " functions, %" Pd " dynamic types," |
| 80 " %" Pd " dynamic selectors\n", | 85 " %" Pd " dynamic selectors.\n Dropped %" Pd " functions.\n", |
| 81 function_count_, | 86 function_count_, |
| 82 class_count_, | 87 class_count_, |
| 83 sent_selectors_.Length()); | 88 selector_count_, |
| 89 dropped_function_count_); |
| 84 } | 90 } |
| 85 | 91 |
| 86 I->set_compilation_allowed(false); | 92 I->set_compilation_allowed(false); |
| 87 } | 93 } |
| 88 | 94 |
| 89 | 95 |
| 90 void Precompiler::ClearAllCode() { | 96 void Precompiler::ClearAllCode() { |
| 91 Library& lib = Library::Handle(Z); | 97 Library& lib = Library::Handle(Z); |
| 92 Class& cls = Class::Handle(Z); | 98 Class& cls = Class::Handle(Z); |
| 93 Array& functions = Array::Handle(Z); | 99 Array& functions = Array::Handle(Z); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 String& class_name = String::Handle(Z); | 269 String& class_name = String::Handle(Z); |
| 264 String& function_name = String::Handle(Z); | 270 String& function_name = String::Handle(Z); |
| 265 for (intptr_t i = 0; kExternallyCalled[i].library_ != NULL; i++) { | 271 for (intptr_t i = 0; kExternallyCalled[i].library_ != NULL; i++) { |
| 266 library_name = Symbols::New(kExternallyCalled[i].library_); | 272 library_name = Symbols::New(kExternallyCalled[i].library_); |
| 267 class_name = Symbols::New(kExternallyCalled[i].class_); | 273 class_name = Symbols::New(kExternallyCalled[i].class_); |
| 268 function_name = Symbols::New(kExternallyCalled[i].function_); | 274 function_name = Symbols::New(kExternallyCalled[i].function_); |
| 269 | 275 |
| 270 lib = Library::LookupLibrary(library_name); | 276 lib = Library::LookupLibrary(library_name); |
| 271 if (lib.IsNull()) { | 277 if (lib.IsNull()) { |
| 272 if (FLAG_trace_precompiler) { | 278 if (FLAG_trace_precompiler) { |
| 273 OS::Print("WARNING: Missing %s\n", kExternallyCalled[i].library_); | 279 ISL_Print("WARNING: Missing %s\n", kExternallyCalled[i].library_); |
| 274 } | 280 } |
| 275 continue; | 281 continue; |
| 276 } | 282 } |
| 277 | 283 |
| 278 if (class_name.raw() == Symbols::TopLevel().raw()) { | 284 if (class_name.raw() == Symbols::TopLevel().raw()) { |
| 279 func = lib.LookupFunctionAllowPrivate(function_name); | 285 func = lib.LookupFunctionAllowPrivate(function_name); |
| 280 } else { | 286 } else { |
| 281 cls = lib.LookupClassAllowPrivate(class_name); | 287 cls = lib.LookupClassAllowPrivate(class_name); |
| 282 if (cls.IsNull()) { | 288 if (cls.IsNull()) { |
| 283 if (FLAG_trace_precompiler) { | 289 if (FLAG_trace_precompiler) { |
| 284 OS::Print("WARNING: Missing %s %s\n", | 290 ISL_Print("WARNING: Missing %s %s\n", |
| 285 kExternallyCalled[i].library_, | 291 kExternallyCalled[i].library_, |
| 286 kExternallyCalled[i].class_); | 292 kExternallyCalled[i].class_); |
| 287 } | 293 } |
| 288 continue; | 294 continue; |
| 289 } | 295 } |
| 290 | 296 |
| 291 ASSERT(!cls.IsNull()); | 297 ASSERT(!cls.IsNull()); |
| 292 func = cls.LookupFunctionAllowPrivate(function_name); | 298 func = cls.LookupFunctionAllowPrivate(function_name); |
| 293 } | 299 } |
| 294 | 300 |
| 295 if (func.IsNull()) { | 301 if (func.IsNull()) { |
| 296 if (FLAG_trace_precompiler) { | 302 if (FLAG_trace_precompiler) { |
| 297 OS::Print("WARNING: Missing %s %s %s\n", | 303 ISL_Print("WARNING: Missing %s %s %s\n", |
| 298 kExternallyCalled[i].library_, | 304 kExternallyCalled[i].library_, |
| 299 kExternallyCalled[i].class_, | 305 kExternallyCalled[i].class_, |
| 300 kExternallyCalled[i].function_); | 306 kExternallyCalled[i].function_); |
| 301 } | 307 } |
| 302 continue; | 308 continue; |
| 303 } | 309 } |
| 304 | 310 |
| 305 AddFunction(func); | 311 AddFunction(func); |
| 306 } | 312 } |
| 307 } | 313 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 326 function ^= collected_closures_.RemoveLast(); | 332 function ^= collected_closures_.RemoveLast(); |
| 327 ProcessFunction(function); | 333 ProcessFunction(function); |
| 328 } | 334 } |
| 329 } | 335 } |
| 330 } | 336 } |
| 331 | 337 |
| 332 | 338 |
| 333 void Precompiler::CleanUp() { | 339 void Precompiler::CleanUp() { |
| 334 I->set_collected_closures(GrowableObjectArray::Handle(Z)); | 340 I->set_collected_closures(GrowableObjectArray::Handle(Z)); |
| 335 | 341 |
| 336 // TODO(rmacnak): Drop functions without code, classes without functions, etc. | 342 DropUncompiledFunctions(); |
| 343 |
| 344 // TODO(rmacnak): DropEmptyClasses(); |
| 337 } | 345 } |
| 338 | 346 |
| 339 | 347 |
| 340 void Precompiler::ProcessFunction(const Function& function) { | 348 void Precompiler::ProcessFunction(const Function& function) { |
| 341 if (!function.HasCode()) { | 349 if (!function.HasCode()) { |
| 342 function_count_++; | 350 function_count_++; |
| 343 | 351 |
| 344 if (FLAG_trace_precompiler) { | 352 if (FLAG_trace_precompiler) { |
| 345 OS::Print("Precompiling %" Pd " %s (%" Pd ", %s)\n", | 353 ISL_Print("Precompiling %" Pd " %s (%" Pd ", %s)\n", |
| 346 function_count_, | 354 function_count_, |
| 347 function.ToLibNamePrefixedQualifiedCString(), | 355 function.ToLibNamePrefixedQualifiedCString(), |
| 348 function.token_pos(), | 356 function.token_pos(), |
| 349 Function::KindToCString(function.kind())); | 357 Function::KindToCString(function.kind())); |
| 350 } | 358 } |
| 351 | 359 |
| 352 ASSERT(!function.is_abstract()); | 360 ASSERT(!function.is_abstract()); |
| 353 ASSERT(!function.IsRedirectingFactory()); | 361 ASSERT(!function.IsRedirectingFactory()); |
| 354 | 362 |
| 355 error_ = Compiler::CompileFunction(thread_, function); | 363 error_ = Compiler::CompileFunction(thread_, function); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 // Potential const object. Uninitialized field will harmlessly do a | 435 // Potential const object. Uninitialized field will harmlessly do a |
| 428 // redundant add of the Null class. | 436 // redundant add of the Null class. |
| 429 const Object& value = Object::Handle(Z, field.value()); | 437 const Object& value = Object::Handle(Z, field.value()); |
| 430 const Class& cls = Class::Handle(Z, value.clazz()); | 438 const Class& cls = Class::Handle(Z, value.clazz()); |
| 431 AddClass(cls); | 439 AddClass(cls); |
| 432 | 440 |
| 433 if (field.has_initializer()) { | 441 if (field.has_initializer()) { |
| 434 if (field.initializer() != Function::null()) return; | 442 if (field.initializer() != Function::null()) return; |
| 435 | 443 |
| 436 if (FLAG_trace_precompiler) { | 444 if (FLAG_trace_precompiler) { |
| 437 OS::Print("Precompiling initializer for %s\n", field.ToCString()); | 445 ISL_Print("Precompiling initializer for %s\n", field.ToCString()); |
| 438 } | 446 } |
| 439 Compiler::CompileStaticInitializer(field); | 447 Compiler::CompileStaticInitializer(field); |
| 440 | 448 |
| 441 const Function& function = Function::Handle(Z, field.initializer()); | 449 const Function& function = Function::Handle(Z, field.initializer()); |
| 442 AddCalleesOf(function); | 450 AddCalleesOf(function); |
| 443 } | 451 } |
| 444 } | 452 } |
| 445 } | 453 } |
| 446 | 454 |
| 447 | 455 |
| 448 void Precompiler::AddFunction(const Function& function) { | 456 void Precompiler::AddFunction(const Function& function) { |
| 449 if (function.HasCode()) return; | 457 if (function.HasCode()) return; |
| 450 | 458 |
| 451 pending_functions_.Add(function); | 459 pending_functions_.Add(function); |
| 452 changed_ = true; | 460 changed_ = true; |
| 453 } | 461 } |
| 454 | 462 |
| 455 | 463 |
| 456 bool Precompiler::IsSent(const String& selector) { | 464 bool Precompiler::IsSent(const String& selector) { |
| 457 ASSERT(selector.IsSymbol()); | 465 return sent_selectors_.Includes(selector); |
| 458 | |
| 459 // TODO(rmacnak): Use a proper set. | |
| 460 for (intptr_t i = 0; i < sent_selectors_.Length(); i++) { | |
| 461 if (sent_selectors_.At(i) == selector.raw()) { | |
| 462 return true; | |
| 463 } | |
| 464 } | |
| 465 | |
| 466 return false; | |
| 467 } | 466 } |
| 468 | 467 |
| 469 | 468 |
| 470 void Precompiler::AddSelector(const String& selector) { | 469 void Precompiler::AddSelector(const String& selector) { |
| 471 if (!IsSent(selector)) { | 470 if (!IsSent(selector)) { |
| 471 sent_selectors_.Add(selector); |
| 472 selector_count_++; |
| 473 changed_ = true; |
| 474 |
| 472 if (FLAG_trace_precompiler) { | 475 if (FLAG_trace_precompiler) { |
| 473 OS::Print("Enqueueing selector %" Pd " %s\n", | 476 ISL_Print("Enqueueing selector %" Pd " %s\n", |
| 474 sent_selectors_.Length(), | 477 selector_count_, |
| 475 selector.ToCString()); | 478 selector.ToCString()); |
| 476 } | 479 } |
| 477 | 480 |
| 478 sent_selectors_.Add(selector); | |
| 479 changed_ = true; | |
| 480 | |
| 481 if (!Field::IsGetterName(selector) && | 481 if (!Field::IsGetterName(selector) && |
| 482 !Field::IsSetterName(selector)) { | 482 !Field::IsSetterName(selector)) { |
| 483 // Regular method may be call-through-getter. | 483 // Regular method may be call-through-getter. |
| 484 // TODO(rmacnak): Do not create the symbol if it does not already exist. | 484 const String& getter = String::Handle(Field::GetterSymbol(selector)); |
| 485 String& getter = String::Handle(Field::GetterName(selector)); | |
| 486 getter = Symbols::New(getter); | |
| 487 AddSelector(getter); | 485 AddSelector(getter); |
| 488 } | 486 } |
| 489 } | 487 } |
| 490 } | 488 } |
| 491 | 489 |
| 492 | 490 |
| 493 void Precompiler::AddClass(const Class& cls) { | 491 void Precompiler::AddClass(const Class& cls) { |
| 494 if (cls.is_allocated()) return; | 492 if (cls.is_allocated()) return; |
| 495 | 493 |
| 496 class_count_++; | 494 class_count_++; |
| 497 cls.set_is_allocated(); | 495 cls.set_is_allocated(); |
| 498 changed_ = true; | 496 changed_ = true; |
| 499 | 497 |
| 500 if (FLAG_trace_precompiler) { | 498 if (FLAG_trace_precompiler) { |
| 501 OS::Print("Allocation %" Pd " %s\n", class_count_, cls.ToCString()); | 499 ISL_Print("Allocation %" Pd " %s\n", class_count_, cls.ToCString()); |
| 502 } | 500 } |
| 503 | 501 |
| 504 const Class& superclass = Class::Handle(cls.SuperClass()); | 502 const Class& superclass = Class::Handle(cls.SuperClass()); |
| 505 if (!superclass.IsNull()) { | 503 if (!superclass.IsNull()) { |
| 506 AddClass(superclass); | 504 AddClass(superclass); |
| 507 } | 505 } |
| 508 } | 506 } |
| 509 | 507 |
| 510 | 508 |
| 511 void Precompiler::CheckForNewDynamicFunctions() { | 509 void Precompiler::CheckForNewDynamicFunctions() { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 // if (function.HasCode()) continue; | 568 // if (function.HasCode()) continue; |
| 571 | 569 |
| 572 selector = function.name(); | 570 selector = function.name(); |
| 573 if (IsSent(selector)) { | 571 if (IsSent(selector)) { |
| 574 AddFunction(function); | 572 AddFunction(function); |
| 575 } | 573 } |
| 576 | 574 |
| 577 if (function.kind() == RawFunction::kRegularFunction && | 575 if (function.kind() == RawFunction::kRegularFunction && |
| 578 !Field::IsGetterName(selector) && | 576 !Field::IsGetterName(selector) && |
| 579 !Field::IsSetterName(selector)) { | 577 !Field::IsSetterName(selector)) { |
| 580 // TODO(rmacnak): Do not create the symbol if it does not already | 578 selector = Field::GetterSymbol(selector); |
| 581 // exist. | |
| 582 selector = Field::GetterName(selector); | |
| 583 selector = Symbols::New(selector); | |
| 584 if (IsSent(selector)) { | 579 if (IsSent(selector)) { |
| 585 function = function.ImplicitClosureFunction(); | 580 function = function.ImplicitClosureFunction(); |
| 586 AddFunction(function); | 581 AddFunction(function); |
| 587 } | 582 } |
| 588 } | 583 } |
| 589 } | 584 } |
| 590 } | 585 } |
| 591 } | 586 } |
| 592 } | 587 } |
| 593 | 588 |
| 589 |
| 590 void Precompiler::DropUncompiledFunctions() { |
| 591 Library& lib = Library::Handle(Z); |
| 592 Class& cls = Class::Handle(Z); |
| 593 Array& functions = Array::Handle(Z); |
| 594 Function& function = Function::Handle(Z); |
| 595 GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z); |
| 596 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z); |
| 597 |
| 598 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
| 599 lib ^= libraries_.At(i); |
| 600 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); |
| 601 while (it.HasNext()) { |
| 602 cls = it.GetNextClass(); |
| 603 if (cls.IsDynamicClass()) { |
| 604 continue; // class 'dynamic' is in the read-only VM isolate. |
| 605 } |
| 606 |
| 607 functions = cls.functions(); |
| 608 retained_functions = GrowableObjectArray::New(); |
| 609 for (intptr_t j = 0; j < functions.Length(); j++) { |
| 610 function ^= functions.At(j); |
| 611 if (function.HasCode()) { |
| 612 retained_functions.Add(function); |
| 613 } else { |
| 614 dropped_function_count_++; |
| 615 if (FLAG_trace_precompiler) { |
| 616 ISL_Print("Precompilation dropping %s\n", |
| 617 function.ToLibNamePrefixedQualifiedCString()); |
| 618 } |
| 619 } |
| 620 } |
| 621 |
| 622 functions = Array::New(retained_functions.Length(), Heap::kOld); |
| 623 for (intptr_t j = 0; j < retained_functions.Length(); j++) { |
| 624 function ^= retained_functions.At(j); |
| 625 functions.SetAt(j, function); |
| 626 } |
| 627 cls.SetFunctions(functions); |
| 628 |
| 629 closures = cls.closures(); |
| 630 if (!closures.IsNull()) { |
| 631 for (intptr_t j = 0; j < closures.Length(); j++) { |
| 632 function ^= closures.At(j); |
| 633 ASSERT(function.HasCode()); |
| 634 } |
| 635 } |
| 636 } |
| 637 } |
| 638 } |
| 639 |
| 594 } // namespace dart | 640 } // namespace dart |
| OLD | NEW |