OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/precompiler.h" | 5 #include "vm/precompiler.h" |
6 | 6 |
7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
10 #include "vm/branch_optimizer.h" | 10 #include "vm/branch_optimizer.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "vm/flow_graph_type_propagator.h" | 26 #include "vm/flow_graph_type_propagator.h" |
27 #include "vm/hash_table.h" | 27 #include "vm/hash_table.h" |
28 #include "vm/il_printer.h" | 28 #include "vm/il_printer.h" |
29 #include "vm/isolate.h" | 29 #include "vm/isolate.h" |
30 #include "vm/log.h" | 30 #include "vm/log.h" |
31 #include "vm/longjump.h" | 31 #include "vm/longjump.h" |
32 #include "vm/object.h" | 32 #include "vm/object.h" |
33 #include "vm/object_store.h" | 33 #include "vm/object_store.h" |
34 #include "vm/os.h" | 34 #include "vm/os.h" |
35 #include "vm/parser.h" | 35 #include "vm/parser.h" |
36 #include "vm/program_visitor.h" | |
37 #include "vm/redundancy_elimination.h" | 36 #include "vm/redundancy_elimination.h" |
38 #include "vm/regexp_assembler.h" | 37 #include "vm/regexp_assembler.h" |
39 #include "vm/regexp_parser.h" | 38 #include "vm/regexp_parser.h" |
40 #include "vm/resolver.h" | 39 #include "vm/resolver.h" |
41 #include "vm/symbols.h" | 40 #include "vm/symbols.h" |
42 #include "vm/tags.h" | 41 #include "vm/tags.h" |
43 #include "vm/timeline.h" | 42 #include "vm/timeline.h" |
44 #include "vm/timer.h" | 43 #include "vm/timer.h" |
45 #include "vm/type_table.h" | 44 #include "vm/type_table.h" |
46 #include "vm/version.h" | |
47 #include "vm/json_parser.h" | |
48 | 45 |
49 namespace dart { | 46 namespace dart { |
50 | 47 |
| 48 |
51 #define T (thread()) | 49 #define T (thread()) |
52 #define I (isolate()) | 50 #define I (isolate()) |
53 #define Z (zone()) | 51 #define Z (zone()) |
54 | 52 |
55 | 53 |
56 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); | 54 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); |
57 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); | 55 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); |
58 DEFINE_FLAG( | 56 DEFINE_FLAG( |
59 int, | 57 int, |
60 max_speculative_inlining_attempts, | 58 max_speculative_inlining_attempts, |
(...skipping 10 matching lines...) Expand all Loading... |
71 DECLARE_FLAG(bool, range_analysis); | 69 DECLARE_FLAG(bool, range_analysis); |
72 DECLARE_FLAG(bool, trace_compiler); | 70 DECLARE_FLAG(bool, trace_compiler); |
73 DECLARE_FLAG(bool, trace_optimizing_compiler); | 71 DECLARE_FLAG(bool, trace_optimizing_compiler); |
74 DECLARE_FLAG(bool, trace_bailout); | 72 DECLARE_FLAG(bool, trace_bailout); |
75 DECLARE_FLAG(bool, use_inlining); | 73 DECLARE_FLAG(bool, use_inlining); |
76 DECLARE_FLAG(bool, verify_compiler); | 74 DECLARE_FLAG(bool, verify_compiler); |
77 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); | 75 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); |
78 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 76 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
79 DECLARE_FLAG(bool, trace_inlining_intervals); | 77 DECLARE_FLAG(bool, trace_inlining_intervals); |
80 DECLARE_FLAG(bool, trace_irregexp); | 78 DECLARE_FLAG(bool, trace_irregexp); |
81 DECLARE_FLAG(int, inlining_hotness); | |
82 DECLARE_FLAG(int, inlining_size_threshold); | |
83 DECLARE_FLAG(int, inlining_callee_size_threshold); | |
84 DECLARE_FLAG(int, inline_getters_setters_smaller_than); | |
85 DECLARE_FLAG(int, inlining_depth_threshold); | |
86 DECLARE_FLAG(int, inlining_caller_size_threshold); | |
87 DECLARE_FLAG(int, inlining_constant_arguments_max_size_threshold); | |
88 DECLARE_FLAG(int, inlining_constant_arguments_min_size_threshold); | |
89 | |
90 | 79 |
91 #ifdef DART_PRECOMPILER | 80 #ifdef DART_PRECOMPILER |
92 | 81 |
93 class DartPrecompilationPipeline : public DartCompilationPipeline { | 82 class DartPrecompilationPipeline : public DartCompilationPipeline { |
94 public: | 83 public: |
95 explicit DartPrecompilationPipeline(Zone* zone, | 84 explicit DartPrecompilationPipeline(Zone* zone, |
96 FieldTypeMap* field_map = NULL) | 85 FieldTypeMap* field_map = NULL) |
97 : zone_(zone), result_type_(CompileType::None()), field_map_(field_map) {} | 86 : zone_(zone), result_type_(CompileType::None()), field_map_(field_map) {} |
98 | 87 |
99 virtual void FinalizeCompilation(FlowGraph* flow_graph) { | 88 virtual void FinalizeCompilation(FlowGraph* flow_graph) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 | 178 |
190 DISALLOW_COPY_AND_ASSIGN(PrecompileParsedFunctionHelper); | 179 DISALLOW_COPY_AND_ASSIGN(PrecompileParsedFunctionHelper); |
191 }; | 180 }; |
192 | 181 |
193 | 182 |
194 static void Jump(const Error& error) { | 183 static void Jump(const Error& error) { |
195 Thread::Current()->long_jump_base()->Jump(1, error); | 184 Thread::Current()->long_jump_base()->Jump(1, error); |
196 } | 185 } |
197 | 186 |
198 | 187 |
199 TypeRangeCache::TypeRangeCache(Precompiler* precompiler, | |
200 Thread* thread, | |
201 intptr_t num_cids) | |
202 : precompiler_(precompiler), | |
203 thread_(thread), | |
204 lower_limits_(thread->zone()->Alloc<intptr_t>(num_cids)), | |
205 upper_limits_(thread->zone()->Alloc<intptr_t>(num_cids)) { | |
206 for (intptr_t i = 0; i < num_cids; i++) { | |
207 lower_limits_[i] = kNotComputed; | |
208 upper_limits_[i] = kNotComputed; | |
209 } | |
210 ASSERT(precompiler->type_range_cache() == NULL); | |
211 precompiler->set_type_range_cache(this); | |
212 } | |
213 | |
214 | |
215 TypeRangeCache::~TypeRangeCache() { | |
216 ASSERT(precompiler_->type_range_cache() == this); | |
217 precompiler_->set_type_range_cache(NULL); | |
218 } | |
219 | |
220 | |
221 RawError* Precompiler::CompileAll( | 188 RawError* Precompiler::CompileAll( |
222 Dart_QualifiedFunctionName embedder_entry_points[], | 189 Dart_QualifiedFunctionName embedder_entry_points[], |
223 bool reset_fields, | 190 bool reset_fields) { |
224 uint8_t* jit_feedback, | |
225 intptr_t jit_feedback_length) { | |
226 LongJumpScope jump; | 191 LongJumpScope jump; |
227 if (setjmp(*jump.Set()) == 0) { | 192 if (setjmp(*jump.Set()) == 0) { |
228 Precompiler precompiler(Thread::Current(), reset_fields); | 193 Precompiler precompiler(Thread::Current(), reset_fields); |
229 precompiler.LoadFeedback(jit_feedback, jit_feedback_length); | |
230 precompiler.DoCompileAll(embedder_entry_points); | 194 precompiler.DoCompileAll(embedder_entry_points); |
231 return Error::null(); | 195 return Error::null(); |
232 } else { | 196 } else { |
233 Thread* thread = Thread::Current(); | 197 Thread* thread = Thread::Current(); |
234 const Error& error = Error::Handle(thread->sticky_error()); | 198 const Error& error = Error::Handle(thread->sticky_error()); |
235 thread->clear_sticky_error(); | 199 thread->clear_sticky_error(); |
236 return error.raw(); | 200 return error.raw(); |
237 } | 201 } |
238 } | 202 } |
239 | 203 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 upper_limits_[type_cid] = *upper_limit; | 287 upper_limits_[type_cid] = *upper_limit; |
324 return true; | 288 return true; |
325 } | 289 } |
326 | 290 |
327 | 291 |
328 Precompiler::Precompiler(Thread* thread, bool reset_fields) | 292 Precompiler::Precompiler(Thread* thread, bool reset_fields) |
329 : thread_(thread), | 293 : thread_(thread), |
330 zone_(NULL), | 294 zone_(NULL), |
331 isolate_(thread->isolate()), | 295 isolate_(thread->isolate()), |
332 reset_fields_(reset_fields), | 296 reset_fields_(reset_fields), |
333 jit_feedback_(NULL), | |
334 changed_(false), | 297 changed_(false), |
335 function_count_(0), | 298 function_count_(0), |
336 class_count_(0), | 299 class_count_(0), |
337 selector_count_(0), | 300 selector_count_(0), |
338 dropped_function_count_(0), | 301 dropped_function_count_(0), |
339 dropped_field_count_(0), | 302 dropped_field_count_(0), |
340 dropped_class_count_(0), | 303 dropped_class_count_(0), |
341 dropped_typearg_count_(0), | 304 dropped_typearg_count_(0), |
342 dropped_type_count_(0), | 305 dropped_type_count_(0), |
343 dropped_library_count_(0), | 306 dropped_library_count_(0), |
344 libraries_(GrowableObjectArray::Handle(I->object_store()->libraries())), | 307 libraries_(GrowableObjectArray::Handle(I->object_store()->libraries())), |
345 pending_functions_( | 308 pending_functions_( |
346 GrowableObjectArray::Handle(GrowableObjectArray::New())), | 309 GrowableObjectArray::Handle(GrowableObjectArray::New())), |
347 sent_selectors_(), | 310 sent_selectors_(), |
348 enqueued_functions_(), | 311 enqueued_functions_(), |
349 fields_to_retain_(), | 312 fields_to_retain_(), |
350 functions_to_retain_(), | 313 functions_to_retain_(), |
351 classes_to_retain_(), | 314 classes_to_retain_(), |
352 typeargs_to_retain_(), | 315 typeargs_to_retain_(), |
353 types_to_retain_(), | 316 types_to_retain_(), |
354 consts_to_retain_(), | 317 consts_to_retain_(), |
355 field_type_map_(), | 318 field_type_map_(), |
356 type_range_cache_(NULL), | |
357 error_(Error::Handle()), | 319 error_(Error::Handle()), |
358 get_runtime_type_is_unique_(false) {} | 320 get_runtime_type_is_unique_(false) {} |
359 | 321 |
360 | 322 |
361 void Precompiler::LoadFeedback(uint8_t* buffer, intptr_t length) { | |
362 if (buffer == NULL) { | |
363 if (FLAG_trace_precompiler) { | |
364 THR_Print("Precompiler running without JIT feedback\n"); | |
365 } | |
366 | |
367 // Flags affecting compilation only: | |
368 // There is no counter feedback in precompilation, so ignore the counter | |
369 // when making inlining decisions. | |
370 FLAG_inlining_hotness = 0; | |
371 // Use smaller thresholds in precompilation as we are compiling everything | |
372 // with the optimizing compiler instead of only hot functions. | |
373 FLAG_inlining_size_threshold = 5; | |
374 FLAG_inline_getters_setters_smaller_than = 5; | |
375 FLAG_inlining_callee_size_threshold = 20; | |
376 FLAG_inlining_depth_threshold = 4; | |
377 FLAG_inlining_caller_size_threshold = 1000; | |
378 FLAG_inlining_constant_arguments_max_size_threshold = 100; | |
379 FLAG_inlining_constant_arguments_min_size_threshold = 30; | |
380 return; | |
381 } | |
382 | |
383 if (FLAG_trace_precompiler) { | |
384 THR_Print("Loading JIT feedback\n"); | |
385 } | |
386 | |
387 JSONParser parser(reinterpret_cast<const char*>(buffer), length, | |
388 Thread::Current()->zone()); | |
389 ParsedJSONValue* root = parser.ParseValue(); | |
390 if (root->IsError()) { | |
391 ParsedJSONError* error = static_cast<ParsedJSONError*>(root); | |
392 THR_Print("Error parsing JIT feedback: %s:%" Pd "\n", error->message(), | |
393 error->position()); | |
394 } else if (!root->IsObject()) { | |
395 THR_Print("Error parsing JIT feedback: object expected\n"); | |
396 } else { | |
397 jit_feedback_ = static_cast<ParsedJSONObject*>(root); | |
398 } | |
399 } | |
400 | |
401 | |
402 void Precompiler::DoCompileAll( | 323 void Precompiler::DoCompileAll( |
403 Dart_QualifiedFunctionName embedder_entry_points[]) { | 324 Dart_QualifiedFunctionName embedder_entry_points[]) { |
404 ASSERT(I->compilation_allowed()); | 325 ASSERT(I->compilation_allowed()); |
405 | 326 |
406 { | 327 { |
407 StackZone stack_zone(T); | 328 StackZone stack_zone(T); |
408 zone_ = stack_zone.GetZone(); | 329 zone_ = stack_zone.GetZone(); |
409 | 330 |
410 { | 331 { |
411 HANDLESCOPE(T); | 332 HANDLESCOPE(T); |
412 // Make sure class hierarchy is stable before compilation so that CHA | 333 // Make sure class hierarchy is stable before compilation so that CHA |
413 // can be used. Also ensures lookup of entry points won't miss functions | 334 // can be used. Also ensures lookup of entry points won't miss functions |
414 // because their class hasn't been finalized yet. | 335 // because their class hasn't been finalized yet. |
415 FinalizeAllClasses(); | 336 FinalizeAllClasses(); |
416 | 337 |
417 SortClasses(); | 338 SortClasses(); |
418 TypeRangeCache trc(this, T, I->class_table()->NumCids()); | 339 TypeRangeCache trc(T, I->class_table()->NumCids()); |
419 VerifyJITFeedback(); | |
420 | 340 |
421 // Precompile static initializers to compute result type information. | 341 // Precompile static initializers to compute result type information. |
422 PrecompileStaticInitializers(); | 342 PrecompileStaticInitializers(); |
423 | 343 |
424 // Precompile constructors to compute type information for final fields. | 344 // Precompile constructors to compute type information for final fields. |
425 ClearAllCode(); | 345 ClearAllCode(); |
426 PrecompileConstructors(); | 346 PrecompileConstructors(); |
427 | 347 |
428 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { | 348 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { |
429 if (FLAG_trace_precompiler) { | 349 if (FLAG_trace_precompiler) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 } | 471 } |
552 | 472 |
553 private: | 473 private: |
554 Array& fields_; | 474 Array& fields_; |
555 Field& field_; | 475 Field& field_; |
556 Function& function_; | 476 Function& function_; |
557 }; | 477 }; |
558 | 478 |
559 HANDLESCOPE(T); | 479 HANDLESCOPE(T); |
560 StaticInitializerVisitor visitor(Z); | 480 StaticInitializerVisitor visitor(Z); |
561 ProgramVisitor::VisitClasses(&visitor); | 481 VisitClasses(&visitor); |
562 } | 482 } |
563 | 483 |
564 | 484 |
565 void Precompiler::PrecompileConstructors() { | 485 void Precompiler::PrecompileConstructors() { |
566 class ConstructorVisitor : public FunctionVisitor { | 486 class ConstructorVisitor : public FunctionVisitor { |
567 public: | 487 public: |
568 explicit ConstructorVisitor(Precompiler* precompiler, Zone* zone) | 488 explicit ConstructorVisitor(Precompiler* precompiler, Zone* zone) |
569 : precompiler_(precompiler), zone_(zone) {} | 489 : precompiler_(precompiler), zone_(zone) {} |
570 void Visit(const Function& function) { | 490 void Visit(const Function& function) { |
571 if (!function.IsGenerativeConstructor()) return; | 491 if (!function.IsGenerativeConstructor()) return; |
572 if (function.HasCode()) { | 492 if (function.HasCode()) { |
573 // Const constructors may have been visited before. Recompile them here | 493 // Const constructors may have been visited before. Recompile them here |
574 // to collect type information for final fields for them as well. | 494 // to collect type information for final fields for them as well. |
575 function.ClearCode(); | 495 function.ClearCode(); |
576 } | 496 } |
577 if (FLAG_trace_precompiler) { | 497 if (FLAG_trace_precompiler) { |
578 THR_Print("Precompiling constructor %s\n", function.ToCString()); | 498 THR_Print("Precompiling constructor %s\n", function.ToCString()); |
579 } | 499 } |
580 CompileFunction(precompiler_, Thread::Current(), zone_, function, | 500 CompileFunction(precompiler_, Thread::Current(), zone_, function, |
581 precompiler_->field_type_map()); | 501 precompiler_->field_type_map()); |
582 } | 502 } |
583 | 503 |
584 private: | 504 private: |
585 Precompiler* precompiler_; | 505 Precompiler* precompiler_; |
586 Zone* zone_; | 506 Zone* zone_; |
587 }; | 507 }; |
588 | 508 |
589 HANDLESCOPE(T); | 509 HANDLESCOPE(T); |
590 ConstructorVisitor visitor(this, zone_); | 510 ConstructorVisitor visitor(this, zone_); |
591 ProgramVisitor::VisitFunctions(&visitor); | 511 VisitFunctions(&visitor); |
592 | 512 |
593 FieldTypeMap::Iterator it(field_type_map_.GetIterator()); | 513 FieldTypeMap::Iterator it(field_type_map_.GetIterator()); |
594 for (FieldTypePair* current = it.Next(); current != NULL; | 514 for (FieldTypePair* current = it.Next(); current != NULL; |
595 current = it.Next()) { | 515 current = it.Next()) { |
596 const intptr_t cid = current->cid_; | 516 const intptr_t cid = current->cid_; |
597 current->field_->set_guarded_cid(cid); | 517 current->field_->set_guarded_cid(cid); |
598 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); | 518 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); |
599 if (FLAG_trace_precompiler) { | 519 if (FLAG_trace_precompiler) { |
600 THR_Print( | 520 THR_Print( |
601 "Field %s <- Type %s\n", current->field_->ToCString(), | 521 "Field %s <- Type %s\n", current->field_->ToCString(), |
602 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); | 522 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); |
603 } | 523 } |
604 } | 524 } |
605 } | 525 } |
606 | 526 |
607 | 527 |
608 void Precompiler::ClearAllCode() { | 528 void Precompiler::ClearAllCode() { |
609 class ClearCodeFunctionVisitor : public FunctionVisitor { | 529 class ClearCodeFunctionVisitor : public FunctionVisitor { |
610 void Visit(const Function& function) { | 530 void Visit(const Function& function) { |
611 function.ClearCode(); | 531 function.ClearCode(); |
612 function.ClearICDataArray(); | 532 function.ClearICDataArray(); |
613 } | 533 } |
614 }; | 534 }; |
615 ClearCodeFunctionVisitor function_visitor; | 535 ClearCodeFunctionVisitor function_visitor; |
616 ProgramVisitor::VisitFunctions(&function_visitor); | 536 VisitFunctions(&function_visitor); |
617 | 537 |
618 class ClearCodeClassVisitor : public ClassVisitor { | 538 class ClearCodeClassVisitor : public ClassVisitor { |
619 void Visit(const Class& cls) { cls.DisableAllocationStub(); } | 539 void Visit(const Class& cls) { cls.DisableAllocationStub(); } |
620 }; | 540 }; |
621 ClearCodeClassVisitor class_visitor; | 541 ClearCodeClassVisitor class_visitor; |
622 ProgramVisitor::VisitClasses(&class_visitor); | 542 VisitClasses(&class_visitor); |
623 } | 543 } |
624 | 544 |
625 | 545 |
626 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { | 546 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { |
627 // Note that <rootlibrary>.main is not a root. The appropriate main will be | 547 // Note that <rootlibrary>.main is not a root. The appropriate main will be |
628 // discovered through _getMainClosure. | 548 // discovered through _getMainClosure. |
629 | 549 |
630 AddSelector(Symbols::NoSuchMethod()); | 550 AddSelector(Symbols::NoSuchMethod()); |
631 | 551 |
632 AddSelector(Symbols::Call()); // For speed, not correctness. | 552 AddSelector(Symbols::Call()); // For speed, not correctness. |
(...skipping 1521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2154 | 2074 |
2155 private: | 2075 private: |
2156 Code& code_; | 2076 Code& code_; |
2157 Array& table_; | 2077 Array& table_; |
2158 Smi& pc_offset_; | 2078 Smi& pc_offset_; |
2159 Function& target_; | 2079 Function& target_; |
2160 Code& target_code_; | 2080 Code& target_code_; |
2161 }; | 2081 }; |
2162 | 2082 |
2163 BindStaticCallsVisitor visitor(Z); | 2083 BindStaticCallsVisitor visitor(Z); |
2164 ProgramVisitor::VisitFunctions(&visitor); | 2084 VisitFunctions(&visitor); |
2165 } | 2085 } |
2166 | 2086 |
2167 | 2087 |
2168 void Precompiler::SwitchICCalls() { | 2088 void Precompiler::SwitchICCalls() { |
2169 #if !defined(TARGET_ARCH_DBC) | 2089 #if !defined(TARGET_ARCH_DBC) |
2170 // Now that all functions have been compiled, we can switch to an instance | 2090 // Now that all functions have been compiled, we can switch to an instance |
2171 // call sequence that loads the Code object and entry point directly from | 2091 // call sequence that loads the Code object and entry point directly from |
2172 // the ic data array instead indirectly through a Function in the ic data | 2092 // the ic data array instead indirectly through a Function in the ic data |
2173 // array. Iterate all the object pools and rewrite the ic data from | 2093 // array. Iterate all the object pools and rewrite the ic data from |
2174 // (cid, target function, count) to (cid, target code, entry point), and | 2094 // (cid, target function, count) to (cid, target code, entry point), and |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2243 ICData& ic_; | 2163 ICData& ic_; |
2244 String& target_name_; | 2164 String& target_name_; |
2245 Array& args_descriptor_; | 2165 Array& args_descriptor_; |
2246 UnlinkedCall& unlinked_; | 2166 UnlinkedCall& unlinked_; |
2247 Code& target_code_; | 2167 Code& target_code_; |
2248 UnlinkedCallSet canonical_unlinked_calls_; | 2168 UnlinkedCallSet canonical_unlinked_calls_; |
2249 }; | 2169 }; |
2250 | 2170 |
2251 ASSERT(!I->compilation_allowed()); | 2171 ASSERT(!I->compilation_allowed()); |
2252 SwitchICCallsVisitor visitor(Z); | 2172 SwitchICCallsVisitor visitor(Z); |
2253 ProgramVisitor::VisitFunctions(&visitor); | 2173 VisitFunctions(&visitor); |
2254 #endif | 2174 #endif |
2255 } | 2175 } |
2256 | 2176 |
2257 | 2177 |
2258 void Precompiler::ShareMegamorphicBuckets() { | 2178 void Precompiler::ShareMegamorphicBuckets() { |
2259 const GrowableObjectArray& table = GrowableObjectArray::Handle( | 2179 const GrowableObjectArray& table = GrowableObjectArray::Handle( |
2260 Z, I->object_store()->megamorphic_cache_table()); | 2180 Z, I->object_store()->megamorphic_cache_table()); |
2261 if (table.IsNull()) return; | 2181 if (table.IsNull()) return; |
2262 MegamorphicCache& cache = MegamorphicCache::Handle(Z); | 2182 MegamorphicCache& cache = MegamorphicCache::Handle(Z); |
2263 | 2183 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2316 | 2236 |
2317 private: | 2237 private: |
2318 Zone* zone_; | 2238 Zone* zone_; |
2319 StackMapSet canonical_stackmaps_; | 2239 StackMapSet canonical_stackmaps_; |
2320 Code& code_; | 2240 Code& code_; |
2321 Array& stackmaps_; | 2241 Array& stackmaps_; |
2322 StackMap& stackmap_; | 2242 StackMap& stackmap_; |
2323 }; | 2243 }; |
2324 | 2244 |
2325 DedupStackMapsVisitor visitor(Z); | 2245 DedupStackMapsVisitor visitor(Z); |
2326 ProgramVisitor::VisitFunctions(&visitor); | 2246 VisitFunctions(&visitor); |
2327 } | 2247 } |
2328 | 2248 |
2329 | 2249 |
2330 void Precompiler::DedupLists() { | 2250 void Precompiler::DedupLists() { |
2331 class DedupListsVisitor : public FunctionVisitor { | 2251 class DedupListsVisitor : public FunctionVisitor { |
2332 public: | 2252 public: |
2333 explicit DedupListsVisitor(Zone* zone) | 2253 explicit DedupListsVisitor(Zone* zone) |
2334 : zone_(zone), | 2254 : zone_(zone), |
2335 canonical_lists_(), | 2255 canonical_lists_(), |
2336 code_(Code::Handle(zone)), | 2256 code_(Code::Handle(zone)), |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2383 } | 2303 } |
2384 | 2304 |
2385 private: | 2305 private: |
2386 Zone* zone_; | 2306 Zone* zone_; |
2387 ArraySet canonical_lists_; | 2307 ArraySet canonical_lists_; |
2388 Code& code_; | 2308 Code& code_; |
2389 Array& list_; | 2309 Array& list_; |
2390 }; | 2310 }; |
2391 | 2311 |
2392 DedupListsVisitor visitor(Z); | 2312 DedupListsVisitor visitor(Z); |
2393 ProgramVisitor::VisitFunctions(&visitor); | 2313 VisitFunctions(&visitor); |
2394 } | 2314 } |
2395 | 2315 |
2396 | 2316 |
2397 void Precompiler::DedupInstructions() { | 2317 void Precompiler::DedupInstructions() { |
2398 class DedupInstructionsVisitor : public FunctionVisitor { | 2318 class DedupInstructionsVisitor : public FunctionVisitor { |
2399 public: | 2319 public: |
2400 explicit DedupInstructionsVisitor(Zone* zone) | 2320 explicit DedupInstructionsVisitor(Zone* zone) |
2401 : zone_(zone), | 2321 : zone_(zone), |
2402 canonical_instructions_set_(), | 2322 canonical_instructions_set_(), |
2403 code_(Code::Handle(zone)), | 2323 code_(Code::Handle(zone)), |
(...skipping 25 matching lines...) Expand all Loading... |
2429 } | 2349 } |
2430 | 2350 |
2431 private: | 2351 private: |
2432 Zone* zone_; | 2352 Zone* zone_; |
2433 InstructionsSet canonical_instructions_set_; | 2353 InstructionsSet canonical_instructions_set_; |
2434 Code& code_; | 2354 Code& code_; |
2435 Instructions& instructions_; | 2355 Instructions& instructions_; |
2436 }; | 2356 }; |
2437 | 2357 |
2438 DedupInstructionsVisitor visitor(Z); | 2358 DedupInstructionsVisitor visitor(Z); |
2439 ProgramVisitor::VisitFunctions(&visitor); | 2359 VisitFunctions(&visitor); |
2440 } | 2360 } |
2441 | 2361 |
2442 | 2362 |
| 2363 void Precompiler::VisitClasses(ClassVisitor* visitor) { |
| 2364 Library& lib = Library::Handle(Z); |
| 2365 Class& cls = Class::Handle(Z); |
| 2366 |
| 2367 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
| 2368 lib ^= libraries_.At(i); |
| 2369 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); |
| 2370 while (it.HasNext()) { |
| 2371 cls = it.GetNextClass(); |
| 2372 if (cls.IsDynamicClass()) { |
| 2373 continue; // class 'dynamic' is in the read-only VM isolate. |
| 2374 } |
| 2375 visitor->Visit(cls); |
| 2376 } |
| 2377 } |
| 2378 } |
| 2379 |
| 2380 |
| 2381 void Precompiler::VisitFunctions(FunctionVisitor* visitor) { |
| 2382 Library& lib = Library::Handle(Z); |
| 2383 Class& cls = Class::Handle(Z); |
| 2384 Array& functions = Array::Handle(Z); |
| 2385 Array& fields = Array::Handle(Z); |
| 2386 Field& field = Field::Handle(Z); |
| 2387 Object& object = Object::Handle(Z); |
| 2388 Function& function = Function::Handle(Z); |
| 2389 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z); |
| 2390 |
| 2391 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
| 2392 lib ^= libraries_.At(i); |
| 2393 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); |
| 2394 while (it.HasNext()) { |
| 2395 cls = it.GetNextClass(); |
| 2396 if (cls.IsDynamicClass()) { |
| 2397 continue; // class 'dynamic' is in the read-only VM isolate. |
| 2398 } |
| 2399 |
| 2400 functions = cls.functions(); |
| 2401 for (intptr_t j = 0; j < functions.Length(); j++) { |
| 2402 function ^= functions.At(j); |
| 2403 visitor->Visit(function); |
| 2404 if (function.HasImplicitClosureFunction()) { |
| 2405 function = function.ImplicitClosureFunction(); |
| 2406 visitor->Visit(function); |
| 2407 } |
| 2408 } |
| 2409 |
| 2410 functions = cls.invocation_dispatcher_cache(); |
| 2411 for (intptr_t j = 0; j < functions.Length(); j++) { |
| 2412 object = functions.At(j); |
| 2413 if (object.IsFunction()) { |
| 2414 function ^= functions.At(j); |
| 2415 visitor->Visit(function); |
| 2416 } |
| 2417 } |
| 2418 fields = cls.fields(); |
| 2419 for (intptr_t j = 0; j < fields.Length(); j++) { |
| 2420 field ^= fields.At(j); |
| 2421 if (field.is_static() && field.HasPrecompiledInitializer()) { |
| 2422 function ^= field.PrecompiledInitializer(); |
| 2423 visitor->Visit(function); |
| 2424 } |
| 2425 } |
| 2426 } |
| 2427 } |
| 2428 closures = isolate()->object_store()->closure_functions(); |
| 2429 for (intptr_t j = 0; j < closures.Length(); j++) { |
| 2430 function ^= closures.At(j); |
| 2431 visitor->Visit(function); |
| 2432 ASSERT(!function.HasImplicitClosureFunction()); |
| 2433 } |
| 2434 } |
| 2435 |
| 2436 |
2443 void Precompiler::FinalizeAllClasses() { | 2437 void Precompiler::FinalizeAllClasses() { |
2444 Library& lib = Library::Handle(Z); | 2438 Library& lib = Library::Handle(Z); |
2445 Class& cls = Class::Handle(Z); | 2439 Class& cls = Class::Handle(Z); |
2446 | 2440 |
2447 for (intptr_t i = 0; i < libraries_.Length(); i++) { | 2441 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
2448 lib ^= libraries_.At(i); | 2442 lib ^= libraries_.At(i); |
2449 if (!lib.Loaded()) { | 2443 if (!lib.Loaded()) { |
2450 String& uri = String::Handle(Z, lib.url()); | 2444 String& uri = String::Handle(Z, lib.url()); |
2451 String& msg = String::Handle( | 2445 String& msg = String::Handle( |
2452 Z, | 2446 Z, |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2606 } | 2600 } |
2607 } | 2601 } |
2608 | 2602 |
2609 #if defined(DEBUG) | 2603 #if defined(DEBUG) |
2610 I->class_table()->Validate(); | 2604 I->class_table()->Validate(); |
2611 I->heap()->Verify(); | 2605 I->heap()->Verify(); |
2612 #endif | 2606 #endif |
2613 } | 2607 } |
2614 | 2608 |
2615 | 2609 |
2616 void Precompiler::VerifyJITFeedback() { | |
2617 if (jit_feedback_ == NULL) return; | |
2618 | |
2619 ParsedJSONString* js_vmversion = jit_feedback_->StringAt("vmVersion"); | |
2620 if ((js_vmversion == NULL) || | |
2621 strcmp(js_vmversion->value(), Version::CommitString()) != 0) { | |
2622 THR_Print( | |
2623 "JIT feedback contains invalid vm version " | |
2624 "(saw %s, expected %s).\n", | |
2625 js_vmversion->value(), Version::CommitString()); | |
2626 jit_feedback_ = NULL; | |
2627 return; | |
2628 } | |
2629 ParsedJSONBoolean* js_asserts = jit_feedback_->BooleanAt("asserts"); | |
2630 if ((js_asserts == NULL) || (FLAG_enable_asserts != js_asserts->value())) { | |
2631 THR_Print("JIT feedback contains invalid FLAG_enable_asserts\n"); | |
2632 jit_feedback_ = NULL; | |
2633 return; | |
2634 } | |
2635 ParsedJSONBoolean* js_typechecks = jit_feedback_->BooleanAt("typeChecks"); | |
2636 if ((js_typechecks == NULL) || | |
2637 (FLAG_enable_type_checks != js_typechecks->value())) { | |
2638 THR_Print("JIT feedback contains invalid FLAG_enable_type_checks\n"); | |
2639 jit_feedback_ = NULL; | |
2640 return; | |
2641 } | |
2642 | |
2643 ParsedJSONArray* js_scripts = jit_feedback_->ArrayAt("scripts"); | |
2644 ASSERT(js_scripts != NULL); | |
2645 Script& script = Script::Handle(Z); | |
2646 for (intptr_t i = 0; i < js_scripts->Length(); i++) { | |
2647 ParsedJSONObject* js_script = js_scripts->ObjectAt(i); | |
2648 ASSERT(js_script != NULL); | |
2649 ParsedJSONString* js_uri = js_script->StringAt("uri"); | |
2650 ASSERT(js_uri != NULL); | |
2651 ParsedJSONNumber* js_fp = js_script->NumberAt("checksum"); | |
2652 ASSERT(js_fp != NULL); | |
2653 script = LookupScript(js_uri->value()); | |
2654 if (script.IsNull()) { | |
2655 THR_Print("Cannot find script %s\n", js_uri->value()); | |
2656 continue; | |
2657 } | |
2658 intptr_t fp = script.SourceFingerprint(); | |
2659 if (fp != js_fp->value()) { | |
2660 THR_Print( | |
2661 "Fingerprint has changed for %s. Continuing without JIT " | |
2662 "feedback.\n", | |
2663 js_uri->value()); | |
2664 jit_feedback_ = NULL; | |
2665 return; | |
2666 } | |
2667 } | |
2668 | |
2669 ParsedJSONArray* js_classes = jit_feedback_->ArrayAt("classes"); | |
2670 ASSERT(js_classes != NULL); | |
2671 Library& lib = Library::Handle(Z); | |
2672 Class& cls = Class::Handle(Z); | |
2673 String& str = String::Handle(Z); | |
2674 for (intptr_t i = 0; i < js_classes->Length(); i++) { | |
2675 ParsedJSONObject* js_class = js_classes->ObjectAt(i); | |
2676 ASSERT(js_class != NULL); | |
2677 ParsedJSONString* js_uri = js_class->StringAt("uri"); | |
2678 ASSERT(js_uri != NULL); | |
2679 ParsedJSONString* js_name = js_class->StringAt("name"); | |
2680 ASSERT(js_name != NULL); | |
2681 ParsedJSONNumber* js_cid = js_class->NumberAt("cid"); | |
2682 ASSERT(js_cid != NULL); | |
2683 | |
2684 str = String::New(js_uri->value()); | |
2685 lib = Library::LookupLibrary(T, str); | |
2686 if (lib.IsNull()) { | |
2687 THR_Print("Cannot find library %s\n", js_uri->value()); | |
2688 continue; | |
2689 } | |
2690 str = String::New(js_name->value()); | |
2691 if (str.Equals(Symbols::TopLevel())) { | |
2692 cls = lib.toplevel_class(); | |
2693 } else { | |
2694 cls = lib.LookupClassAllowPrivate(str); | |
2695 } | |
2696 if (cls.IsNull()) { | |
2697 THR_Print("Missing class %s\n", js_name->value()); | |
2698 continue; | |
2699 } | |
2700 | |
2701 feedback_cid_map_.Insert(IntptrPair(js_cid->value(), cls.id())); | |
2702 } | |
2703 | |
2704 ParsedJSONArray* js_functions = jit_feedback_->ArrayAt("functions"); | |
2705 ASSERT(js_functions != NULL); | |
2706 for (intptr_t i = 0; i < js_functions->Length(); i++) { | |
2707 ParsedJSONObject* js_function = js_functions->ObjectAt(i); | |
2708 ASSERT(js_function != NULL); | |
2709 ParsedJSONString* js_name = js_function->StringAt("name"); | |
2710 ASSERT(js_name != NULL); | |
2711 ParsedJSONNumber* js_cid = js_function->NumberAt("class"); | |
2712 ASSERT(js_cid != NULL); | |
2713 ParsedJSONNumber* js_token = js_function->NumberAt("tokenPos"); | |
2714 ASSERT(js_token != NULL); | |
2715 ParsedJSONNumber* js_kind = js_function->NumberAt("kind"); | |
2716 ASSERT(js_kind != NULL); | |
2717 function_feedback_map_.Insert(FunctionFeedbackPair( | |
2718 FunctionFeedbackKey(MapCid(js_cid->value()), js_token->value(), | |
2719 js_kind->value()), | |
2720 js_function)); | |
2721 } | |
2722 | |
2723 class ApplyUsageVisitor : public FunctionVisitor { | |
2724 public: | |
2725 explicit ApplyUsageVisitor(Precompiler* precompiler) | |
2726 : precompiler_(precompiler) {} | |
2727 void Visit(const Function& function) { | |
2728 ParsedJSONObject* js_function = precompiler_->LookupFeedback(function); | |
2729 if (js_function == NULL) { | |
2730 function.set_usage_counter(0); | |
2731 } else { | |
2732 ParsedJSONNumber* js_usage = js_function->NumberAt("usageCounter"); | |
2733 ASSERT(js_usage != NULL); | |
2734 function.set_usage_counter(js_usage->value()); | |
2735 } | |
2736 } | |
2737 | |
2738 private: | |
2739 Precompiler* precompiler_; | |
2740 }; | |
2741 | |
2742 ApplyUsageVisitor visitor(this); | |
2743 ProgramVisitor::VisitFunctions(&visitor); | |
2744 } | |
2745 | |
2746 | |
2747 ParsedJSONObject* Precompiler::LookupFeedback(const Function& function) { | |
2748 const Class& owner = Class::Handle(Z, function.Owner()); | |
2749 | |
2750 FunctionFeedbackKey key(owner.id(), function.token_pos().value(), | |
2751 function.kind()); | |
2752 FunctionFeedbackPair* pair = function_feedback_map_.Lookup(key); | |
2753 if (pair == NULL) { | |
2754 return NULL; | |
2755 } | |
2756 return pair->value_; | |
2757 } | |
2758 | |
2759 | |
2760 RawScript* Precompiler::LookupScript(const char* uri) { | |
2761 String& dart_uri = String::Handle(Z, String::New(uri)); | |
2762 Library& lib = Library::Handle(Z); | |
2763 Script& script = Script::Handle(Z); | |
2764 for (intptr_t i = 0; i < libraries_.Length(); i++) { | |
2765 lib ^= libraries_.At(i); | |
2766 script = lib.LookupScript(dart_uri); | |
2767 if (!script.IsNull()) { | |
2768 return script.raw(); | |
2769 } | |
2770 } | |
2771 return Script::null(); | |
2772 } | |
2773 | |
2774 | |
2775 intptr_t Precompiler::MapCid(intptr_t feedback_cid) { | |
2776 if (feedback_cid < kNumPredefinedCids) { | |
2777 return feedback_cid; | |
2778 } | |
2779 IntptrPair* pair = feedback_cid_map_.Lookup(feedback_cid); | |
2780 if (pair == NULL) return kIllegalCid; | |
2781 return pair->value_; | |
2782 } | |
2783 | |
2784 | |
2785 void Precompiler::PopulateWithICData(const Function& function, | |
2786 FlowGraph* graph) { | |
2787 Zone* zone = Thread::Current()->zone(); | |
2788 | |
2789 for (BlockIterator block_it = graph->reverse_postorder_iterator(); | |
2790 !block_it.Done(); block_it.Advance()) { | |
2791 ForwardInstructionIterator it(block_it.Current()); | |
2792 for (; !it.Done(); it.Advance()) { | |
2793 Instruction* instr = it.Current(); | |
2794 if (instr->IsInstanceCall()) { | |
2795 InstanceCallInstr* call = instr->AsInstanceCall(); | |
2796 if (!call->HasICData()) { | |
2797 const Array& arguments_descriptor = Array::Handle( | |
2798 zone, ArgumentsDescriptor::New(call->ArgumentCount(), | |
2799 call->argument_names())); | |
2800 const ICData& ic_data = ICData::ZoneHandle( | |
2801 zone, ICData::New(function, call->function_name(), | |
2802 arguments_descriptor, call->deopt_id(), | |
2803 call->checked_argument_count(), false)); | |
2804 call->set_ic_data(&ic_data); | |
2805 } | |
2806 } else if (instr->IsStaticCall()) { | |
2807 StaticCallInstr* call = instr->AsStaticCall(); | |
2808 if (!call->HasICData()) { | |
2809 const Array& arguments_descriptor = Array::Handle( | |
2810 zone, ArgumentsDescriptor::New(call->ArgumentCount(), | |
2811 call->argument_names())); | |
2812 const Function& target = call->function(); | |
2813 MethodRecognizer::Kind recognized_kind = | |
2814 MethodRecognizer::RecognizeKind(target); | |
2815 int num_args_checked = 0; | |
2816 switch (recognized_kind) { | |
2817 case MethodRecognizer::kDoubleFromInteger: | |
2818 case MethodRecognizer::kMathMin: | |
2819 case MethodRecognizer::kMathMax: | |
2820 num_args_checked = 2; | |
2821 break; | |
2822 default: | |
2823 break; | |
2824 } | |
2825 const ICData& ic_data = ICData::ZoneHandle( | |
2826 zone, ICData::New(function, String::Handle(zone, target.name()), | |
2827 arguments_descriptor, call->deopt_id(), | |
2828 num_args_checked, true)); | |
2829 ic_data.AddTarget(target); | |
2830 call->set_ic_data(&ic_data); | |
2831 } | |
2832 } | |
2833 } | |
2834 } | |
2835 } | |
2836 | |
2837 | |
2838 void Precompiler::TryApplyFeedback(const Function& function, FlowGraph* graph) { | |
2839 ParsedJSONObject* js_function = LookupFeedback(function); | |
2840 if (js_function == NULL) { | |
2841 if (FLAG_trace_precompiler) { | |
2842 THR_Print("No feedback available for %s\n", | |
2843 function.ToQualifiedCString()); | |
2844 } | |
2845 return; | |
2846 } | |
2847 | |
2848 ParsedJSONArray* js_icdatas = js_function->ArrayAt("ics"); | |
2849 ASSERT(js_icdatas != NULL); | |
2850 | |
2851 for (BlockIterator block_it = graph->reverse_postorder_iterator(); | |
2852 !block_it.Done(); block_it.Advance()) { | |
2853 ForwardInstructionIterator it(block_it.Current()); | |
2854 for (; !it.Done(); it.Advance()) { | |
2855 Instruction* instr = it.Current(); | |
2856 if (instr->IsInstanceCall()) { | |
2857 InstanceCallInstr* call = instr->AsInstanceCall(); | |
2858 TryApplyFeedback(js_icdatas, *call->ic_data()); | |
2859 } else if (instr->IsStaticCall()) { | |
2860 StaticCallInstr* call = instr->AsStaticCall(); | |
2861 TryApplyFeedback(js_icdatas, *call->ic_data()); | |
2862 } | |
2863 } | |
2864 } | |
2865 } | |
2866 | |
2867 | |
2868 void Precompiler::TryApplyFeedback(ParsedJSONArray* js_icdatas, | |
2869 const ICData& ic) { | |
2870 for (intptr_t j = 0; j < js_icdatas->Length(); j++) { | |
2871 ParsedJSONObject* js_icdata = js_icdatas->ObjectAt(j); | |
2872 ASSERT(js_icdata != NULL); | |
2873 | |
2874 ParsedJSONNumber* js_deoptid = js_icdata->NumberAt("deoptId"); | |
2875 ASSERT(js_deoptid != NULL); | |
2876 if (js_deoptid->value() != ic.deopt_id()) continue; | |
2877 | |
2878 ParsedJSONBoolean* js_isstaticcall = js_icdata->BooleanAt("isStaticCall"); | |
2879 ASSERT(js_isstaticcall != NULL); | |
2880 if (js_isstaticcall->value() != ic.is_static_call()) return; | |
2881 | |
2882 ParsedJSONNumber* js_argsTested = js_icdata->NumberAt("argsTested"); | |
2883 ASSERT(js_argsTested != NULL); | |
2884 if (js_argsTested->value() != ic.NumArgsTested()) return; | |
2885 | |
2886 ParsedJSONString* js_selector = js_icdata->StringAt("selector"); | |
2887 ASSERT(js_selector != NULL); | |
2888 const String& feedback_selector = | |
2889 String::Handle(String::New(js_selector->value())); | |
2890 const String& selector = String::Handle(ic.target_name()); | |
2891 // N.B.: EqualsIgnoringPrivateKey is not symmetric. | |
2892 if (!String::EqualsIgnoringPrivateKey(selector, feedback_selector)) return; | |
2893 | |
2894 ParsedJSONArray* js_entries = js_icdata->ArrayAt("entries"); | |
2895 ASSERT(js_entries != NULL); | |
2896 if (ic.is_static_call()) { | |
2897 // [cid [cid]] target count | |
2898 ParsedJSONNumber* entry = js_entries->NumberAt(js_entries->Length() - 1); | |
2899 ASSERT(entry != NULL); | |
2900 ic.SetCountAt(0, entry->value()); | |
2901 } else { | |
2902 // [cid [cid [cid]]] target count | |
2903 const Array& arguments_descriptor = | |
2904 Array::Handle(ic.arguments_descriptor()); | |
2905 ArgumentsDescriptor args_desc(arguments_descriptor); | |
2906 | |
2907 intptr_t num_args_checked = ic.NumArgsTested(); | |
2908 for (intptr_t k = 0; k < js_entries->Length(); | |
2909 k += num_args_checked + 1) { | |
2910 GrowableArray<intptr_t> class_ids(num_args_checked); | |
2911 for (intptr_t arg = 0; arg < num_args_checked; arg++) { | |
2912 ParsedJSONNumber* entry = js_entries->NumberAt(k + arg); | |
2913 ASSERT(entry != NULL); | |
2914 class_ids.Add(MapCid(entry->value())); | |
2915 } | |
2916 ParsedJSONNumber* entry = js_entries->NumberAt(k + num_args_checked); | |
2917 ASSERT(entry != NULL); | |
2918 intptr_t count = entry->value(); | |
2919 | |
2920 bool has_missing_cid = false; | |
2921 for (intptr_t arg = 0; arg < num_args_checked; arg++) { | |
2922 if (class_ids[arg] == kIllegalCid) { | |
2923 has_missing_cid = true; | |
2924 } | |
2925 } | |
2926 if (has_missing_cid) continue; | |
2927 | |
2928 intptr_t receiver_cid = class_ids[0]; | |
2929 const Class& receiver_cls = | |
2930 Class::Handle(I->class_table()->At(receiver_cid)); | |
2931 if (receiver_cls.IsClass()) { | |
2932 const Function& target = | |
2933 Function::Handle(Resolver::ResolveDynamicForReceiverClass( | |
2934 receiver_cls, selector, args_desc, false)); | |
2935 // TODO(rmacnak): Create missing dispatchers. | |
2936 if (!target.IsNull()) { | |
2937 if (num_args_checked == 1) { | |
2938 ic.AddReceiverCheck(receiver_cid, target, count); | |
2939 } else { | |
2940 ic.AddCheck(class_ids, target, count); | |
2941 } | |
2942 } | |
2943 } | |
2944 } | |
2945 } | |
2946 | |
2947 return; | |
2948 } | |
2949 } | |
2950 | |
2951 | |
2952 void Precompiler::ResetPrecompilerState() { | 2610 void Precompiler::ResetPrecompilerState() { |
2953 changed_ = false; | 2611 changed_ = false; |
2954 function_count_ = 0; | 2612 function_count_ = 0; |
2955 class_count_ = 0; | 2613 class_count_ = 0; |
2956 selector_count_ = 0; | 2614 selector_count_ = 0; |
2957 dropped_function_count_ = 0; | 2615 dropped_function_count_ = 0; |
2958 dropped_field_count_ = 0; | 2616 dropped_field_count_ = 0; |
2959 ASSERT(pending_functions_.Length() == 0); | 2617 ASSERT(pending_functions_.Length() == 0); |
2960 sent_selectors_.Clear(); | 2618 sent_selectors_.Clear(); |
2961 enqueued_functions_.Clear(); | 2619 enqueued_functions_.Clear(); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3092 ZoneGrowableArray<const ICData*>* ic_data_array = | 2750 ZoneGrowableArray<const ICData*>* ic_data_array = |
3093 new (zone) ZoneGrowableArray<const ICData*>(); | 2751 new (zone) ZoneGrowableArray<const ICData*>(); |
3094 #ifndef PRODUCT | 2752 #ifndef PRODUCT |
3095 TimelineDurationScope tds(thread(), compiler_timeline, | 2753 TimelineDurationScope tds(thread(), compiler_timeline, |
3096 "BuildFlowGraph"); | 2754 "BuildFlowGraph"); |
3097 #endif // !PRODUCT | 2755 #endif // !PRODUCT |
3098 flow_graph = pipeline->BuildFlowGraph( | 2756 flow_graph = pipeline->BuildFlowGraph( |
3099 zone, parsed_function(), *ic_data_array, Compiler::kNoOSRDeoptId); | 2757 zone, parsed_function(), *ic_data_array, Compiler::kNoOSRDeoptId); |
3100 } | 2758 } |
3101 | 2759 |
3102 if (optimized()) { | |
3103 Precompiler::PopulateWithICData(parsed_function()->function(), | |
3104 flow_graph); | |
3105 if (precompiler_ != NULL) { | |
3106 precompiler_->TryApplyFeedback(parsed_function()->function(), | |
3107 flow_graph); | |
3108 } | |
3109 } | |
3110 | |
3111 const bool print_flow_graph = | 2760 const bool print_flow_graph = |
3112 (FLAG_print_flow_graph || | 2761 (FLAG_print_flow_graph || |
3113 (optimized() && FLAG_print_flow_graph_optimized)) && | 2762 (optimized() && FLAG_print_flow_graph_optimized)) && |
3114 FlowGraphPrinter::ShouldPrint(function); | 2763 FlowGraphPrinter::ShouldPrint(function); |
3115 | 2764 |
3116 if (print_flow_graph) { | 2765 if (print_flow_graph) { |
3117 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); | 2766 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); |
3118 } | 2767 } |
3119 | 2768 |
3120 if (optimized()) { | 2769 if (optimized()) { |
(...skipping 30 matching lines...) Expand all Loading... |
3151 // is that the length of |inline_id_to_function| is always larger | 2800 // is that the length of |inline_id_to_function| is always larger |
3152 // than the length of |inline_id_to_token_pos| by one. | 2801 // than the length of |inline_id_to_token_pos| by one. |
3153 // Top scope function has no caller (-1). We do this because we expect | 2802 // Top scope function has no caller (-1). We do this because we expect |
3154 // all token positions to be at an inlined call. | 2803 // all token positions to be at an inlined call. |
3155 // Top scope function has no caller (-1). | 2804 // Top scope function has no caller (-1). |
3156 caller_inline_id.Add(-1); | 2805 caller_inline_id.Add(-1); |
3157 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); | 2806 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); |
3158 | 2807 |
3159 AotOptimizer optimizer(precompiler_, flow_graph, | 2808 AotOptimizer optimizer(precompiler_, flow_graph, |
3160 use_speculative_inlining, &inlining_black_list); | 2809 use_speculative_inlining, &inlining_black_list); |
| 2810 optimizer.PopulateWithICData(); |
3161 | 2811 |
3162 optimizer.ApplyClassIds(); | 2812 optimizer.ApplyClassIds(); |
3163 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2813 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3164 | 2814 |
3165 FlowGraphTypePropagator::Propagate(flow_graph); | 2815 FlowGraphTypePropagator::Propagate(flow_graph); |
3166 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2816 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3167 | 2817 |
3168 optimizer.ApplyICData(); | 2818 optimizer.ApplyICData(); |
3169 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2819 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3170 | 2820 |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3649 | 3299 |
3650 ASSERT(FLAG_precompiled_mode); | 3300 ASSERT(FLAG_precompiled_mode); |
3651 const bool optimized = function.IsOptimizable(); // False for natives. | 3301 const bool optimized = function.IsOptimizable(); // False for natives. |
3652 DartPrecompilationPipeline pipeline(zone, field_type_map); | 3302 DartPrecompilationPipeline pipeline(zone, field_type_map); |
3653 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); | 3303 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); |
3654 } | 3304 } |
3655 | 3305 |
3656 #endif // DART_PRECOMPILER | 3306 #endif // DART_PRECOMPILER |
3657 | 3307 |
3658 } // namespace dart | 3308 } // namespace dart |
OLD | NEW |