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

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

Issue 1259123009: Initial tree-shaking for precompilation: only selective compilation, no removal of unused Functions… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: sync + more dart:io roots 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
« no previous file with comments | « 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/isolate.h" 8 #include "vm/isolate.h"
9 #include "vm/longjump.h"
8 #include "vm/object.h" 10 #include "vm/object.h"
9 #include "vm/object_store.h" 11 #include "vm/object_store.h"
10 #include "vm/compiler.h" 12 #include "vm/resolver.h"
11 #include "vm/longjump.h" 13 #include "vm/symbols.h"
12 14
13 namespace dart { 15 namespace dart {
14 16
15 17
18 #define I (isolate())
19 #define Z (zone())
20
21
16 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); 22 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler.");
17 23
18 24
19 static RawError* CompileFunction(const Function& func) { 25 static void Jump(const Error& error) {
20 Thread* thread = Thread::Current(); 26 Isolate::Current()->long_jump_base()->Jump(1, error);
21 Error& error = Error::Handle();
22 if (func.is_abstract() || func.IsRedirectingFactory()) {
23 return error.raw();
24 }
25
26 if (!func.HasCode()) {
27 if (FLAG_trace_precompiler) {
28 OS::Print(" Precompiling %s (%" Pd ")\n",
29 func.ToQualifiedCString(),
30 func.token_pos());
31 }
32 error = Compiler::CompileFunction(thread, func);
33 if (!error.IsNull()) {
34 return error.raw();
35 }
36 }
37
38 if ((func.kind() == RawFunction::kRegularFunction) && !func.is_static()) {
39 const String& name = String::Handle(func.name());
40 if (!Field::IsGetterName(name) && !Field::IsSetterName(name)) {
41 const Function& closure_func =
42 Function::Handle(func.ImplicitClosureFunction());
43 ASSERT(!closure_func.IsNull());
44 error = CompileFunction(closure_func);
45 }
46 }
47
48 return error.raw();
49 }
50
51
52 static RawError* CompileClass(const Class& cls) {
53 if (FLAG_trace_precompiler) {
54 OS::Print(" Precompiling %s\n", cls.ToCString());
55 }
56
57 Error& error = Error::Handle();
58 error = cls.EnsureIsFinalized(Isolate::Current());
59 if (!error.IsNull()) {
60 return error.raw();
61 }
62
63 const Array& fields = Array::Handle(cls.fields());
64 Field& field = Field::Handle();
65 for (intptr_t i = 0; i < fields.Length(); i++) {
66 field ^= fields.At(i);
67 ASSERT(!field.IsNull());
68 if (field.is_static() && field.has_initializer()) {
69 if (FLAG_trace_precompiler) {
70 OS::Print(" Precompiling initializer for %s\n", field.ToCString());
71 }
72 Compiler::CompileStaticInitializer(field);
73 }
74 }
75
76 const Array& functions = Array::Handle(cls.functions());
77 Function& func = Function::Handle();
78 for (intptr_t i = 0; i < functions.Length(); i++) {
79 func ^= functions.At(i);
80 ASSERT(!func.IsNull());
81 error = CompileFunction(func);
82 if (!error.IsNull()) {
83 return error.raw();
84 }
85 }
86
87 return error.raw();
88 }
89
90
91 static RawError* CompileLibrary(const Library& lib) {
92 if (FLAG_trace_precompiler) {
93 OS::Print("Precompiling %s\n", lib.ToCString());
94 }
95 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
96 Class& cls = Class::Handle();
97 Error& error = Error::Handle();
98 while (it.HasNext()) {
99 cls = it.GetNextClass();
100 error = CompileClass(cls);
101 if (!error.IsNull()) {
102 return error.raw();
103 }
104 }
105
106 return error.raw();
107 }
108
109
110 static RawError* InnerCompileAll() {
111 Error& error = Error::Handle();
112 const GrowableObjectArray& libs = GrowableObjectArray::Handle(
113 Isolate::Current()->object_store()->libraries());
114 Library& lib = Library::Handle();
115 for (int i = 0; i < libs.Length(); i++) {
116 lib ^= libs.At(i);
117 error = CompileLibrary(lib);
118 if (!error.IsNull()) {
119 return error.raw();
120 }
121 }
122
123 if (FLAG_trace_precompiler) {
124 OS::Print("** Precompiling collected closures **\n");
125 }
126
127 const GrowableObjectArray& closures =
128 GrowableObjectArray::Handle(Isolate::Current()->collected_closures());
129 Function& func = Function::Handle();
130 if (!closures.IsNull()) {
131 for (int i = 0; i < closures.Length(); i++) {
132 func ^= closures.At(i);
133 error = CompileFunction(func);
134 if (!error.IsNull()) {
135 return error.raw();
136 }
137 }
138 }
139 Isolate::Current()->set_collected_closures(GrowableObjectArray::Handle());
140
141 if (FLAG_trace_precompiler) {
142 OS::Print("*** Done precompiling ***\n");
143 }
144 Isolate::Current()->set_compilation_allowed(false);
145 return error.raw();
146 } 27 }
147 28
148 29
149 RawError* Precompiler::CompileAll() { 30 RawError* Precompiler::CompileAll() {
150 LongJumpScope jump; 31 LongJumpScope jump;
151 if (setjmp(*jump.Set()) == 0) { 32 if (setjmp(*jump.Set()) == 0) {
152 return InnerCompileAll(); 33 Precompiler precompiler(Thread::Current());
34 precompiler.DoCompileAll();
35 return Error::null();
153 } else { 36 } else {
154 Isolate* isolate = Isolate::Current(); 37 Isolate* isolate = Isolate::Current();
155 const Error& error = Error::Handle(isolate, 38 const Error& error = Error::Handle(isolate->object_store()->sticky_error());
156 isolate->object_store()->sticky_error());
157 isolate->object_store()->clear_sticky_error(); 39 isolate->object_store()->clear_sticky_error();
158 return error.raw(); 40 return error.raw();
159 } 41 }
160 } 42 }
161 43
44
45 Precompiler::Precompiler(Thread* thread) :
46 thread_(thread),
47 zone_(thread->zone()),
48 isolate_(thread->isolate()),
49 changed_(false),
50 function_count_(0),
51 class_count_(0),
52 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())),
53 pending_functions_(GrowableObjectArray::Handle(Z,
54 GrowableObjectArray::New())),
55 collected_closures_(GrowableObjectArray::Handle(Z, I->collected_closures())),
56 sent_selectors_(GrowableObjectArray::Handle(Z, GrowableObjectArray::New())),
57 error_(Error::Handle(Z)) {
58 }
59
60
61 void Precompiler::DoCompileAll() {
62 // 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.
64 ClearAllCode();
65
66 // Start with the allocations and invocations that happen from C++.
67 AddRoots();
68
69 // TODO(rmacnak): Eagerly add field-invocation functions to all signature
70 // classes so closure calls don't go through the runtime.
71
72 // Compile newly found targets and add their callees until we reach a fixed
73 // point.
74 Iterate();
75
76 CleanUp();
77
78 if (FLAG_trace_precompiler) {
79 OS::Print("Precompiled %" Pd " functions, %" Pd " dynamic types,"
80 " %" Pd " dynamic selectors\n",
81 function_count_,
82 class_count_,
83 sent_selectors_.Length());
84 }
85
86 I->set_compilation_allowed(false);
87 }
88
89
90 void Precompiler::ClearAllCode() {
91 Library& lib = Library::Handle(Z);
92 Class& cls = Class::Handle(Z);
93 Array& functions = Array::Handle(Z);
94 Function& function = Function::Handle(Z);
95
96 for (intptr_t i = 0; i < libraries_.Length(); i++) {
97 lib ^= libraries_.At(i);
98 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
99 while (it.HasNext()) {
100 cls = it.GetNextClass();
101 error_ = cls.EnsureIsFinalized(I);
102 if (!error_.IsNull()) {
103 Jump(error_);
104 }
105 }
106 }
107
108 for (intptr_t i = 0; i < libraries_.Length(); i++) {
109 lib ^= libraries_.At(i);
110 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
111 while (it.HasNext()) {
112 cls = it.GetNextClass();
113 functions = cls.functions();
114 for (intptr_t i = 0; i < functions.Length(); i++) {
115 function ^= functions.At(i);
116 function.ClearCode();
117 }
118 }
119 }
120 }
121
122
123 void Precompiler::AddRoots() {
124 // Note that <rootlibrary>.main is not a root. The appropriate main will be
125 // discovered through _getMainClosure.
126
127 AddSelector(Symbols::NoSuchMethod());
128
129 AddSelector(Symbols::Call()); // For speed, not correctness.
130
131 // Allocated from C++.
132 static const intptr_t kExternallyAllocatedCids[] = {
133 kBoolCid,
134 kNullCid,
135
136 kSmiCid,
137 kMintCid,
138 kBigintCid,
139 kDoubleCid,
140
141 kOneByteStringCid,
142 kTwoByteStringCid,
143 kExternalOneByteStringCid,
144 kExternalTwoByteStringCid,
145
146 kArrayCid,
147 kImmutableArrayCid,
148 kGrowableObjectArrayCid,
149 kLinkedHashMapCid,
150
151 kTypedDataUint8ClampedArrayCid,
152 kTypedDataUint8ArrayCid,
153 kTypedDataUint16ArrayCid,
154 kTypedDataUint32ArrayCid,
155 kTypedDataUint64ArrayCid,
156
157 kTypedDataInt8ArrayCid,
158 kTypedDataInt16ArrayCid,
159 kTypedDataInt32ArrayCid,
160 kTypedDataInt64ArrayCid,
161
162 kExternalTypedDataUint8ArrayCid,
163
164 kTypedDataFloat32ArrayCid,
165 kTypedDataFloat64ArrayCid,
166
167 kTypedDataFloat32x4ArrayCid,
168 kTypedDataInt32x4ArrayCid,
169 kTypedDataFloat64x2ArrayCid,
170
171 kInt32x4Cid,
172 kFloat32x4Cid,
173 kFloat64x2Cid,
174
175 kTypeCid,
176 kTypeRefCid,
177 kTypeParameterCid,
178 kBoundedTypeCid,
179 kLibraryPrefixCid,
180
181 kJSRegExpCid,
182 kUserTagCid,
183 kStacktraceCid,
184 kWeakPropertyCid,
185 kCapabilityCid,
186 ReceivePort::kClassId,
187 SendPort::kClassId,
188
189 kIllegalCid
190 };
191
192 Class& cls = Class::Handle(Z);
193 for (intptr_t i = 0; kExternallyAllocatedCids[i] != kIllegalCid; i++) {
194 cls = isolate()->class_table()->At(kExternallyAllocatedCids[i]);
195 AddClass(cls);
196 }
197
198 static const struct {
199 const char* library_;
200 const char* class_;
201 const char* function_;
202 } kExternallyCalled[] = {
203 { "dart:_builtin", "::", "_getMainClosure" },
204 { "dart:_builtin", "::", "_getPrintClosure" },
205 { "dart:_builtin", "::", "_getUriBaseClosure" },
206 { "dart:_builtin", "::", "_resolveUri" },
207 { "dart:_builtin", "::", "_setWorkingDirectory" },
208 { "dart:async", "::", "_setScheduleImmediateClosure" },
209 { "dart:core", "_InternalError", "_InternalError." },
210 { "dart:core", "_InvocationMirror", "_allocateInvocationMirror" },
211 { "dart:io", "::", "_makeUint8ListView" },
212 { "dart:io", "::", "_makeDatagram" },
213 { "dart:io", "CertificateException", "CertificateException." },
214 { "dart:io", "HandshakeException", "HandshakeException." },
215 { "dart:io", "TlsException", "TlsException." },
216 { "dart:io", "X509Certificate", "X509Certificate." },
217 { "dart:io", "_ExternalBuffer", "set:data" },
218 { "dart:io", "_Platform", "set:_nativeScript" },
219 { "dart:io", "_ProcessStartStatus", "set:_errorCode" },
220 { "dart:io", "_ProcessStartStatus", "set:_errorMessage" },
221 { "dart:io", "_SecureFilterImpl", "get:ENCRYPTED_SIZE" },
222 { "dart:io", "_SecureFilterImpl", "get:SIZE" },
223 { "dart:isolate", "::", "_getIsolateScheduleImmediateClosure" },
224 { "dart:isolate", "::", "_startMainIsolate" },
225 { "dart:isolate", "_RawReceivePortImpl", "_handleMessage" },
226 { "dart:isolate", "_RawReceivePortImpl", "_lookupHandler" },
227 { "dart:vmservice", "::", "_registerIsolate" },
228 { "dart:vmservice", "::", "boot" },
229 { "dart:vmservice_io", "::", "_addResource" },
230 { "dart:vmservice_io", "::", "main" },
231
232 // Cf. Exceptions::Create
233 { "dart:core", "RangeError", "RangeError." },
234 { "dart:core", "RangeError", "RangeError.range" },
235 { "dart:core", "ArgumentError", "ArgumentError." },
236 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" },
237 { "dart:core", "FormatException", "FormatException." },
238 { "dart:core", "UnsupportedError", "UnsupportedError." },
239 { "dart:core", "NullThrownError", "NullThrownError." },
240 { "dart:isolate", "IsolateSpawnException", "IsolateSpawnException." },
241 { "dart:isolate", "_IsolateUnhandledException",
242 "_IsolateUnhandledException." },
243 { "dart:core", "_JavascriptIntegerOverflowError",
244 "_JavascriptIntegerOverflowError." },
245 { "dart:core", "_JavascriptCompatibilityError",
246 "_JavascriptCompatibilityError." },
247 { "dart:core", "AssertionError", "AssertionError." },
248 { "dart:core", "_CastError", "_CastError._create" },
249 { "dart:core", "_TypeError", "_TypeError._create" },
250 { "dart:core", "FallThroughError", "FallThroughError._create" },
251 { "dart:core", "AbstractClassInstantiationError",
252 "AbstractClassInstantiationError._create" },
253 { "dart:core", "CyclicInitializationError",
254 "CyclicInitializationError." },
255 { "dart:core", "StackOverflowError", "StackOverflowError." },
256 { "dart:core", "OutOfMemoryError", "OutOfMemoryError." },
257 { NULL, NULL, NULL }
258 };
259
260 Library& lib = Library::Handle(Z);
261 Function& func = Function::Handle(Z);
262 String& library_name = String::Handle(Z);
263 String& class_name = String::Handle(Z);
264 String& function_name = String::Handle(Z);
265 for (intptr_t i = 0; kExternallyCalled[i].library_ != NULL; i++) {
266 library_name = Symbols::New(kExternallyCalled[i].library_);
267 class_name = Symbols::New(kExternallyCalled[i].class_);
268 function_name = Symbols::New(kExternallyCalled[i].function_);
269
270 lib = Library::LookupLibrary(library_name);
271 if (lib.IsNull()) {
272 if (FLAG_trace_precompiler) {
273 OS::Print("WARNING: Missing %s\n", kExternallyCalled[i].library_);
274 }
275 continue;
276 }
277
278 if (class_name.raw() == Symbols::TopLevel().raw()) {
279 func = lib.LookupFunctionAllowPrivate(function_name);
280 } else {
281 cls = lib.LookupClassAllowPrivate(class_name);
282 if (cls.IsNull()) {
283 if (FLAG_trace_precompiler) {
284 OS::Print("WARNING: Missing %s %s\n",
285 kExternallyCalled[i].library_,
286 kExternallyCalled[i].class_);
287 }
288 continue;
289 }
290
291 ASSERT(!cls.IsNull());
292 func = cls.LookupFunctionAllowPrivate(function_name);
293 }
294
295 if (func.IsNull()) {
296 if (FLAG_trace_precompiler) {
297 OS::Print("WARNING: Missing %s %s %s\n",
298 kExternallyCalled[i].library_,
299 kExternallyCalled[i].class_,
300 kExternallyCalled[i].function_);
301 }
302 continue;
303 }
304
305 AddFunction(func);
306 }
307 }
308
309
310 void Precompiler::Iterate() {
311 Function& function = Function::Handle(Z);
312
313 while (changed_) {
314 changed_ = false;
315
316 while (pending_functions_.Length() > 0) {
317 function ^= pending_functions_.RemoveLast();
318 ProcessFunction(function);
319 }
320
321 CheckForNewDynamicFunctions();
322
323 // Drain collected_closures last because additions to this list come from
324 // outside the Precompiler and so do not flip our changed_ flag.
325 while (collected_closures_.Length() > 0) {
326 function ^= collected_closures_.RemoveLast();
327 ProcessFunction(function);
328 }
329 }
330 }
331
332
333 void Precompiler::CleanUp() {
334 I->set_collected_closures(GrowableObjectArray::Handle(Z));
335
336 // TODO(rmacnak): Drop functions without code, classes without functions, etc.
337 }
338
339
340 void Precompiler::ProcessFunction(const Function& function) {
341 if (!function.HasCode()) {
342 function_count_++;
343
344 if (FLAG_trace_precompiler) {
345 OS::Print("Precompiling %" Pd " %s (%" Pd ", %s)\n",
346 function_count_,
347 function.ToLibNamePrefixedQualifiedCString(),
348 function.token_pos(),
349 Function::KindToCString(function.kind()));
350 }
351
352 ASSERT(!function.is_abstract());
353 ASSERT(!function.IsRedirectingFactory());
354
355 error_ = Compiler::CompileFunction(thread_, function);
356 if (!error_.IsNull()) {
357 Jump(error_);
358 }
359 }
360
361 ASSERT(function.HasCode());
362 AddCalleesOf(function);
363 }
364
365
366 void Precompiler::AddCalleesOf(const Function& function) {
367 ASSERT(function.HasCode());
368
369 const Code& code = Code::Handle(Z, function.CurrentCode());
370
371 const Array& table = Array::Handle(Z, code.static_calls_target_table());
372 Object& entry = Object::Handle(Z);
373 Function& target = Function::Handle(Z);
374 for (intptr_t i = 0; i < table.Length(); i++) {
375 entry = table.At(i);
376 if (entry.IsFunction()) {
377 target ^= table.At(i);
378 AddFunction(target);
379 }
380 }
381
382 #if defined(TARGET_ARCH_IA32)
383 FATAL("Callee scanning unimplemented for IA32");
384 #endif
385
386 const ObjectPool& pool = ObjectPool::Handle(Z, code.GetObjectPool());
387 ICData& call_site = ICData::Handle(Z);
388 String& selector = String::Handle(Z);
389 Field& field = Field::Handle(Z);
390 Class& cls = Class::Handle(Z);
391 for (intptr_t i = 0; i < pool.Length(); i++) {
392 if (pool.InfoAt(i) == ObjectPool::kTaggedObject) {
393 entry = pool.ObjectAt(i);
394 if (entry.IsICData()) {
395 call_site ^= entry.raw();
396 if (call_site.NumberOfChecks() == 1) {
397 // Probably a static call.
398 target = call_site.GetTargetAt(0);
399 AddFunction(target);
400 if (!target.is_static()) {
401 // Super call (should not enqueue selector) or dynamic call with a
402 // CHA prediction (should enqueue selector).
403 selector = call_site.target_name();
404 AddSelector(selector);
405 }
406 } else {
407 // A dynamic call.
408 selector = call_site.target_name();
409 AddSelector(selector);
410 }
411 } else if (entry.IsField()) {
412 // Potential need for field initializer.
413 field ^= entry.raw();
414 AddField(field);
415 } else if (entry.IsInstance()) {
416 // Potential const object.
417 cls = entry.clazz();
418 AddClass(cls);
419 }
420 }
421 }
422 }
423
424
425 void Precompiler::AddField(const Field& field) {
426 if (field.is_static()) {
427 // Potential const object. Uninitialized field will harmlessly do a redudant
Florian Schneider 2015/08/04 08:20:01 *redundant
rmacnak 2015/08/04 18:34:28 Done.
428 // add of the Null class.
429 const Object& value = Object::Handle(Z, field.value());
430 const Class& cls = Class::Handle(Z, value.clazz());
431 AddClass(cls);
432
433 if (field.has_initializer()) {
434 if (field.initializer() != Function::null()) return;
435
436 if (FLAG_trace_precompiler) {
437 OS::Print("Precompiling initializer for %s\n", field.ToCString());
438 }
439 Compiler::CompileStaticInitializer(field);
440
441 const Function& function = Function::Handle(Z, field.initializer());
442 AddCalleesOf(function);
443 }
444 }
445 }
446
447
448 void Precompiler::AddFunction(const Function& function) {
449 if (function.HasCode()) return;
450
451 pending_functions_.Add(function);
452 changed_ = true;
453 }
454
455
456 bool Precompiler::IsSent(const String& selector) {
457 ASSERT(selector.IsSymbol());
458
459 // TODO(rmacnak): Use a proper set.
Florian Schneider 2015/08/04 08:20:01 You could use the one from runtime/vm/hash_map.h,
rmacnak 2015/08/04 18:34:28 I'll do that in the next CL.
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 }
468
469
470 void Precompiler::AddSelector(const String& selector) {
471 if (!IsSent(selector)) {
472 if (FLAG_trace_precompiler) {
473 OS::Print("Enqueueing selector %" Pd " %s\n",
474 sent_selectors_.Length(),
475 selector.ToCString());
476 }
477
478 sent_selectors_.Add(selector);
479 changed_ = true;
480
481 if (!Field::IsGetterName(selector) &&
482 !Field::IsSetterName(selector)) {
483 // Regular method may be call-through-getter.
484 // TODO(rmacnak): Do not create the symbol if it does not already exist.
485 String& getter = String::Handle(Field::GetterName(selector));
486 getter = Symbols::New(getter);
487 AddSelector(getter);
488 }
489 }
490 }
491
492
493 void Precompiler::AddClass(const Class& cls) {
494 if (cls.is_allocated()) return;
495
496 class_count_++;
497 cls.set_is_allocated();
498 changed_ = true;
499
500 if (FLAG_trace_precompiler) {
501 OS::Print("Allocation %ld %s\n", class_count_, cls.ToCString());
502 }
503
504 const Class& superclass = Class::Handle(cls.SuperClass());
505 if (!superclass.IsNull()) {
506 AddClass(superclass);
507 }
508 }
509
510
511 void Precompiler::CheckForNewDynamicFunctions() {
512 Library& lib = Library::Handle(Z);
513 Class& cls = Class::Handle(Z);
514 Array& functions = Array::Handle(Z);
515 Function& function = Function::Handle(Z);
516 String& selector = String::Handle(Z);
517
518 for (intptr_t i = 0; i < libraries_.Length(); i++) {
519 lib ^= libraries_.At(i);
520 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
521 while (it.HasNext()) {
522 cls = it.GetNextClass();
523
524 if (!cls.is_allocated()) {
525 bool has_compiled_constructor = false;
526 if (cls.allocation_stub() != Code::null()) {
527 // Regular objects.
528 has_compiled_constructor = true;
529 } else if (cls.is_synthesized_class()) {
530 // Enums.
531 has_compiled_constructor = true;
532 } else {
533 // Objects only allocated via const constructors, and not stored in a
534 // static field or code.
535 // E.g. A in
536 // class A {
537 // const A();
538 // toString() => "Don't drop me!";
539 // }
540 // class B {
541 // const a = const A();
542 // const B();
543 // static const theB = const B();
544 // }
545 // main() => print(B.theB.a);
546 functions = cls.functions();
547 for (intptr_t k = 0; k < functions.Length(); k++) {
548 function ^= functions.At(k);
549 if (function.IsGenerativeConstructor() &&
550 function.HasCode()) {
551 has_compiled_constructor = true;
552 break;
553 }
554 }
555 }
556 if (!has_compiled_constructor) {
557 continue;
558 }
559 AddClass(cls);
560 }
561
562 functions = cls.functions();
563 for (intptr_t k = 0; k < functions.Length(); k++) {
564 function ^= functions.At(k);
565
566 if (function.is_static() || function.is_abstract()) continue;
567
568 // Don't bail out early if there is already code because we may discover
569 // the corresponding getter selector is sent in some later iteration.
570 // if (function.HasCode()) continue;
571
572 selector = function.name();
573 if (IsSent(selector)) {
574 AddFunction(function);
575 }
576
577 if (function.kind() == RawFunction::kRegularFunction &&
578 !Field::IsGetterName(selector) &&
579 !Field::IsSetterName(selector)) {
580 // TODO(rmacnak): Do not create the symbol if it does not already
581 // exist.
582 selector = Field::GetterName(selector);
583 selector = Symbols::New(selector);
584 if (IsSent(selector)) {
585 function = function.ImplicitClosureFunction();
586 AddFunction(function);
587 }
588 }
589 }
590 }
591 }
592 }
593
162 } // namespace dart 594 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698