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

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
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 // TODO(rmacnak): Probably don't need to remember imports/exports either.
212 DropLibraries();
202 213
203 BindStaticCalls(); 214 BindStaticCalls();
204 215
205 DedupStackmaps(); 216 DedupStackmaps();
206 DedupStackmapLists(); 217 DedupStackmapLists();
207 218
208 if (FLAG_dedup_instructions) { 219 if (FLAG_dedup_instructions) {
209 // Reduces binary size but obfuscates profiler results. 220 // Reduces binary size but obfuscates profiler results.
210 DedupInstructions(); 221 DedupInstructions();
211 } 222 }
212 223
213 I->object_store()->set_compile_time_constants(Array::null_array()); 224 I->object_store()->set_compile_time_constants(Array::null_array());
214 I->object_store()->set_unique_dynamic_targets(Array::null_array()); 225 I->object_store()->set_unique_dynamic_targets(Array::null_array());
215 226
216 zone_ = NULL; 227 zone_ = NULL;
217 } 228 }
218 229
219 intptr_t dropped_symbols_count = Symbols::Compact(I); 230 intptr_t dropped_symbols_count = Symbols::Compact(I);
220 231
221 if (FLAG_trace_precompiler) { 232 if (FLAG_trace_precompiler) {
222 THR_Print("Precompiled %" Pd " functions, %" Pd " dynamic types," 233 THR_Print("Precompiled %" Pd " functions,", function_count_);
223 " %" Pd " dynamic selectors.\n Dropped %" Pd " functions, %" Pd 234 THR_Print(" %" Pd " dynamic types,", class_count_);
224 " fields, %" Pd " symbols.\n", 235 THR_Print(" %" Pd " dynamic selectors.\n", selector_count_);
225 function_count_, 236
226 class_count_, 237 THR_Print("Dropped %" Pd " functions,", dropped_function_count_);
227 selector_count_, 238 THR_Print(" %" Pd " fields,", dropped_field_count_);
228 dropped_function_count_, 239 THR_Print(" %" Pd " symbols,", dropped_symbols_count);
229 dropped_field_count_, 240 THR_Print(" %" Pd " types,", dropped_type_count_);
230 dropped_symbols_count); 241 THR_Print(" %" Pd " type arguments,", dropped_typearg_count_);
242 THR_Print(" %" Pd " classes,", dropped_class_count_);
243 THR_Print(" %" Pd " libraries.\n", dropped_library_count_);
231 } 244 }
232 } 245 }
233 246
234 247
235 void Precompiler::ClearAllCode() { 248 void Precompiler::ClearAllCode() {
236 class ClearCodeFunctionVisitor : public FunctionVisitor { 249 class ClearCodeFunctionVisitor : public FunctionVisitor {
237 void VisitFunction(const Function& function) { 250 void VisitFunction(const Function& function) {
238 function.ClearCode(); 251 function.ClearCode();
252 function.ClearICDataArray();
239 } 253 }
240 }; 254 };
241 ClearCodeFunctionVisitor visitor; 255 ClearCodeFunctionVisitor visitor;
242 VisitFunctions(&visitor); 256 VisitFunctions(&visitor);
243 } 257 }
244 258
245 259
246 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { 260 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) {
247 // Note that <rootlibrary>.main is not a root. The appropriate main will be 261 // Note that <rootlibrary>.main is not a root. The appropriate main will be
248 // discovered through _getMainClosure. 262 // discovered through _getMainClosure.
249 263
250 AddSelector(Symbols::NoSuchMethod()); 264 AddSelector(Symbols::NoSuchMethod());
251 265
252 AddSelector(Symbols::Call()); // For speed, not correctness. 266 AddSelector(Symbols::Call()); // For speed, not correctness.
253 267
254 // Allocated from C++. 268 // 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); 269 Class& cls = Class::Handle(Z);
324 for (intptr_t i = 0; kExternallyAllocatedCids[i] != kIllegalCid; i++) { 270 for (intptr_t cid = kInstanceCid; cid < kNumPredefinedCids; cid++) {
325 cls = isolate()->class_table()->At(kExternallyAllocatedCids[i]); 271 ASSERT(isolate()->class_table()->IsValidIndex(cid));
272 if (!isolate()->class_table()->HasValidClassAt(cid)) {
273 continue;
274 }
275 if ((cid == kDynamicCid) ||
276 (cid == kVoidCid) ||
277 (cid == kFreeListElement)) {
278 continue;
279 }
280 cls = isolate()->class_table()->At(cid);
326 AddInstantiatedClass(cls); 281 AddInstantiatedClass(cls);
327 } 282 }
328 283
329 Dart_QualifiedFunctionName vm_entry_points[] = { 284 Dart_QualifiedFunctionName vm_entry_points[] = {
330 // Functions 285 // Functions
331 { "dart:async", "::", "_setScheduleImmediateClosure" }, 286 { "dart:async", "::", "_setScheduleImmediateClosure" },
332 { "dart:core", "::", "_completeDeferredLoads"}, 287 { "dart:core", "::", "_completeDeferredLoads" },
333 { "dart:core", "AbstractClassInstantiationError", 288 { "dart:core", "AbstractClassInstantiationError",
334 "AbstractClassInstantiationError._create" }, 289 "AbstractClassInstantiationError._create" },
335 { "dart:core", "ArgumentError", "ArgumentError." }, 290 { "dart:core", "ArgumentError", "ArgumentError." },
336 { "dart:core", "CyclicInitializationError", 291 { "dart:core", "CyclicInitializationError",
337 "CyclicInitializationError." }, 292 "CyclicInitializationError." },
338 { "dart:core", "FallThroughError", "FallThroughError._create" }, 293 { "dart:core", "FallThroughError", "FallThroughError._create" },
339 { "dart:core", "FormatException", "FormatException." }, 294 { "dart:core", "FormatException", "FormatException." },
340 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" }, 295 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" },
341 { "dart:core", "NullThrownError", "NullThrownError." }, 296 { "dart:core", "NullThrownError", "NullThrownError." },
342 { "dart:core", "OutOfMemoryError", "OutOfMemoryError." }, 297 { "dart:core", "OutOfMemoryError", "OutOfMemoryError." },
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 Function::KindToCString(function.kind())); 431 Function::KindToCString(function.kind()));
477 } 432 }
478 433
479 ASSERT(!function.is_abstract()); 434 ASSERT(!function.is_abstract());
480 ASSERT(!function.IsRedirectingFactory()); 435 ASSERT(!function.IsRedirectingFactory());
481 436
482 error_ = CompileFunction(thread_, function); 437 error_ = CompileFunction(thread_, function);
483 if (!error_.IsNull()) { 438 if (!error_.IsNull()) {
484 Jump(error_); 439 Jump(error_);
485 } 440 }
441 // Used in the JIT to save type-feedback across compilations.
442 function.ClearICDataArray();
486 } else { 443 } else {
487 if (FLAG_trace_precompiler) { 444 if (FLAG_trace_precompiler) {
488 // This function was compiled from somewhere other than Precompiler, 445 // This function was compiled from somewhere other than Precompiler,
489 // such as const constructors compiled by the parser. 446 // such as const constructors compiled by the parser.
490 THR_Print("Already has code: %s (%s, %s)\n", 447 THR_Print("Already has code: %s (%s, %s)\n",
491 function.ToLibNamePrefixedQualifiedCString(), 448 function.ToLibNamePrefixedQualifiedCString(),
492 function.token_pos().ToCString(), 449 function.token_pos().ToCString(),
493 Function::KindToCString(function.kind())); 450 Function::KindToCString(function.kind()));
494 } 451 }
495 } 452 }
496 453
497 ASSERT(function.HasCode()); 454 ASSERT(function.HasCode());
498 AddCalleesOf(function); 455 AddCalleesOf(function);
499 } 456 }
500 457
501 458
502 void Precompiler::AddCalleesOf(const Function& function) { 459 void Precompiler::AddCalleesOf(const Function& function) {
503 ASSERT(function.HasCode()); 460 ASSERT(function.HasCode());
504 461
505 const Code& code = Code::Handle(Z, function.CurrentCode()); 462 const Code& code = Code::Handle(Z, function.CurrentCode());
506 463
507 const Array& table = Array::Handle(Z, code.static_calls_target_table()); 464 const Array& table = Array::Handle(Z, code.static_calls_target_table());
508 Object& entry = Object::Handle(Z); 465 Object& entry = Object::Handle(Z);
509 Function& target = Function::Handle(Z); 466 Function& target = Function::Handle(Z);
510 for (intptr_t i = 0; i < table.Length(); i++) { 467 for (intptr_t i = 0; i < table.Length(); i++) {
511 entry = table.At(i); 468 entry = table.At(i);
512 if (entry.IsFunction()) { 469 if (entry.IsFunction()) {
513 target ^= table.At(i); 470 target ^= entry.raw();
514 AddFunction(target); 471 AddFunction(target);
515 } 472 }
516 } 473 }
517 474
518 #if defined(TARGET_ARCH_IA32) 475 #if defined(TARGET_ARCH_IA32)
519 FATAL("Callee scanning unimplemented for IA32"); 476 FATAL("Callee scanning unimplemented for IA32");
520 #endif 477 #endif
521 478
522 const ObjectPool& pool = ObjectPool::Handle(Z, code.GetObjectPool()); 479 const ObjectPool& pool = ObjectPool::Handle(Z, code.GetObjectPool());
523 ICData& call_site = ICData::Handle(Z); 480 ICData& call_site = ICData::Handle(Z);
524 MegamorphicCache& cache = MegamorphicCache::Handle(Z); 481 MegamorphicCache& cache = MegamorphicCache::Handle(Z);
525 String& selector = String::Handle(Z); 482 String& selector = String::Handle(Z);
526 Field& field = Field::Handle(Z); 483 Field& field = Field::Handle(Z);
527 Class& cls = Class::Handle(Z); 484 Class& cls = Class::Handle(Z);
528 Instance& instance = Instance::Handle(Z); 485 Instance& instance = Instance::Handle(Z);
529 Code& target_code = Code::Handle(Z); 486 Code& target_code = Code::Handle(Z);
530 for (intptr_t i = 0; i < pool.Length(); i++) { 487 for (intptr_t i = 0; i < pool.Length(); i++) {
531 if (pool.InfoAt(i) == ObjectPool::kTaggedObject) { 488 if (pool.InfoAt(i) == ObjectPool::kTaggedObject) {
532 entry = pool.ObjectAt(i); 489 entry = pool.ObjectAt(i);
533 if (entry.IsICData()) { 490 if (entry.IsICData()) {
534 call_site ^= entry.raw(); 491 call_site ^= entry.raw();
535 if (call_site.NumberOfChecks() == 1) { 492 for (intptr_t j = 0; j < call_site.NumberOfChecks(); j++) {
536 // Probably a static call. 493 target = call_site.GetTargetAt(j);
537 target = call_site.GetTargetAt(0);
538 AddFunction(target); 494 AddFunction(target);
539 if (!target.is_static()) { 495 if (!target.is_static()) {
540 // Super call (should not enqueue selector) or dynamic call with a 496 // Super call (should not enqueue selector) or dynamic call with a
541 // CHA prediction (should enqueue selector). 497 // CHA prediction (should enqueue selector).
542 selector = call_site.target_name(); 498 selector = call_site.target_name();
543 AddSelector(selector); 499 AddSelector(selector);
544 } 500 }
545 } else { 501 }
502 if (call_site.NumberOfChecks() == 0) {
546 // A dynamic call. 503 // A dynamic call.
547 selector = call_site.target_name(); 504 selector = call_site.target_name();
548 AddSelector(selector); 505 AddSelector(selector);
549 if (selector.raw() == Symbols::Call().raw()) { 506 if (selector.raw() == Symbols::Call().raw()) {
550 // Potential closure call. 507 // Potential closure call.
551 AddClosureCall(call_site); 508 AddClosureCall(call_site);
552 } 509 }
553 } 510 }
554 } else if (entry.IsMegamorphicCache()) { 511 } else if (entry.IsMegamorphicCache()) {
555 // A dynamic call. 512 // A dynamic call.
556 cache ^= entry.raw(); 513 cache ^= entry.raw();
557 selector = cache.target_name(); 514 selector = cache.target_name();
558 AddSelector(selector); 515 AddSelector(selector);
559 } else if (entry.IsField()) { 516 } else if (entry.IsField()) {
560 // Potential need for field initializer. 517 // Potential need for field initializer.
561 field ^= entry.raw(); 518 field ^= entry.raw();
562 AddField(field); 519 AddField(field);
563 } else if (entry.IsInstance()) { 520 } else if (entry.IsInstance()) {
564 // Const object, literal or args descriptor. 521 // Const object, literal or args descriptor.
565 instance ^= entry.raw(); 522 instance ^= entry.raw();
566 AddConstObject(instance); 523 if (entry.IsAbstractType()) {
524 AddType(AbstractType::Cast(entry));
525 } else {
526 AddConstObject(instance);
527 }
567 } else if (entry.IsFunction()) { 528 } else if (entry.IsFunction()) {
568 // Local closure function. 529 // Local closure function.
569 target ^= entry.raw(); 530 target ^= entry.raw();
570 AddFunction(target); 531 AddFunction(target);
571 } else if (entry.IsCode()) { 532 } else if (entry.IsCode()) {
572 target_code ^= entry.raw(); 533 target_code ^= entry.raw();
573 if (target_code.IsAllocationStubCode()) { 534 if (target_code.IsAllocationStubCode()) {
574 cls ^= target_code.owner(); 535 cls ^= target_code.owner();
575 AddInstantiatedClass(cls); 536 AddInstantiatedClass(cls);
576 } 537 }
538 } else if (entry.IsTypeArguments()) {
539 AddTypeArguments(TypeArguments::Cast(entry));
577 } 540 }
578 } 541 }
579 } 542 }
580 } 543 }
581 544
582 545
546 void Precompiler::AddTypesOf(const Class& cls) {
547 if (cls.IsNull()) return;
548 if (classes_to_retain_.Lookup(&cls) != NULL) return;
549
550 classes_to_retain_.Insert(&Class::ZoneHandle(Z, cls.raw()));
551
552 Array& interfaces = Array::Handle(Z, cls.interfaces());
553 AbstractType& type = AbstractType::Handle(Z);
554 for (intptr_t i = 0; i < interfaces.Length(); i++) {
555 type ^= interfaces.At(i);
556 AddType(type);
557 }
558
559 AddTypeArguments(TypeArguments::Handle(Z, cls.type_parameters()));
560
561 type = cls.super_type();
562 AddType(type);
563
564 type = cls.mixin();
565 AddType(type);
regis 2016/02/19 20:54:07 I am not sure, but if cls is a typedef, you may al
rmacnak 2016/02/20 01:35:39 Done.
566 }
567
568
569 void Precompiler::AddTypesOf(const Function& function) {
570 AbstractType& type = AbstractType::Handle(Z);
571 type = function.result_type();
572 AddType(type);
573 for (intptr_t i = 0; i < function.NumParameters(); i++) {
574 type = function.ParameterTypeAt(i);
575 AddType(type);
576 }
577 }
578
579
580 void Precompiler::AddType(const AbstractType& abstype) {
581 if (abstype.IsNull()) return;
582
583 if (types_to_retain_.Lookup(&abstype) != NULL) return;
584 types_to_retain_.Insert(&AbstractType::ZoneHandle(Z, abstype.raw()));
585
586 if (abstype.IsType()) {
587 const Type& type = Type::Cast(abstype);
588 const Class& cls = Class::Handle(Z, type.type_class());
589 AddTypesOf(cls);
590
591 const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
592 AddTypeArguments(vector);
regis 2016/02/19 20:54:07 Bad indentation.
rmacnak 2016/02/20 01:35:39 Done.
593 } else if (abstype.IsFunctionType()) {
594 const FunctionType& func_type = FunctionType::Cast(abstype);
595 const Class& cls = Class::Handle(Z, func_type.scope_class());
596 AddTypesOf(cls);
597 const Function& func = Function::Handle(Z, func_type.signature());
598 AddTypesOf(func);
599
600 const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
601 AddTypeArguments(vector);
602 }
regis 2016/02/19 20:54:07 What about BoundedType and TypeRef?
rmacnak 2016/02/20 01:35:39 Added.
603 }
604
605
606 void Precompiler::AddTypeArguments(const TypeArguments& args) {
607 if (args.IsNull()) return;
608
609 if (typeargs_to_retain_.Lookup(&args) != NULL) return;
610 typeargs_to_retain_.Insert(&TypeArguments::ZoneHandle(Z, args.raw()));
611
612 AbstractType& arg = AbstractType::Handle(Z);
613 for (intptr_t i = 0; i < args.Length(); i++) {
614 arg = args.TypeAt(i);
615 AddType(arg);
616 }
617 }
618
619
583 void Precompiler::AddConstObject(const Instance& instance) { 620 void Precompiler::AddConstObject(const Instance& instance) {
584 const Class& cls = Class::Handle(Z, instance.clazz()); 621 const Class& cls = Class::Handle(Z, instance.clazz());
585 AddInstantiatedClass(cls); 622 AddInstantiatedClass(cls);
586 623
587 if (instance.IsClosure()) { 624 if (instance.IsClosure()) {
588 // An implicit static closure. 625 // An implicit static closure.
589 const Function& func = 626 const Function& func =
590 Function::Handle(Z, Closure::Cast(instance).function()); 627 Function::Handle(Z, Closure::Cast(instance).function());
591 ASSERT(func.is_static()); 628 ASSERT(func.is_static());
592 AddFunction(func); 629 AddFunction(func);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 AddCalleesOf(function); 712 AddCalleesOf(function);
676 } 713 }
677 } 714 }
678 } 715 }
679 716
680 717
681 RawFunction* Precompiler::CompileStaticInitializer(const Field& field) { 718 RawFunction* Precompiler::CompileStaticInitializer(const Field& field) {
682 ASSERT(field.is_static()); 719 ASSERT(field.is_static());
683 if (field.HasPrecompiledInitializer()) { 720 if (field.HasPrecompiledInitializer()) {
684 // TODO(rmacnak): Investigate why this happens for _enum_names. 721 // TODO(rmacnak): Investigate why this happens for _enum_names.
685 OS::Print("Warning: Ignoring repeated request for initializer for %s\n", 722 THR_Print("Warning: Ignoring repeated request for initializer for %s\n",
686 field.ToCString()); 723 field.ToCString());
687 return Function::null(); 724 return Function::null();
688 } 725 }
689 Thread* thread = Thread::Current(); 726 Thread* thread = Thread::Current();
690 StackZone zone(thread); 727 StackZone zone(thread);
691 728
692 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); 729 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
693 730
694 parsed_function->AllocateVariables(); 731 parsed_function->AllocateVariables();
695 // Non-optimized code generator. 732 // 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 1172 // It can happen that all uses of an implicit closure inline their
1136 // target function, leaving the target function uncompiled. Keep 1173 // target function, leaving the target function uncompiled. Keep
1137 // the target function anyway so we can enumerate it to bind its 1174 // the target function anyway so we can enumerate it to bind its
1138 // static calls, etc. 1175 // static calls, etc.
1139 function2 = function.ImplicitClosureFunction(); 1176 function2 = function.ImplicitClosureFunction();
1140 retain = function2.HasCode(); 1177 retain = function2.HasCode();
1141 } 1178 }
1142 if (retain) { 1179 if (retain) {
1143 retained_functions.Add(function); 1180 retained_functions.Add(function);
1144 function.DropUncompiledImplicitClosureFunction(); 1181 function.DropUncompiledImplicitClosureFunction();
1182 AddTypesOf(function);
1145 } else { 1183 } else {
1146 bool top_level = cls.IsTopLevel(); 1184 bool top_level = cls.IsTopLevel();
1147 if (top_level && 1185 if (top_level &&
1148 (function.kind() != RawFunction::kImplicitStaticFinalGetter)) { 1186 (function.kind() != RawFunction::kImplicitStaticFinalGetter)) {
1149 // Implicit static final getters are not added to the library 1187 // Implicit static final getters are not added to the library
1150 // dictionary in the first place. 1188 // dictionary in the first place.
1151 name = function.DictionaryName(); 1189 name = function.DictionaryName();
1152 bool removed = lib.RemoveObject(function, name); 1190 bool removed = lib.RemoveObject(function, name);
1153 ASSERT(removed); 1191 ASSERT(removed);
1154 } 1192 }
(...skipping 11 matching lines...) Expand all
1166 } else { 1204 } else {
1167 cls.SetFunctions(Object::empty_array()); 1205 cls.SetFunctions(Object::empty_array());
1168 } 1206 }
1169 } 1207 }
1170 } 1208 }
1171 1209
1172 closures = isolate()->object_store()->closure_functions(); 1210 closures = isolate()->object_store()->closure_functions();
1173 retained_functions = GrowableObjectArray::New(); 1211 retained_functions = GrowableObjectArray::New();
1174 for (intptr_t j = 0; j < closures.Length(); j++) { 1212 for (intptr_t j = 0; j < closures.Length(); j++) {
1175 function ^= closures.At(j); 1213 function ^= closures.At(j);
1176 if (function.HasCode()) { 1214 bool retain = function.HasCode();
1215 if (retain) {
1177 retained_functions.Add(function); 1216 retained_functions.Add(function);
1217 AddTypesOf(function);
1178 } else { 1218 } else {
1179 dropped_function_count_++; 1219 dropped_function_count_++;
1180 if (FLAG_trace_precompiler) { 1220 if (FLAG_trace_precompiler) {
1181 THR_Print("Precompilation dropping %s\n", 1221 THR_Print("Precompilation dropping %s\n",
1182 function.ToLibNamePrefixedQualifiedCString()); 1222 function.ToLibNamePrefixedQualifiedCString());
1183 } 1223 }
1184 } 1224 }
1185 } 1225 }
1186 isolate()->object_store()->set_closure_functions(retained_functions); 1226 isolate()->object_store()->set_closure_functions(retained_functions);
1187 } 1227 }
1188 1228
1189 1229
1190 void Precompiler::DropFields() { 1230 void Precompiler::DropFields() {
1191 Library& lib = Library::Handle(Z); 1231 Library& lib = Library::Handle(Z);
1192 Class& cls = Class::Handle(Z); 1232 Class& cls = Class::Handle(Z);
1193 Array& fields = Array::Handle(Z); 1233 Array& fields = Array::Handle(Z);
1194 Field& field = Field::Handle(Z); 1234 Field& field = Field::Handle(Z);
1195 GrowableObjectArray& retained_fields = GrowableObjectArray::Handle(Z); 1235 GrowableObjectArray& retained_fields = GrowableObjectArray::Handle(Z);
1196 String& name = String::Handle(Z); 1236 String& name = String::Handle(Z);
1237 AbstractType& type = AbstractType::Handle(Z);
1197 1238
1198 for (intptr_t i = 0; i < libraries_.Length(); i++) { 1239 for (intptr_t i = 0; i < libraries_.Length(); i++) {
1199 lib ^= libraries_.At(i); 1240 lib ^= libraries_.At(i);
1200 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); 1241 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
1201 while (it.HasNext()) { 1242 while (it.HasNext()) {
1202 cls = it.GetNextClass(); 1243 cls = it.GetNextClass();
1203 if (cls.IsDynamicClass()) { 1244 if (cls.IsDynamicClass()) {
1204 continue; // class 'dynamic' is in the read-only VM isolate. 1245 continue; // class 'dynamic' is in the read-only VM isolate.
1205 } 1246 }
1206 1247
1207 fields = cls.fields(); 1248 fields = cls.fields();
1208 retained_fields = GrowableObjectArray::New(); 1249 retained_fields = GrowableObjectArray::New();
1209 for (intptr_t j = 0; j < fields.Length(); j++) { 1250 for (intptr_t j = 0; j < fields.Length(); j++) {
1210 field ^= fields.At(j); 1251 field ^= fields.At(j);
1211 bool retain = fields_to_retain_.Lookup(&field) != NULL; 1252 bool retain = fields_to_retain_.Lookup(&field) != NULL;
1212 if (retain) { 1253 if (retain) {
1213 retained_fields.Add(field); 1254 retained_fields.Add(field);
1255 type = field.type();
1256 AddType(type);
1214 } else { 1257 } else {
1215 bool top_level = cls.IsTopLevel(); 1258 bool top_level = cls.IsTopLevel();
1216 if (top_level) { 1259 if (top_level) {
1217 name = field.DictionaryName(); 1260 name = field.DictionaryName();
1218 bool removed = lib.RemoveObject(field, name); 1261 bool removed = lib.RemoveObject(field, name);
1219 ASSERT(removed); 1262 ASSERT(removed);
1220 } 1263 }
1221 dropped_field_count_++; 1264 dropped_field_count_++;
1222 if (FLAG_trace_precompiler) { 1265 if (FLAG_trace_precompiler) {
1223 THR_Print("Precompilation dropping %s\n", 1266 THR_Print("Precompilation dropping %s\n",
1224 field.ToCString()); 1267 field.ToCString());
1225 } 1268 }
1226 } 1269 }
1227 } 1270 }
1228 1271
1229 if (retained_fields.Length() > 0) { 1272 if (retained_fields.Length() > 0) {
1230 fields = Array::MakeArray(retained_fields); 1273 fields = Array::MakeArray(retained_fields);
1231 cls.SetFields(fields); 1274 cls.SetFields(fields);
1232 } else { 1275 } else {
1233 cls.SetFields(Object::empty_array()); 1276 cls.SetFields(Object::empty_array());
1234 } 1277 }
1235 } 1278 }
1236 } 1279 }
1237 } 1280 }
1238 1281
1239 1282
1283 void Precompiler::DropTypes() {
1284 Library& lib = Library::Handle(Z);
1285 Class& cls = Class::Handle(Z);
1286 Object& obj = Object::Handle(Z);
1287 Array& arr = Array::Handle(Z);
1288 GrowableObjectArray& retained_types = GrowableObjectArray::Handle(Z);
1289 AbstractType& type = AbstractType::Handle(Z);
1290
1291 for (intptr_t i = 0; i < libraries_.Length(); i++) {
1292 lib ^= libraries_.At(i);
1293 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
1294 while (it.HasNext()) {
1295 cls = it.GetNextClass();
1296 if (cls.IsDynamicClass()) {
1297 continue; // class 'dynamic' is in the read-only VM isolate.
1298 }
1299 obj = cls.canonical_types();
1300 if (!obj.IsArray()) {
1301 // Class only has one type, keep it.
1302 } else {
1303 // Class has many types.
1304 arr ^= obj.raw();
1305 retained_types = GrowableObjectArray::New();
1306
1307 // Always keep the first one.
1308 ASSERT(arr.Length() >= 1);
1309 obj = arr.At(0);
1310 retained_types.Add(obj);
1311
1312 for (intptr_t i = 1; i < arr.Length(); i++) {
1313 obj = arr.At(i);
1314 if (obj.IsNull()) {
1315 continue;
1316 }
1317 type ^= obj.raw();
1318 bool retain = types_to_retain_.Lookup(&type) != NULL;
1319 if (retain) {
1320 retained_types.Add(type);
1321 } else {
1322 dropped_type_count_++;
1323 }
1324 }
1325 arr = Array::MakeArray(retained_types);
1326 cls.set_canonical_types(arr);
1327 }
1328 }
1329 }
1330 }
1331
1332
1333 void Precompiler::DropTypeArguments() {
1334 const Array& typeargs_table =
1335 Array::Handle(Z, I->object_store()->canonical_type_arguments());
1336 GrowableObjectArray& retained_typeargs =
1337 GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
1338 TypeArguments& typeargs = TypeArguments::Handle(Z);
1339 for (intptr_t i = 0; i < (typeargs_table.Length() - 1); i++) {
1340 typeargs ^= typeargs_table.At(i);
1341 bool retain = typeargs_to_retain_.Lookup(&typeargs) != NULL;
1342 if (retain) {
1343 retained_typeargs.Add(typeargs);
1344 } else {
1345 dropped_typearg_count_++;
1346 }
1347 }
1348
1349 const intptr_t dict_size =
1350 Utils::RoundUpToPowerOfTwo(retained_typeargs.Length() * 4 / 3);
1351 const Array& new_table = Array::Handle(Z, Array::New(dict_size + 1));
1352
1353 Object& element = Object::Handle(Z);
1354 for (intptr_t i = 0; i < retained_typeargs.Length(); i++) {
1355 typeargs ^= retained_typeargs.At(i);
1356 intptr_t hash = typeargs.Hash();
1357 intptr_t index = hash & (dict_size - 1);
1358 element = new_table.At(index);
1359 while (!element.IsNull()) {
1360 index = (index + 1) & (dict_size - 1);
1361 element = new_table.At(index);
1362 }
1363 new_table.SetAt(index, typeargs);
1364 }
1365
1366 const Smi& used = Smi::Handle(Z, Smi::New(retained_typeargs.Length()));
1367 new_table.SetAt(dict_size, used);
1368
1369 I->object_store()->set_canonical_type_arguments(new_table);
1370 }
1371
1372
1373 void Precompiler::TraceTypesFromRetainedClasses() {
1374 Library& lib = Library::Handle(Z);
1375 Class& cls = Class::Handle(Z);
1376 Array& members = Array::Handle(Z);
1377
1378 for (intptr_t i = 0; i < libraries_.Length(); i++) {
1379 lib ^= libraries_.At(i);
1380 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
1381 while (it.HasNext()) {
1382 cls = it.GetNextClass();
1383 if (cls.IsDynamicClass()) {
1384 continue; // class 'dynamic' is in the read-only VM isolate.
1385 }
1386
1387 // The subclasses array is only needed for CHA.
1388 cls.ClearDirectSubclasses();
1389
1390 bool retain = false;
1391 members = cls.fields();
1392 if (members.Length() > 0) {
1393 retain = true;
1394 }
1395 members = cls.functions();
1396 if (members.Length() > 0) {
1397 retain = true;
1398 }
1399 if (cls.is_allocated()) {
1400 retain = true;
1401 }
1402 if (cls.is_enum_class()) {
1403 // Enum classes have live instances, so we cannot unregister
1404 // them.
1405 retain = true;
1406 }
1407 members = cls.constants();
1408 if (members.Length() > 0) {
1409 // --compile_all?
1410 retain = true;
1411 }
1412
1413 if (retain) {
1414 AddTypesOf(cls);
1415 }
1416 }
1417 }
1418 }
1419
1420
1421 void Precompiler::DropClasses() {
1422 Library& lib = Library::Handle(Z);
1423 Class& cls = Class::Handle(Z);
1424 Array& members = Array::Handle(Z);
1425 String& name = String::Handle(Z);
1426
1427 #if defined(DEBUG)
1428 {
1429 // Force GC for allocation stats.
1430 I->heap()->CollectAllGarbage();
1431 }
1432 #endif
1433
1434 ClassTable* class_table = I->class_table();
1435 intptr_t num_cids = class_table->NumCids();
1436
1437 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
1438 if (!class_table->IsValidIndex(cid)) continue;
1439 if (!class_table->HasValidClassAt(cid)) continue;
1440
1441 cls = class_table->At(cid);
1442 ASSERT(!cls.IsNull());
1443
1444 if (cls.IsTopLevel()) {
1445 // Top-level classes are referenced specially from their library. They
1446 // will only be removed as a consquence of an entire library being
regis 2016/02/19 20:54:07 consequence
rmacnak 2016/02/20 01:35:39 Done.
1447 // removed.
1448 continue;
1449 }
1450 if (cls.is_enum_class()) {
1451 // Enum classes have live instances, so we cannot unregister
1452 // them.
1453 continue;
1454 }
1455 members = cls.constants();
1456 if (members.Length() > 0) {
1457 // --compile_all?
1458 continue;
1459 }
1460
1461 bool retain = classes_to_retain_.Lookup(&cls) != NULL;
1462 if (retain) {
1463 continue;
1464 }
1465
1466 #if defined(DEBUG)
1467 intptr_t instances =
1468 class_table->StatsWithUpdatedSize(cid)->post_gc.new_count +
1469 class_table->StatsWithUpdatedSize(cid)->post_gc.old_count;
1470 if (instances != 0) {
1471 FATAL2("Want to drop class %s, but it has %" Pd " instances\n",
1472 cls.ToCString(),
1473 instances);
1474 }
1475 #endif
1476
1477 dropped_class_count_++;
1478 if (FLAG_trace_precompiler) {
1479 THR_Print("Precompilation dropping %ld %s\n", cid, cls.ToCString());
1480 }
1481
1482 #if defined(DEBUG)
1483 class_table->Unregister(cid);
1484 #endif
1485 cls.set_id(kIllegalCid); // We check this when serializing.
1486
1487 lib = cls.library();
1488 name = cls.DictionaryName();
1489 lib.RemoveObject(cls, name);
1490 }
1491 }
1492
1493
1494 void Precompiler::DropLibraries() {
1495 const GrowableObjectArray& retained_libraries =
1496 GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
1497 Library& lib = Library::Handle(Z);
1498
1499 for (intptr_t i = 0; i < libraries_.Length(); i++) {
1500 lib ^= libraries_.At(i);
1501 lib.DropDependencies();
1502 intptr_t entries = 0;
1503 DictionaryIterator it(lib);
1504 while (it.HasNext()) {
1505 it.GetNext();
1506 entries++;
1507 }
1508 if (entries > 0) {
1509 lib.set_index(retained_libraries.Length());
1510 retained_libraries.Add(lib);
1511 } else {
1512 dropped_library_count_++;
1513 lib.set_index(-1);
1514 if (FLAG_trace_precompiler) {
1515 THR_Print("Precompilation dropping %s\n", lib.ToCString());
1516 }
1517 }
1518 }
1519
1520 I->object_store()->set_libraries(retained_libraries);
1521 libraries_ = retained_libraries.raw();
1522 }
1523
1524
1240 void Precompiler::BindStaticCalls() { 1525 void Precompiler::BindStaticCalls() {
1241 class BindStaticCallsVisitor : public FunctionVisitor { 1526 class BindStaticCallsVisitor : public FunctionVisitor {
1242 public: 1527 public:
1243 explicit BindStaticCallsVisitor(Zone* zone) : 1528 explicit BindStaticCallsVisitor(Zone* zone) :
1244 code_(Code::Handle(zone)), 1529 code_(Code::Handle(zone)),
1245 table_(Array::Handle(zone)), 1530 table_(Array::Handle(zone)),
1246 pc_offset_(Smi::Handle(zone)), 1531 pc_offset_(Smi::Handle(zone)),
1247 target_(Function::Handle(zone)), 1532 target_(Function::Handle(zone)),
1248 target_code_(Code::Handle(zone)) { 1533 target_code_(Code::Handle(zone)) {
1249 } 1534 }
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after
2228 CompilationPipeline::New(thread->zone(), function); 2513 CompilationPipeline::New(thread->zone(), function);
2229 2514
2230 ASSERT(FLAG_precompilation); 2515 ASSERT(FLAG_precompilation);
2231 const bool optimized = function.IsOptimizable(); // False for natives. 2516 const bool optimized = function.IsOptimizable(); // False for natives.
2232 return PrecompileFunctionHelper(pipeline, function, optimized); 2517 return PrecompileFunctionHelper(pipeline, function, optimized);
2233 } 2518 }
2234 2519
2235 #endif // DART_PRECOMPILER 2520 #endif // DART_PRECOMPILER
2236 2521
2237 } // namespace dart 2522 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698