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

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

Issue 1686773002: Precompilation: drop unused types and type arguments and empty classes and libraries. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 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
« no previous file with comments | « runtime/vm/precompiler.h ('k') | runtime/vm/raw_object.h » ('j') | 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/assembler.h" 7 #include "vm/assembler.h"
8 #include "vm/ast_printer.h" 8 #include "vm/ast_printer.h"
9 #include "vm/branch_optimizer.h" 9 #include "vm/branch_optimizer.h"
10 #include "vm/cha.h" 10 #include "vm/cha.h"
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 thread_(thread), 133 thread_(thread),
134 zone_(NULL), 134 zone_(NULL),
135 isolate_(thread->isolate()), 135 isolate_(thread->isolate()),
136 reset_fields_(reset_fields), 136 reset_fields_(reset_fields),
137 changed_(false), 137 changed_(false),
138 function_count_(0), 138 function_count_(0),
139 class_count_(0), 139 class_count_(0),
140 selector_count_(0), 140 selector_count_(0),
141 dropped_function_count_(0), 141 dropped_function_count_(0),
142 dropped_field_count_(0), 142 dropped_field_count_(0),
143 dropped_class_count_(0),
144 dropped_typearg_count_(0),
145 dropped_type_count_(0),
146 dropped_library_count_(0),
143 libraries_(GrowableObjectArray::Handle(I->object_store()->libraries())), 147 libraries_(GrowableObjectArray::Handle(I->object_store()->libraries())),
144 pending_functions_( 148 pending_functions_(
145 GrowableObjectArray::Handle(GrowableObjectArray::New())), 149 GrowableObjectArray::Handle(GrowableObjectArray::New())),
146 sent_selectors_(), 150 sent_selectors_(),
147 enqueued_functions_(), 151 enqueued_functions_(),
148 fields_to_retain_(), 152 fields_to_retain_(),
153 classes_to_retain_(),
154 typeargs_to_retain_(),
155 types_to_retain_(),
149 error_(Error::Handle()) { 156 error_(Error::Handle()) {
150 } 157 }
151 158
152 159
153 void Precompiler::DoCompileAll( 160 void Precompiler::DoCompileAll(
154 Dart_QualifiedFunctionName embedder_entry_points[]) { 161 Dart_QualifiedFunctionName embedder_entry_points[]) {
155 ASSERT(I->compilation_allowed()); 162 ASSERT(I->compilation_allowed());
156 163
157 { 164 {
158 StackZone stack_zone(T); 165 StackZone stack_zone(T);
159 zone_ = stack_zone.GetZone(); 166 zone_ = stack_zone.GetZone();
160 167
161 // Make sure class hierarchy is stable before compilation so that CHA 168 // Make sure class hierarchy is stable before compilation so that CHA
162 // can be used. Also ensures lookup of entry points won't miss functions 169 // can be used. Also ensures lookup of entry points won't miss functions
163 // because their class hasn't been finalized yet. 170 // because their class hasn't been finalized yet.
164 FinalizeAllClasses(); 171 FinalizeAllClasses();
165 172
166 const intptr_t kPrecompilerRounds = 1; 173 const intptr_t kPrecompilerRounds = 1;
167 for (intptr_t round = 0; round < kPrecompilerRounds; round++) { 174 for (intptr_t round = 0; round < kPrecompilerRounds; round++) {
168 if (FLAG_trace_precompiler) { 175 if (FLAG_trace_precompiler) {
169 OS::Print("Precompiler round %" Pd "\n", round); 176 THR_Print("Precompiler round %" Pd "\n", round);
170 } 177 }
171 178
172 if (round > 0) { 179 if (round > 0) {
173 ResetPrecompilerState(); 180 ResetPrecompilerState();
174 } 181 }
175 182
176 // TODO(rmacnak): We should be able to do a more thorough job and drop 183 // TODO(rmacnak): We should be able to do a more thorough job and drop
177 // some 184 // some
178 // - implicit static closures 185 // - implicit static closures
179 // - field initializers 186 // - field initializers
(...skipping 10 matching lines...) Expand all
190 197
191 // Compile newly found targets and add their callees until we reach a 198 // Compile newly found targets and add their callees until we reach a
192 // fixed point. 199 // fixed point.
193 Iterate(); 200 Iterate();
194 } 201 }
195 202
196 I->set_compilation_allowed(false); 203 I->set_compilation_allowed(false);
197 204
198 DropFunctions(); 205 DropFunctions();
199 DropFields(); 206 DropFields();
200 207 TraceTypesFromRetainedClasses();
201 // TODO(rmacnak): DropEmptyClasses(); 208 DropTypes();
209 DropTypeArguments();
210 DropClasses();
211 DropLibraries();
202 212
203 BindStaticCalls(); 213 BindStaticCalls();
204 214
205 DedupStackmaps(); 215 DedupStackmaps();
206 DedupStackmapLists(); 216 DedupStackmapLists();
207 217
208 if (FLAG_dedup_instructions) { 218 if (FLAG_dedup_instructions) {
209 // Reduces binary size but obfuscates profiler results. 219 // Reduces binary size but obfuscates profiler results.
210 DedupInstructions(); 220 DedupInstructions();
211 } 221 }
212 222
213 I->object_store()->set_compile_time_constants(Array::null_array()); 223 I->object_store()->set_compile_time_constants(Array::null_array());
214 I->object_store()->set_unique_dynamic_targets(Array::null_array()); 224 I->object_store()->set_unique_dynamic_targets(Array::null_array());
215 225
216 zone_ = NULL; 226 zone_ = NULL;
217 } 227 }
218 228
219 intptr_t dropped_symbols_count = Symbols::Compact(I); 229 intptr_t dropped_symbols_count = Symbols::Compact(I);
220 230
221 if (FLAG_trace_precompiler) { 231 if (FLAG_trace_precompiler) {
222 THR_Print("Precompiled %" Pd " functions, %" Pd " dynamic types," 232 THR_Print("Precompiled %" Pd " functions,", function_count_);
223 " %" Pd " dynamic selectors.\n Dropped %" Pd " functions, %" Pd 233 THR_Print(" %" Pd " dynamic types,", class_count_);
224 " fields, %" Pd " symbols.\n", 234 THR_Print(" %" Pd " dynamic selectors.\n", selector_count_);
225 function_count_, 235
226 class_count_, 236 THR_Print("Dropped %" Pd " functions,", dropped_function_count_);
227 selector_count_, 237 THR_Print(" %" Pd " fields,", dropped_field_count_);
228 dropped_function_count_, 238 THR_Print(" %" Pd " symbols,", dropped_symbols_count);
229 dropped_field_count_, 239 THR_Print(" %" Pd " types,", dropped_type_count_);
230 dropped_symbols_count); 240 THR_Print(" %" Pd " type arguments,", dropped_typearg_count_);
241 THR_Print(" %" Pd " classes,", dropped_class_count_);
242 THR_Print(" %" Pd " libraries.\n", dropped_library_count_);
231 } 243 }
232 } 244 }
233 245
234 246
235 void Precompiler::ClearAllCode() { 247 void Precompiler::ClearAllCode() {
236 class ClearCodeFunctionVisitor : public FunctionVisitor { 248 class ClearCodeFunctionVisitor : public FunctionVisitor {
237 void VisitFunction(const Function& function) { 249 void VisitFunction(const Function& function) {
238 function.ClearCode(); 250 function.ClearCode();
251 function.ClearICDataArray();
239 } 252 }
240 }; 253 };
241 ClearCodeFunctionVisitor visitor; 254 ClearCodeFunctionVisitor visitor;
242 VisitFunctions(&visitor); 255 VisitFunctions(&visitor);
243 } 256 }
244 257
245 258
246 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { 259 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) {
247 // Note that <rootlibrary>.main is not a root. The appropriate main will be 260 // Note that <rootlibrary>.main is not a root. The appropriate main will be
248 // discovered through _getMainClosure. 261 // discovered through _getMainClosure.
249 262
250 AddSelector(Symbols::NoSuchMethod()); 263 AddSelector(Symbols::NoSuchMethod());
251 264
252 AddSelector(Symbols::Call()); // For speed, not correctness. 265 AddSelector(Symbols::Call()); // For speed, not correctness.
253 266
254 // Allocated from C++. 267 // Allocated from C++.
255 static const intptr_t kExternallyAllocatedCids[] = {
256 kBoolCid,
257 kNullCid,
258 kClosureCid,
259
260 kSmiCid,
261 kMintCid,
262 kBigintCid,
263 kDoubleCid,
264
265 kOneByteStringCid,
266 kTwoByteStringCid,
267 kExternalOneByteStringCid,
268 kExternalTwoByteStringCid,
269
270 kArrayCid,
271 kImmutableArrayCid,
272 kGrowableObjectArrayCid,
273 kLinkedHashMapCid,
274
275 kTypedDataUint8ClampedArrayCid,
276 kTypedDataUint8ArrayCid,
277 kTypedDataUint16ArrayCid,
278 kTypedDataUint32ArrayCid,
279 kTypedDataUint64ArrayCid,
280 kTypedDataInt8ArrayCid,
281 kTypedDataInt16ArrayCid,
282 kTypedDataInt32ArrayCid,
283 kTypedDataInt64ArrayCid,
284
285 kExternalTypedDataUint8ArrayCid,
286 kExternalTypedDataUint16ArrayCid,
287 kExternalTypedDataUint32ArrayCid,
288 kExternalTypedDataUint64ArrayCid,
289 kExternalTypedDataInt8ArrayCid,
290 kExternalTypedDataInt16ArrayCid,
291 kExternalTypedDataInt32ArrayCid,
292 kExternalTypedDataInt64ArrayCid,
293
294 kTypedDataFloat32ArrayCid,
295 kTypedDataFloat64ArrayCid,
296
297 kTypedDataFloat32x4ArrayCid,
298 kTypedDataInt32x4ArrayCid,
299 kTypedDataFloat64x2ArrayCid,
300
301 kInt32x4Cid,
302 kFloat32x4Cid,
303 kFloat64x2Cid,
304
305 kTypeCid,
306 kFunctionTypeCid,
307 kTypeRefCid,
308 kTypeParameterCid,
309 kBoundedTypeCid,
310 kLibraryPrefixCid,
311
312 kJSRegExpCid,
313 kUserTagCid,
314 kStacktraceCid,
315 kWeakPropertyCid,
316 kCapabilityCid,
317 ReceivePort::kClassId,
318 SendPort::kClassId,
319
320 kIllegalCid
321 };
322
323 Class& cls = Class::Handle(Z); 268 Class& cls = Class::Handle(Z);
324 for (intptr_t i = 0; kExternallyAllocatedCids[i] != kIllegalCid; i++) { 269 for (intptr_t cid = kInstanceCid; cid < kNumPredefinedCids; cid++) {
325 cls = isolate()->class_table()->At(kExternallyAllocatedCids[i]); 270 ASSERT(isolate()->class_table()->IsValidIndex(cid));
271 if (!isolate()->class_table()->HasValidClassAt(cid)) {
272 continue;
273 }
274 if ((cid == kDynamicCid) ||
275 (cid == kVoidCid) ||
276 (cid == kFreeListElement)) {
277 continue;
278 }
279 cls = isolate()->class_table()->At(cid);
326 AddInstantiatedClass(cls); 280 AddInstantiatedClass(cls);
327 } 281 }
328 282
329 Dart_QualifiedFunctionName vm_entry_points[] = { 283 Dart_QualifiedFunctionName vm_entry_points[] = {
330 // Functions 284 // Functions
331 { "dart:async", "::", "_setScheduleImmediateClosure" }, 285 { "dart:async", "::", "_setScheduleImmediateClosure" },
332 { "dart:core", "::", "_completeDeferredLoads"}, 286 { "dart:core", "::", "_completeDeferredLoads" },
333 { "dart:core", "AbstractClassInstantiationError", 287 { "dart:core", "AbstractClassInstantiationError",
334 "AbstractClassInstantiationError._create" }, 288 "AbstractClassInstantiationError._create" },
335 { "dart:core", "ArgumentError", "ArgumentError." }, 289 { "dart:core", "ArgumentError", "ArgumentError." },
336 { "dart:core", "CyclicInitializationError", 290 { "dart:core", "CyclicInitializationError",
337 "CyclicInitializationError." }, 291 "CyclicInitializationError." },
338 { "dart:core", "FallThroughError", "FallThroughError._create" }, 292 { "dart:core", "FallThroughError", "FallThroughError._create" },
339 { "dart:core", "FormatException", "FormatException." }, 293 { "dart:core", "FormatException", "FormatException." },
340 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" }, 294 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" },
341 { "dart:core", "NullThrownError", "NullThrownError." }, 295 { "dart:core", "NullThrownError", "NullThrownError." },
342 { "dart:core", "OutOfMemoryError", "OutOfMemoryError." }, 296 { "dart:core", "OutOfMemoryError", "OutOfMemoryError." },
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 Function::KindToCString(function.kind())); 430 Function::KindToCString(function.kind()));
477 } 431 }
478 432
479 ASSERT(!function.is_abstract()); 433 ASSERT(!function.is_abstract());
480 ASSERT(!function.IsRedirectingFactory()); 434 ASSERT(!function.IsRedirectingFactory());
481 435
482 error_ = CompileFunction(thread_, function); 436 error_ = CompileFunction(thread_, function);
483 if (!error_.IsNull()) { 437 if (!error_.IsNull()) {
484 Jump(error_); 438 Jump(error_);
485 } 439 }
440 // Used in the JIT to save type-feedback across compilations.
441 function.ClearICDataArray();
486 } else { 442 } else {
487 if (FLAG_trace_precompiler) { 443 if (FLAG_trace_precompiler) {
488 // This function was compiled from somewhere other than Precompiler, 444 // This function was compiled from somewhere other than Precompiler,
489 // such as const constructors compiled by the parser. 445 // such as const constructors compiled by the parser.
490 THR_Print("Already has code: %s (%s, %s)\n", 446 THR_Print("Already has code: %s (%s, %s)\n",
491 function.ToLibNamePrefixedQualifiedCString(), 447 function.ToLibNamePrefixedQualifiedCString(),
492 function.token_pos().ToCString(), 448 function.token_pos().ToCString(),
493 Function::KindToCString(function.kind())); 449 Function::KindToCString(function.kind()));
494 } 450 }
495 } 451 }
496 452
497 ASSERT(function.HasCode()); 453 ASSERT(function.HasCode());
498 AddCalleesOf(function); 454 AddCalleesOf(function);
499 } 455 }
500 456
501 457
502 void Precompiler::AddCalleesOf(const Function& function) { 458 void Precompiler::AddCalleesOf(const Function& function) {
503 ASSERT(function.HasCode()); 459 ASSERT(function.HasCode());
504 460
505 const Code& code = Code::Handle(Z, function.CurrentCode()); 461 const Code& code = Code::Handle(Z, function.CurrentCode());
506 462
507 const Array& table = Array::Handle(Z, code.static_calls_target_table()); 463 const Array& table = Array::Handle(Z, code.static_calls_target_table());
508 Object& entry = Object::Handle(Z); 464 Object& entry = Object::Handle(Z);
509 Function& target = Function::Handle(Z); 465 Function& target = Function::Handle(Z);
510 for (intptr_t i = 0; i < table.Length(); i++) { 466 for (intptr_t i = 0; i < table.Length(); i++) {
511 entry = table.At(i); 467 entry = table.At(i);
512 if (entry.IsFunction()) { 468 if (entry.IsFunction()) {
513 target ^= table.At(i); 469 target ^= entry.raw();
514 AddFunction(target); 470 AddFunction(target);
515 } 471 }
516 } 472 }
517 473
518 #if defined(TARGET_ARCH_IA32) 474 #if defined(TARGET_ARCH_IA32)
519 FATAL("Callee scanning unimplemented for IA32"); 475 FATAL("Callee scanning unimplemented for IA32");
520 #endif 476 #endif
521 477
522 const ObjectPool& pool = ObjectPool::Handle(Z, code.GetObjectPool()); 478 const ObjectPool& pool = ObjectPool::Handle(Z, code.GetObjectPool());
523 ICData& call_site = ICData::Handle(Z); 479 ICData& call_site = ICData::Handle(Z);
524 MegamorphicCache& cache = MegamorphicCache::Handle(Z); 480 MegamorphicCache& cache = MegamorphicCache::Handle(Z);
525 String& selector = String::Handle(Z); 481 String& selector = String::Handle(Z);
526 Field& field = Field::Handle(Z); 482 Field& field = Field::Handle(Z);
527 Class& cls = Class::Handle(Z); 483 Class& cls = Class::Handle(Z);
528 Instance& instance = Instance::Handle(Z); 484 Instance& instance = Instance::Handle(Z);
529 Code& target_code = Code::Handle(Z); 485 Code& target_code = Code::Handle(Z);
530 for (intptr_t i = 0; i < pool.Length(); i++) { 486 for (intptr_t i = 0; i < pool.Length(); i++) {
531 if (pool.InfoAt(i) == ObjectPool::kTaggedObject) { 487 if (pool.InfoAt(i) == ObjectPool::kTaggedObject) {
532 entry = pool.ObjectAt(i); 488 entry = pool.ObjectAt(i);
533 if (entry.IsICData()) { 489 if (entry.IsICData()) {
534 call_site ^= entry.raw(); 490 call_site ^= entry.raw();
535 if (call_site.NumberOfChecks() == 1) { 491 for (intptr_t j = 0; j < call_site.NumberOfChecks(); j++) {
536 // Probably a static call. 492 target = call_site.GetTargetAt(j);
537 target = call_site.GetTargetAt(0);
538 AddFunction(target); 493 AddFunction(target);
539 if (!target.is_static()) { 494 if (!target.is_static()) {
540 // Super call (should not enqueue selector) or dynamic call with a 495 // Super call (should not enqueue selector) or dynamic call with a
541 // CHA prediction (should enqueue selector). 496 // CHA prediction (should enqueue selector).
542 selector = call_site.target_name(); 497 selector = call_site.target_name();
543 AddSelector(selector); 498 AddSelector(selector);
544 } 499 }
545 } else { 500 }
501 if (call_site.NumberOfChecks() == 0) {
546 // A dynamic call. 502 // A dynamic call.
547 selector = call_site.target_name(); 503 selector = call_site.target_name();
548 AddSelector(selector); 504 AddSelector(selector);
549 if (selector.raw() == Symbols::Call().raw()) { 505 if (selector.raw() == Symbols::Call().raw()) {
550 // Potential closure call. 506 // Potential closure call.
551 AddClosureCall(call_site); 507 AddClosureCall(call_site);
552 } 508 }
553 } 509 }
554 } else if (entry.IsMegamorphicCache()) { 510 } else if (entry.IsMegamorphicCache()) {
555 // A dynamic call. 511 // A dynamic call.
556 cache ^= entry.raw(); 512 cache ^= entry.raw();
557 selector = cache.target_name(); 513 selector = cache.target_name();
558 AddSelector(selector); 514 AddSelector(selector);
559 } else if (entry.IsField()) { 515 } else if (entry.IsField()) {
560 // Potential need for field initializer. 516 // Potential need for field initializer.
561 field ^= entry.raw(); 517 field ^= entry.raw();
562 AddField(field); 518 AddField(field);
563 } else if (entry.IsInstance()) { 519 } else if (entry.IsInstance()) {
564 // Const object, literal or args descriptor. 520 // Const object, literal or args descriptor.
565 instance ^= entry.raw(); 521 instance ^= entry.raw();
566 AddConstObject(instance); 522 if (entry.IsAbstractType()) {
523 AddType(AbstractType::Cast(entry));
524 } else {
525 AddConstObject(instance);
526 }
567 } else if (entry.IsFunction()) { 527 } else if (entry.IsFunction()) {
568 // Local closure function. 528 // Local closure function.
569 target ^= entry.raw(); 529 target ^= entry.raw();
570 AddFunction(target); 530 AddFunction(target);
571 } else if (entry.IsCode()) { 531 } else if (entry.IsCode()) {
572 target_code ^= entry.raw(); 532 target_code ^= entry.raw();
573 if (target_code.IsAllocationStubCode()) { 533 if (target_code.IsAllocationStubCode()) {
574 cls ^= target_code.owner(); 534 cls ^= target_code.owner();
575 AddInstantiatedClass(cls); 535 AddInstantiatedClass(cls);
576 } 536 }
537 } else if (entry.IsTypeArguments()) {
538 AddTypeArguments(TypeArguments::Cast(entry));
577 } 539 }
578 } 540 }
579 } 541 }
580 } 542 }
581 543
582 544
545 void Precompiler::AddTypesOf(const Class& cls) {
546 if (cls.IsNull()) return;
547 if (classes_to_retain_.Lookup(&cls) != NULL) return;
548 classes_to_retain_.Insert(&Class::ZoneHandle(Z, cls.raw()));
549
550 Array& interfaces = Array::Handle(Z, cls.interfaces());
551 AbstractType& type = AbstractType::Handle(Z);
552 for (intptr_t i = 0; i < interfaces.Length(); i++) {
553 type ^= interfaces.At(i);
554 AddType(type);
555 }
556
557 AddTypeArguments(TypeArguments::Handle(Z, cls.type_parameters()));
558
559 type = cls.super_type();
560 AddType(type);
561
562 type = cls.mixin();
563 AddType(type);
564
565 if (cls.IsTypedefClass()) {
566 AddTypesOf(Function::Handle(Z, cls.signature_function()));
567 }
568 }
569
570
571 void Precompiler::AddTypesOf(const Function& function) {
572 AbstractType& type = AbstractType::Handle(Z);
573 type = function.result_type();
574 AddType(type);
575 for (intptr_t i = 0; i < function.NumParameters(); i++) {
576 type = function.ParameterTypeAt(i);
577 AddType(type);
578 }
579 }
580
581
582 void Precompiler::AddType(const AbstractType& abstype) {
583 if (abstype.IsNull()) return;
584
585 if (types_to_retain_.Lookup(&abstype) != NULL) return;
586 types_to_retain_.Insert(&AbstractType::ZoneHandle(Z, abstype.raw()));
587
588 if (abstype.IsType()) {
589 const Type& type = Type::Cast(abstype);
590 const Class& cls = Class::Handle(Z, type.type_class());
591 AddTypesOf(cls);
592 const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
593 AddTypeArguments(vector);
594 } else if (abstype.IsFunctionType()) {
595 const FunctionType& func_type = FunctionType::Cast(abstype);
596 const Class& cls = Class::Handle(Z, func_type.scope_class());
597 AddTypesOf(cls);
598 const Function& func = Function::Handle(Z, func_type.signature());
599 AddTypesOf(func);
600 const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
601 AddTypeArguments(vector);
602 } else if (abstype.IsBoundedType()) {
603 AbstractType& type = AbstractType::Handle(Z);
604 type = BoundedType::Cast(abstype).type();
605 AddType(type);
606 type = BoundedType::Cast(abstype).bound();
607 AddType(type);
608 } else if (abstype.IsTypeRef()) {
609 AbstractType& type = AbstractType::Handle(Z);
610 type = TypeRef::Cast(abstype).type();
611 AddType(type);
612 }
613 }
614
615
616 void Precompiler::AddTypeArguments(const TypeArguments& args) {
617 if (args.IsNull()) return;
618
619 if (typeargs_to_retain_.Lookup(&args) != NULL) return;
620 typeargs_to_retain_.Insert(&TypeArguments::ZoneHandle(Z, args.raw()));
621
622 AbstractType& arg = AbstractType::Handle(Z);
623 for (intptr_t i = 0; i < args.Length(); i++) {
624 arg = args.TypeAt(i);
625 AddType(arg);
626 }
627 }
628
629
583 void Precompiler::AddConstObject(const Instance& instance) { 630 void Precompiler::AddConstObject(const Instance& instance) {
584 const Class& cls = Class::Handle(Z, instance.clazz()); 631 const Class& cls = Class::Handle(Z, instance.clazz());
585 AddInstantiatedClass(cls); 632 AddInstantiatedClass(cls);
586 633
587 if (instance.IsClosure()) { 634 if (instance.IsClosure()) {
588 // An implicit static closure. 635 // An implicit static closure.
589 const Function& func = 636 const Function& func =
590 Function::Handle(Z, Closure::Cast(instance).function()); 637 Function::Handle(Z, Closure::Cast(instance).function());
591 ASSERT(func.is_static()); 638 ASSERT(func.is_static());
592 AddFunction(func); 639 AddFunction(func);
640 AddTypeArguments(TypeArguments::Handle(Z, instance.GetTypeArguments()));
593 return; 641 return;
594 } 642 }
595 643
596 // Can't ask immediate objects if they're canoncial. 644 // Can't ask immediate objects if they're canoncial.
597 if (instance.IsSmi()) return; 645 if (instance.IsSmi()) return;
598 646
599 // Some Instances in the ObjectPool aren't const objects, such as 647 // Some Instances in the ObjectPool aren't const objects, such as
600 // argument descriptors. 648 // argument descriptors.
601 if (!instance.IsCanonical()) return; 649 if (!instance.IsCanonical()) return;
602 650
651 if (cls.NumTypeArguments() > 0) {
652 AddTypeArguments(TypeArguments::Handle(Z, instance.GetTypeArguments()));
653 }
654
603 class ConstObjectVisitor : public ObjectPointerVisitor { 655 class ConstObjectVisitor : public ObjectPointerVisitor {
604 public: 656 public:
605 ConstObjectVisitor(Precompiler* precompiler, Isolate* isolate) : 657 ConstObjectVisitor(Precompiler* precompiler, Isolate* isolate) :
606 ObjectPointerVisitor(isolate), 658 ObjectPointerVisitor(isolate),
607 precompiler_(precompiler), 659 precompiler_(precompiler),
608 subinstance_(Object::Handle()) {} 660 subinstance_(Object::Handle()) {}
609 661
610 virtual void VisitPointers(RawObject** first, RawObject** last) { 662 virtual void VisitPointers(RawObject** first, RawObject** last) {
611 for (RawObject** current = first; current <= last; current++) { 663 for (RawObject** current = first; current <= last; current++) {
612 subinstance_ = *current; 664 subinstance_ = *current;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 AddCalleesOf(function); 727 AddCalleesOf(function);
676 } 728 }
677 } 729 }
678 } 730 }
679 731
680 732
681 RawFunction* Precompiler::CompileStaticInitializer(const Field& field) { 733 RawFunction* Precompiler::CompileStaticInitializer(const Field& field) {
682 ASSERT(field.is_static()); 734 ASSERT(field.is_static());
683 if (field.HasPrecompiledInitializer()) { 735 if (field.HasPrecompiledInitializer()) {
684 // TODO(rmacnak): Investigate why this happens for _enum_names. 736 // TODO(rmacnak): Investigate why this happens for _enum_names.
685 OS::Print("Warning: Ignoring repeated request for initializer for %s\n", 737 THR_Print("Warning: Ignoring repeated request for initializer for %s\n",
686 field.ToCString()); 738 field.ToCString());
687 return Function::null(); 739 return Function::null();
688 } 740 }
689 Thread* thread = Thread::Current(); 741 Thread* thread = Thread::Current();
690 StackZone zone(thread); 742 StackZone zone(thread);
691 743
692 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); 744 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
693 745
694 parsed_function->AllocateVariables(); 746 parsed_function->AllocateVariables();
695 // Non-optimized code generator. 747 // Non-optimized code generator.
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 // It can happen that all uses of an implicit closure inline their 1187 // It can happen that all uses of an implicit closure inline their
1136 // target function, leaving the target function uncompiled. Keep 1188 // target function, leaving the target function uncompiled. Keep
1137 // the target function anyway so we can enumerate it to bind its 1189 // the target function anyway so we can enumerate it to bind its
1138 // static calls, etc. 1190 // static calls, etc.
1139 function2 = function.ImplicitClosureFunction(); 1191 function2 = function.ImplicitClosureFunction();
1140 retain = function2.HasCode(); 1192 retain = function2.HasCode();
1141 } 1193 }
1142 if (retain) { 1194 if (retain) {
1143 retained_functions.Add(function); 1195 retained_functions.Add(function);
1144 function.DropUncompiledImplicitClosureFunction(); 1196 function.DropUncompiledImplicitClosureFunction();
1197 AddTypesOf(function);
1145 } else { 1198 } else {
1146 bool top_level = cls.IsTopLevel(); 1199 bool top_level = cls.IsTopLevel();
1147 if (top_level && 1200 if (top_level &&
1148 (function.kind() != RawFunction::kImplicitStaticFinalGetter)) { 1201 (function.kind() != RawFunction::kImplicitStaticFinalGetter)) {
1149 // Implicit static final getters are not added to the library 1202 // Implicit static final getters are not added to the library
1150 // dictionary in the first place. 1203 // dictionary in the first place.
1151 name = function.DictionaryName(); 1204 name = function.DictionaryName();
1152 bool removed = lib.RemoveObject(function, name); 1205 bool removed = lib.RemoveObject(function, name);
1153 ASSERT(removed); 1206 ASSERT(removed);
1154 } 1207 }
(...skipping 11 matching lines...) Expand all
1166 } else { 1219 } else {
1167 cls.SetFunctions(Object::empty_array()); 1220 cls.SetFunctions(Object::empty_array());
1168 } 1221 }
1169 } 1222 }
1170 } 1223 }
1171 1224
1172 closures = isolate()->object_store()->closure_functions(); 1225 closures = isolate()->object_store()->closure_functions();
1173 retained_functions = GrowableObjectArray::New(); 1226 retained_functions = GrowableObjectArray::New();
1174 for (intptr_t j = 0; j < closures.Length(); j++) { 1227 for (intptr_t j = 0; j < closures.Length(); j++) {
1175 function ^= closures.At(j); 1228 function ^= closures.At(j);
1176 if (function.HasCode()) { 1229 bool retain = function.HasCode();
1230 if (retain) {
1177 retained_functions.Add(function); 1231 retained_functions.Add(function);
1232 AddTypesOf(function);
1178 } else { 1233 } else {
1179 dropped_function_count_++; 1234 dropped_function_count_++;
1180 if (FLAG_trace_precompiler) { 1235 if (FLAG_trace_precompiler) {
1181 THR_Print("Precompilation dropping %s\n", 1236 THR_Print("Precompilation dropping %s\n",
1182 function.ToLibNamePrefixedQualifiedCString()); 1237 function.ToLibNamePrefixedQualifiedCString());
1183 } 1238 }
1184 } 1239 }
1185 } 1240 }
1186 isolate()->object_store()->set_closure_functions(retained_functions); 1241 isolate()->object_store()->set_closure_functions(retained_functions);
1187 } 1242 }
1188 1243
1189 1244
1190 void Precompiler::DropFields() { 1245 void Precompiler::DropFields() {
1191 Library& lib = Library::Handle(Z); 1246 Library& lib = Library::Handle(Z);
1192 Class& cls = Class::Handle(Z); 1247 Class& cls = Class::Handle(Z);
1193 Array& fields = Array::Handle(Z); 1248 Array& fields = Array::Handle(Z);
1194 Field& field = Field::Handle(Z); 1249 Field& field = Field::Handle(Z);
1195 GrowableObjectArray& retained_fields = GrowableObjectArray::Handle(Z); 1250 GrowableObjectArray& retained_fields = GrowableObjectArray::Handle(Z);
1196 String& name = String::Handle(Z); 1251 String& name = String::Handle(Z);
1252 AbstractType& type = AbstractType::Handle(Z);
1197 1253
1198 for (intptr_t i = 0; i < libraries_.Length(); i++) { 1254 for (intptr_t i = 0; i < libraries_.Length(); i++) {
1199 lib ^= libraries_.At(i); 1255 lib ^= libraries_.At(i);
1200 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); 1256 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
1201 while (it.HasNext()) { 1257 while (it.HasNext()) {
1202 cls = it.GetNextClass(); 1258 cls = it.GetNextClass();
1203 if (cls.IsDynamicClass()) { 1259 if (cls.IsDynamicClass()) {
1204 continue; // class 'dynamic' is in the read-only VM isolate. 1260 continue; // class 'dynamic' is in the read-only VM isolate.
1205 } 1261 }
1206 1262
1207 fields = cls.fields(); 1263 fields = cls.fields();
1208 retained_fields = GrowableObjectArray::New(); 1264 retained_fields = GrowableObjectArray::New();
1209 for (intptr_t j = 0; j < fields.Length(); j++) { 1265 for (intptr_t j = 0; j < fields.Length(); j++) {
1210 field ^= fields.At(j); 1266 field ^= fields.At(j);
1211 bool retain = fields_to_retain_.Lookup(&field) != NULL; 1267 bool retain = fields_to_retain_.Lookup(&field) != NULL;
1212 if (retain) { 1268 if (retain) {
1213 retained_fields.Add(field); 1269 retained_fields.Add(field);
1270 type = field.type();
1271 AddType(type);
1214 } else { 1272 } else {
1215 bool top_level = cls.IsTopLevel(); 1273 bool top_level = cls.IsTopLevel();
1216 if (top_level) { 1274 if (top_level) {
1217 name = field.DictionaryName(); 1275 name = field.DictionaryName();
1218 bool removed = lib.RemoveObject(field, name); 1276 bool removed = lib.RemoveObject(field, name);
1219 ASSERT(removed); 1277 ASSERT(removed);
1220 } 1278 }
1221 dropped_field_count_++; 1279 dropped_field_count_++;
1222 if (FLAG_trace_precompiler) { 1280 if (FLAG_trace_precompiler) {
1223 THR_Print("Precompilation dropping %s\n", 1281 THR_Print("Precompilation dropping %s\n",
1224 field.ToCString()); 1282 field.ToCString());
1225 } 1283 }
1226 } 1284 }
1227 } 1285 }
1228 1286
1229 if (retained_fields.Length() > 0) { 1287 if (retained_fields.Length() > 0) {
1230 fields = Array::MakeArray(retained_fields); 1288 fields = Array::MakeArray(retained_fields);
1231 cls.SetFields(fields); 1289 cls.SetFields(fields);
1232 } else { 1290 } else {
1233 cls.SetFields(Object::empty_array()); 1291 cls.SetFields(Object::empty_array());
1234 } 1292 }
1235 } 1293 }
1236 } 1294 }
1237 } 1295 }
1238 1296
1239 1297
1298 void Precompiler::DropTypes() {
1299 Library& lib = Library::Handle(Z);
1300 Class& cls = Class::Handle(Z);
1301 Object& obj = Object::Handle(Z);
1302 Array& arr = Array::Handle(Z);
1303 GrowableObjectArray& retained_types = GrowableObjectArray::Handle(Z);
1304 AbstractType& type = AbstractType::Handle(Z);
1305
1306 for (intptr_t i = 0; i < libraries_.Length(); i++) {
1307 lib ^= libraries_.At(i);
1308 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
1309 while (it.HasNext()) {
1310 cls = it.GetNextClass();
1311 if (cls.IsDynamicClass()) {
1312 continue; // class 'dynamic' is in the read-only VM isolate.
1313 }
1314 obj = cls.canonical_types();
1315 if (!obj.IsArray()) {
1316 // Class only has one type, keep it.
1317 } else {
1318 // Class has many types.
1319 arr ^= obj.raw();
1320 retained_types = GrowableObjectArray::New();
1321
1322 // Always keep the first one.
1323 ASSERT(arr.Length() >= 1);
1324 obj = arr.At(0);
1325 retained_types.Add(obj);
1326
1327 for (intptr_t i = 1; i < arr.Length(); i++) {
1328 obj = arr.At(i);
1329 if (obj.IsNull()) {
1330 continue;
1331 }
1332 type ^= obj.raw();
1333 bool retain = types_to_retain_.Lookup(&type) != NULL;
1334 if (retain) {
1335 retained_types.Add(type);
1336 } else {
1337 dropped_type_count_++;
1338 }
1339 }
1340 arr = Array::MakeArray(retained_types);
1341 cls.set_canonical_types(arr);
1342 }
1343 }
1344 }
1345 }
1346
1347
1348 void Precompiler::DropTypeArguments() {
1349 const Array& typeargs_table =
1350 Array::Handle(Z, I->object_store()->canonical_type_arguments());
1351 GrowableObjectArray& retained_typeargs =
1352 GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
1353 TypeArguments& typeargs = TypeArguments::Handle(Z);
1354 for (intptr_t i = 0; i < (typeargs_table.Length() - 1); i++) {
1355 typeargs ^= typeargs_table.At(i);
1356 bool retain = typeargs_to_retain_.Lookup(&typeargs) != NULL;
1357 if (retain) {
1358 retained_typeargs.Add(typeargs);
1359 } else {
1360 dropped_typearg_count_++;
1361 }
1362 }
1363
1364 const intptr_t dict_size =
1365 Utils::RoundUpToPowerOfTwo(retained_typeargs.Length() * 4 / 3);
1366 const Array& new_table = Array::Handle(Z, Array::New(dict_size + 1));
1367
1368 Object& element = Object::Handle(Z);
1369 for (intptr_t i = 0; i < retained_typeargs.Length(); i++) {
1370 typeargs ^= retained_typeargs.At(i);
1371 intptr_t hash = typeargs.Hash();
1372 intptr_t index = hash & (dict_size - 1);
1373 element = new_table.At(index);
1374 while (!element.IsNull()) {
1375 index = (index + 1) & (dict_size - 1);
1376 element = new_table.At(index);
1377 }
1378 new_table.SetAt(index, typeargs);
1379 }
1380
1381 const Smi& used = Smi::Handle(Z, Smi::New(retained_typeargs.Length()));
1382 new_table.SetAt(dict_size, used);
1383
1384 I->object_store()->set_canonical_type_arguments(new_table);
1385 }
1386
1387
1388 void Precompiler::TraceTypesFromRetainedClasses() {
1389 Library& lib = Library::Handle(Z);
1390 Class& cls = Class::Handle(Z);
1391 Array& members = Array::Handle(Z);
1392
1393 for (intptr_t i = 0; i < libraries_.Length(); i++) {
1394 lib ^= libraries_.At(i);
1395 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
1396 while (it.HasNext()) {
1397 cls = it.GetNextClass();
1398 if (cls.IsDynamicClass()) {
1399 continue; // class 'dynamic' is in the read-only VM isolate.
1400 }
1401
1402 // The subclasses array is only needed for CHA.
1403 cls.ClearDirectSubclasses();
1404
1405 bool retain = false;
1406 members = cls.fields();
1407 if (members.Length() > 0) {
1408 retain = true;
1409 }
1410 members = cls.functions();
1411 if (members.Length() > 0) {
1412 retain = true;
1413 }
1414 if (cls.is_allocated()) {
1415 retain = true;
1416 }
1417 if (cls.is_enum_class()) {
1418 // Enum classes have live instances, so we cannot unregister
1419 // them.
1420 retain = true;
1421 }
1422 members = cls.constants();
1423 if (members.Length() > 0) {
1424 // --compile_all?
1425 retain = true;
1426 }
1427
1428 if (retain) {
1429 AddTypesOf(cls);
1430 }
1431 }
1432 }
1433 }
1434
1435
1436 void Precompiler::DropClasses() {
1437 Library& lib = Library::Handle(Z);
1438 Class& cls = Class::Handle(Z);
1439 Array& members = Array::Handle(Z);
1440 String& name = String::Handle(Z);
1441
1442 #if defined(DEBUG)
1443 {
1444 // Force GC for allocation stats.
1445 I->heap()->CollectAllGarbage();
1446 }
1447 #endif
1448
1449 ClassTable* class_table = I->class_table();
1450 intptr_t num_cids = class_table->NumCids();
1451
1452 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
1453 if (!class_table->IsValidIndex(cid)) continue;
1454 if (!class_table->HasValidClassAt(cid)) continue;
1455
1456 cls = class_table->At(cid);
1457 ASSERT(!cls.IsNull());
1458
1459 if (cls.IsTopLevel()) {
1460 // Top-level classes are referenced directly from their library. They
1461 // will only be removed as a consequence of an entire library being
1462 // removed.
1463 continue;
1464 }
1465 if (cls.is_enum_class()) {
1466 // Enum classes have live instances, so we cannot unregister
1467 // them.
1468 continue;
1469 }
1470 members = cls.constants();
1471 if (members.Length() > 0) {
1472 // --compile_all?
1473 continue;
1474 }
1475
1476 bool retain = classes_to_retain_.Lookup(&cls) != NULL;
1477 if (retain) {
1478 continue;
1479 }
1480
1481 #if defined(DEBUG)
1482 intptr_t instances =
1483 class_table->StatsWithUpdatedSize(cid)->post_gc.new_count +
1484 class_table->StatsWithUpdatedSize(cid)->post_gc.old_count;
1485 if (instances != 0) {
1486 FATAL2("Want to drop class %s, but it has %" Pd " instances\n",
1487 cls.ToCString(),
1488 instances);
1489 }
1490 #endif
1491
1492 dropped_class_count_++;
1493 if (FLAG_trace_precompiler) {
1494 THR_Print("Precompilation dropping %" Pd " %s\n", cid, cls.ToCString());
1495 }
1496
1497 #if defined(DEBUG)
1498 class_table->Unregister(cid);
1499 #endif
1500 cls.set_id(kIllegalCid); // We check this when serializing.
1501
1502 lib = cls.library();
1503 name = cls.DictionaryName();
1504 lib.RemoveObject(cls, name);
1505 }
1506 }
1507
1508
1509 void Precompiler::DropLibraries() {
1510 const GrowableObjectArray& retained_libraries =
1511 GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
1512 Library& lib = Library::Handle(Z);
1513
1514 for (intptr_t i = 0; i < libraries_.Length(); i++) {
1515 lib ^= libraries_.At(i);
1516 lib.DropDependencies();
1517 intptr_t entries = 0;
1518 DictionaryIterator it(lib);
1519 while (it.HasNext()) {
1520 it.GetNext();
1521 entries++;
1522 }
1523 bool retain = (entries > 0) || lib.is_dart_scheme();
1524 if (retain) {
1525 lib.set_index(retained_libraries.Length());
1526 retained_libraries.Add(lib);
1527 } else {
1528 dropped_library_count_++;
1529 lib.set_index(-1);
1530 if (FLAG_trace_precompiler) {
1531 THR_Print("Precompilation dropping %s\n", lib.ToCString());
1532 }
1533 }
1534 }
1535
1536 I->object_store()->set_libraries(retained_libraries);
1537 libraries_ = retained_libraries.raw();
1538 }
1539
1540
1240 void Precompiler::BindStaticCalls() { 1541 void Precompiler::BindStaticCalls() {
1241 class BindStaticCallsVisitor : public FunctionVisitor { 1542 class BindStaticCallsVisitor : public FunctionVisitor {
1242 public: 1543 public:
1243 explicit BindStaticCallsVisitor(Zone* zone) : 1544 explicit BindStaticCallsVisitor(Zone* zone) :
1244 code_(Code::Handle(zone)), 1545 code_(Code::Handle(zone)),
1245 table_(Array::Handle(zone)), 1546 table_(Array::Handle(zone)),
1246 pc_offset_(Smi::Handle(zone)), 1547 pc_offset_(Smi::Handle(zone)),
1247 target_(Function::Handle(zone)), 1548 target_(Function::Handle(zone)),
1248 target_code_(Code::Handle(zone)) { 1549 target_code_(Code::Handle(zone)) {
1249 } 1550 }
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after
2228 CompilationPipeline::New(thread->zone(), function); 2529 CompilationPipeline::New(thread->zone(), function);
2229 2530
2230 ASSERT(FLAG_precompilation); 2531 ASSERT(FLAG_precompilation);
2231 const bool optimized = function.IsOptimizable(); // False for natives. 2532 const bool optimized = function.IsOptimizable(); // False for natives.
2232 return PrecompileFunctionHelper(pipeline, function, optimized); 2533 return PrecompileFunctionHelper(pipeline, function, optimized);
2233 } 2534 }
2234 2535
2235 #endif // DART_PRECOMPILER 2536 #endif // DART_PRECOMPILER
2236 2537
2237 } // namespace dart 2538 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/precompiler.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698