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

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

Issue 1275653002: Tree-shaking: use a hash set for tracking live selectors, drop uncompiled functions. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months 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
« runtime/vm/precompiler.h ('K') | « runtime/vm/precompiler.h ('k') | no next file » | 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) 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
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
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
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
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
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
OLDNEW
« runtime/vm/precompiler.h ('K') | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698