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

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

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 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/flow_graph_compiler_x64.cc ('k') | runtime/vm/flow_graph_range_analysis.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 #if !defined(DART_PRECOMPILED_RUNTIME) 4 #if !defined(DART_PRECOMPILED_RUNTIME)
5 #include "vm/flow_graph_inliner.h" 5 #include "vm/flow_graph_inliner.h"
6 6
7 #include "vm/aot_optimizer.h" 7 #include "vm/aot_optimizer.h"
8 #include "vm/precompiler.h"
9 #include "vm/block_scheduler.h" 8 #include "vm/block_scheduler.h"
10 #include "vm/branch_optimizer.h" 9 #include "vm/branch_optimizer.h"
11 #include "vm/compiler.h" 10 #include "vm/compiler.h"
12 #include "vm/kernel.h"
13 #include "vm/kernel_to_il.h"
14 #include "vm/flags.h" 11 #include "vm/flags.h"
15 #include "vm/flow_graph.h" 12 #include "vm/flow_graph.h"
16 #include "vm/flow_graph_builder.h" 13 #include "vm/flow_graph_builder.h"
17 #include "vm/flow_graph_compiler.h" 14 #include "vm/flow_graph_compiler.h"
18 #include "vm/flow_graph_type_propagator.h" 15 #include "vm/flow_graph_type_propagator.h"
19 #include "vm/il_printer.h" 16 #include "vm/il_printer.h"
20 #include "vm/jit_optimizer.h" 17 #include "vm/jit_optimizer.h"
18 #include "vm/kernel.h"
19 #include "vm/kernel_to_il.h"
21 #include "vm/longjump.h" 20 #include "vm/longjump.h"
22 #include "vm/object.h" 21 #include "vm/object.h"
23 #include "vm/object_store.h" 22 #include "vm/object_store.h"
23 #include "vm/precompiler.h"
24 #include "vm/timer.h" 24 #include "vm/timer.h"
25 25
26 namespace dart { 26 namespace dart {
27 27
28 DEFINE_FLAG(int, 28 DEFINE_FLAG(int,
29 deoptimization_counter_inlining_threshold, 29 deoptimization_counter_inlining_threshold,
30 12, 30 12,
31 "How many times we allow deoptimization before we stop inlining."); 31 "How many times we allow deoptimization before we stop inlining.");
32 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining"); 32 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining");
33 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function"); 33 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function");
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } while (false) 109 } while (false)
110 110
111 #define PRINT_INLINING_TREE(comment, caller, target, instance_call) \ 111 #define PRINT_INLINING_TREE(comment, caller, target, instance_call) \
112 do { \ 112 do { \
113 if (FLAG_print_inlining_tree) { \ 113 if (FLAG_print_inlining_tree) { \
114 inlined_info_.Add(InlinedInfo(caller, target, inlining_depth_, \ 114 inlined_info_.Add(InlinedInfo(caller, target, inlining_depth_, \
115 instance_call, comment)); \ 115 instance_call, comment)); \
116 } \ 116 } \
117 } while (false) 117 } while (false)
118 118
119
120 // Test if a call is recursive by looking in the deoptimization environment. 119 // Test if a call is recursive by looking in the deoptimization environment.
121 static bool IsCallRecursive(const Function& function, Definition* call) { 120 static bool IsCallRecursive(const Function& function, Definition* call) {
122 Environment* env = call->env(); 121 Environment* env = call->env();
123 while (env != NULL) { 122 while (env != NULL) {
124 if (function.raw() == env->function().raw()) { 123 if (function.raw() == env->function().raw()) {
125 return true; 124 return true;
126 } 125 }
127 env = env->outer(); 126 env = env->outer();
128 } 127 }
129 return false; 128 return false;
130 } 129 }
131 130
132
133 // Helper to get the default value of a formal parameter. 131 // Helper to get the default value of a formal parameter.
134 static ConstantInstr* GetDefaultValue(intptr_t i, 132 static ConstantInstr* GetDefaultValue(intptr_t i,
135 const ParsedFunction& parsed_function) { 133 const ParsedFunction& parsed_function) {
136 return new ConstantInstr(parsed_function.DefaultParameterValueAt(i)); 134 return new ConstantInstr(parsed_function.DefaultParameterValueAt(i));
137 } 135 }
138 136
139
140 // Pair of an argument name and its value. 137 // Pair of an argument name and its value.
141 struct NamedArgument { 138 struct NamedArgument {
142 String* name; 139 String* name;
143 Value* value; 140 Value* value;
144 NamedArgument(String* name, Value* value) : name(name), value(value) {} 141 NamedArgument(String* name, Value* value) : name(name), value(value) {}
145 }; 142 };
146 143
147
148 // Helper to collect information about a callee graph when considering it for 144 // Helper to collect information about a callee graph when considering it for
149 // inlining. 145 // inlining.
150 class GraphInfoCollector : public ValueObject { 146 class GraphInfoCollector : public ValueObject {
151 public: 147 public:
152 GraphInfoCollector() : call_site_count_(0), instruction_count_(0) {} 148 GraphInfoCollector() : call_site_count_(0), instruction_count_(0) {}
153 149
154 void Collect(const FlowGraph& graph) { 150 void Collect(const FlowGraph& graph) {
155 call_site_count_ = 0; 151 call_site_count_ = 0;
156 instruction_count_ = 0; 152 instruction_count_ = 0;
157 for (BlockIterator block_it = graph.postorder_iterator(); !block_it.Done(); 153 for (BlockIterator block_it = graph.postorder_iterator(); !block_it.Done();
(...skipping 29 matching lines...) Expand all
187 } 183 }
188 184
189 intptr_t call_site_count() const { return call_site_count_; } 185 intptr_t call_site_count() const { return call_site_count_; }
190 intptr_t instruction_count() const { return instruction_count_; } 186 intptr_t instruction_count() const { return instruction_count_; }
191 187
192 private: 188 private:
193 intptr_t call_site_count_; 189 intptr_t call_site_count_;
194 intptr_t instruction_count_; 190 intptr_t instruction_count_;
195 }; 191 };
196 192
197
198 // Structure for collecting inline data needed to print inlining tree. 193 // Structure for collecting inline data needed to print inlining tree.
199 struct InlinedInfo { 194 struct InlinedInfo {
200 const Function* caller; 195 const Function* caller;
201 const Function* inlined; 196 const Function* inlined;
202 intptr_t inlined_depth; 197 intptr_t inlined_depth;
203 const Definition* call_instr; 198 const Definition* call_instr;
204 const char* bailout_reason; 199 const char* bailout_reason;
205 InlinedInfo(const Function* caller_function, 200 InlinedInfo(const Function* caller_function,
206 const Function* inlined_function, 201 const Function* inlined_function,
207 const intptr_t depth, 202 const intptr_t depth,
208 const Definition* call, 203 const Definition* call,
209 const char* reason) 204 const char* reason)
210 : caller(caller_function), 205 : caller(caller_function),
211 inlined(inlined_function), 206 inlined(inlined_function),
212 inlined_depth(depth), 207 inlined_depth(depth),
213 call_instr(call), 208 call_instr(call),
214 bailout_reason(reason) {} 209 bailout_reason(reason) {}
215 }; 210 };
216 211
217
218 // A collection of call sites to consider for inlining. 212 // A collection of call sites to consider for inlining.
219 class CallSites : public ValueObject { 213 class CallSites : public ValueObject {
220 public: 214 public:
221 explicit CallSites(FlowGraph* flow_graph, intptr_t threshold) 215 explicit CallSites(FlowGraph* flow_graph, intptr_t threshold)
222 : inlining_depth_threshold_(threshold), 216 : inlining_depth_threshold_(threshold),
223 static_calls_(), 217 static_calls_(),
224 closure_calls_(), 218 closure_calls_(),
225 instance_calls_() {} 219 instance_calls_() {}
226 220
227 struct InstanceCallInfo { 221 struct InstanceCallInfo {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 // TODO(srdjan): Add data for closure calls. 339 // TODO(srdjan): Add data for closure calls.
346 } 340 }
347 if (call != NULL) { 341 if (call != NULL) {
348 inlined_info->Add( 342 inlined_info->Add(
349 InlinedInfo(caller, &target, depth + 1, call, "Too deep")); 343 InlinedInfo(caller, &target, depth + 1, call, "Too deep"));
350 } 344 }
351 } 345 }
352 } 346 }
353 } 347 }
354 348
355
356 void FindCallSites(FlowGraph* graph, 349 void FindCallSites(FlowGraph* graph,
357 intptr_t depth, 350 intptr_t depth,
358 GrowableArray<InlinedInfo>* inlined_info) { 351 GrowableArray<InlinedInfo>* inlined_info) {
359 ASSERT(graph != NULL); 352 ASSERT(graph != NULL);
360 if (depth > inlining_depth_threshold_) { 353 if (depth > inlining_depth_threshold_) {
361 if (FLAG_print_inlining_tree) { 354 if (FLAG_print_inlining_tree) {
362 RecordAllNotInlinedFunction(graph, depth, inlined_info); 355 RecordAllNotInlinedFunction(graph, depth, inlined_info);
363 } 356 }
364 return; 357 return;
365 } 358 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 415
423 private: 416 private:
424 intptr_t inlining_depth_threshold_; 417 intptr_t inlining_depth_threshold_;
425 GrowableArray<StaticCallInfo> static_calls_; 418 GrowableArray<StaticCallInfo> static_calls_;
426 GrowableArray<ClosureCallInfo> closure_calls_; 419 GrowableArray<ClosureCallInfo> closure_calls_;
427 GrowableArray<InstanceCallInfo> instance_calls_; 420 GrowableArray<InstanceCallInfo> instance_calls_;
428 421
429 DISALLOW_COPY_AND_ASSIGN(CallSites); 422 DISALLOW_COPY_AND_ASSIGN(CallSites);
430 }; 423 };
431 424
432
433 struct InlinedCallData { 425 struct InlinedCallData {
434 InlinedCallData(Definition* call, 426 InlinedCallData(Definition* call,
435 intptr_t first_param_index, // 1 if type args are passed. 427 intptr_t first_param_index, // 1 if type args are passed.
436 GrowableArray<Value*>* arguments, 428 GrowableArray<Value*>* arguments,
437 const Function& caller, 429 const Function& caller,
438 intptr_t caller_inlining_id) 430 intptr_t caller_inlining_id)
439 : call(call), 431 : call(call),
440 first_param_index(first_param_index), 432 first_param_index(first_param_index),
441 arguments(arguments), 433 arguments(arguments),
442 callee_graph(NULL), 434 callee_graph(NULL),
443 parameter_stubs(NULL), 435 parameter_stubs(NULL),
444 exit_collector(NULL), 436 exit_collector(NULL),
445 caller(caller), 437 caller(caller),
446 caller_inlining_id(caller_inlining_id) {} 438 caller_inlining_id(caller_inlining_id) {}
447 439
448 Definition* call; 440 Definition* call;
449 const intptr_t first_param_index; 441 const intptr_t first_param_index;
450 GrowableArray<Value*>* arguments; 442 GrowableArray<Value*>* arguments;
451 FlowGraph* callee_graph; 443 FlowGraph* callee_graph;
452 ZoneGrowableArray<Definition*>* parameter_stubs; 444 ZoneGrowableArray<Definition*>* parameter_stubs;
453 InlineExitCollector* exit_collector; 445 InlineExitCollector* exit_collector;
454 const Function& caller; 446 const Function& caller;
455 const intptr_t caller_inlining_id; 447 const intptr_t caller_inlining_id;
456 }; 448 };
457 449
458
459 class CallSiteInliner; 450 class CallSiteInliner;
460 451
461 class PolymorphicInliner : public ValueObject { 452 class PolymorphicInliner : public ValueObject {
462 public: 453 public:
463 PolymorphicInliner(CallSiteInliner* owner, 454 PolymorphicInliner(CallSiteInliner* owner,
464 PolymorphicInstanceCallInstr* call, 455 PolymorphicInstanceCallInstr* call,
465 const Function& caller_function, 456 const Function& caller_function,
466 intptr_t caller_inlining_id); 457 intptr_t caller_inlining_id);
467 458
468 void Inline(); 459 void Inline();
(...skipping 21 matching lines...) Expand all
490 // The non_inlined_variants_ can be used in a long-lived instruction object, 481 // The non_inlined_variants_ can be used in a long-lived instruction object,
491 // so they are not embedded into the shorter-lived PolymorphicInliner object. 482 // so they are not embedded into the shorter-lived PolymorphicInliner object.
492 CallTargets* non_inlined_variants_; 483 CallTargets* non_inlined_variants_;
493 GrowableArray<BlockEntryInstr*> inlined_entries_; 484 GrowableArray<BlockEntryInstr*> inlined_entries_;
494 InlineExitCollector* exit_collector_; 485 InlineExitCollector* exit_collector_;
495 486
496 const Function& caller_function_; 487 const Function& caller_function_;
497 const intptr_t caller_inlining_id_; 488 const intptr_t caller_inlining_id_;
498 }; 489 };
499 490
500
501 static bool HasAnnotation(const Function& function, const char* annotation) { 491 static bool HasAnnotation(const Function& function, const char* annotation) {
502 const Class& owner = Class::Handle(function.Owner()); 492 const Class& owner = Class::Handle(function.Owner());
503 const Library& library = Library::Handle(owner.library()); 493 const Library& library = Library::Handle(owner.library());
504 const Array& metadata = 494 const Array& metadata =
505 Array::Cast(Object::Handle(library.GetMetadata(function))); 495 Array::Cast(Object::Handle(library.GetMetadata(function)));
506 496
507 if (metadata.Length() > 0) { 497 if (metadata.Length() > 0) {
508 Object& val = Object::Handle(); 498 Object& val = Object::Handle();
509 for (intptr_t i = 0; i < metadata.Length(); i++) { 499 for (intptr_t i = 0; i < metadata.Length(); i++) {
510 val = metadata.At(i); 500 val = metadata.At(i);
511 if (val.IsString() && String::Cast(val).Equals(annotation)) { 501 if (val.IsString() && String::Cast(val).Equals(annotation)) {
512 return true; 502 return true;
513 } 503 }
514 } 504 }
515 } 505 }
516 return false; 506 return false;
517 } 507 }
518 508
519
520 static void ReplaceParameterStubs(Zone* zone, 509 static void ReplaceParameterStubs(Zone* zone,
521 FlowGraph* caller_graph, 510 FlowGraph* caller_graph,
522 InlinedCallData* call_data, 511 InlinedCallData* call_data,
523 const TargetInfo* target_info) { 512 const TargetInfo* target_info) {
524 CSTAT_TIMER_SCOPE(Thread::Current(), graphinliner_subst_timer); 513 CSTAT_TIMER_SCOPE(Thread::Current(), graphinliner_subst_timer);
525 const bool is_polymorphic = call_data->call->IsPolymorphicInstanceCall(); 514 const bool is_polymorphic = call_data->call->IsPolymorphicInstanceCall();
526 ASSERT(is_polymorphic == (target_info != NULL)); 515 ASSERT(is_polymorphic == (target_info != NULL));
527 FlowGraph* callee_graph = call_data->callee_graph; 516 FlowGraph* callee_graph = call_data->callee_graph;
528 TargetEntryInstr* callee_entry = callee_graph->graph_entry()->normal_entry(); 517 TargetEntryInstr* callee_entry = callee_graph->graph_entry()->normal_entry();
529 518
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 } 588 }
600 param->ReplaceUsesWith(type_args); 589 param->ReplaceUsesWith(type_args);
601 } 590 }
602 } 591 }
603 } 592 }
604 593
605 // Check that inlining maintains use lists. 594 // Check that inlining maintains use lists.
606 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph->VerifyUseLists()); 595 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph->VerifyUseLists());
607 } 596 }
608 597
609
610 class CallSiteInliner : public ValueObject { 598 class CallSiteInliner : public ValueObject {
611 public: 599 public:
612 explicit CallSiteInliner(FlowGraphInliner* inliner, intptr_t threshold) 600 explicit CallSiteInliner(FlowGraphInliner* inliner, intptr_t threshold)
613 : inliner_(inliner), 601 : inliner_(inliner),
614 caller_graph_(inliner->flow_graph()), 602 caller_graph_(inliner->flow_graph()),
615 inlined_(false), 603 inlined_(false),
616 initial_size_(inliner->flow_graph()->InstructionCount()), 604 initial_size_(inliner->flow_graph()->InstructionCount()),
617 inlined_size_(0), 605 inlined_size_(0),
618 inlined_recursive_call_(false), 606 inlined_recursive_call_(false),
619 inlining_depth_(1), 607 inlining_depth_(1),
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 CSTAT_TIMER_SCOPE(thread(), graphinliner_parse_timer); 864 CSTAT_TIMER_SCOPE(thread(), graphinliner_parse_timer);
877 parsed_function = GetParsedFunction(function, &in_cache); 865 parsed_function = GetParsedFunction(function, &in_cache);
878 if (!function.CanBeInlined()) { 866 if (!function.CanBeInlined()) {
879 // As a side effect of parsing the function, it may be marked 867 // As a side effect of parsing the function, it may be marked
880 // as not inlinable. This happens for async and async* functions 868 // as not inlinable. This happens for async and async* functions
881 // when causal stack traces are being tracked. 869 // when causal stack traces are being tracked.
882 return false; 870 return false;
883 } 871 }
884 } 872 }
885 873
886
887 // Build the callee graph. 874 // Build the callee graph.
888 InlineExitCollector* exit_collector = 875 InlineExitCollector* exit_collector =
889 new (Z) InlineExitCollector(caller_graph_, call); 876 new (Z) InlineExitCollector(caller_graph_, call);
890 FlowGraph* callee_graph; 877 FlowGraph* callee_graph;
891 if (UseKernelFrontEndFor(parsed_function)) { 878 if (UseKernelFrontEndFor(parsed_function)) {
892 kernel::FlowGraphBuilder builder( 879 kernel::FlowGraphBuilder builder(
893 parsed_function->function().kernel_offset(), parsed_function, 880 parsed_function->function().kernel_offset(), parsed_function,
894 *ic_data_array, /* not building var desc */ NULL, exit_collector, 881 *ic_data_array, /* not building var desc */ NULL, exit_collector,
895 Compiler::kNoOSRDeoptId, caller_graph_->max_block_id() + 1); 882 Compiler::kNoOSRDeoptId, caller_graph_->max_block_id() + 1);
896 { 883 {
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after
1478 intptr_t inlining_recursion_depth_; 1465 intptr_t inlining_recursion_depth_;
1479 intptr_t inlining_depth_threshold_; 1466 intptr_t inlining_depth_threshold_;
1480 CallSites* collected_call_sites_; 1467 CallSites* collected_call_sites_;
1481 CallSites* inlining_call_sites_; 1468 CallSites* inlining_call_sites_;
1482 GrowableArray<ParsedFunction*> function_cache_; 1469 GrowableArray<ParsedFunction*> function_cache_;
1483 GrowableArray<InlinedInfo> inlined_info_; 1470 GrowableArray<InlinedInfo> inlined_info_;
1484 1471
1485 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); 1472 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner);
1486 }; 1473 };
1487 1474
1488
1489 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner, 1475 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner,
1490 PolymorphicInstanceCallInstr* call, 1476 PolymorphicInstanceCallInstr* call,
1491 const Function& caller_function, 1477 const Function& caller_function,
1492 intptr_t caller_inlining_id) 1478 intptr_t caller_inlining_id)
1493 : owner_(owner), 1479 : owner_(owner),
1494 call_(call), 1480 call_(call),
1495 num_variants_(call->NumberOfChecks()), 1481 num_variants_(call->NumberOfChecks()),
1496 variants_(call->targets_), 1482 variants_(call->targets_),
1497 inlined_variants_(zone()), 1483 inlined_variants_(zone()),
1498 non_inlined_variants_(new (zone()) CallTargets(zone())), 1484 non_inlined_variants_(new (zone()) CallTargets(zone())),
1499 inlined_entries_(num_variants_), 1485 inlined_entries_(num_variants_),
1500 exit_collector_(new (Z) InlineExitCollector(owner->caller_graph(), call)), 1486 exit_collector_(new (Z) InlineExitCollector(owner->caller_graph(), call)),
1501 caller_function_(caller_function), 1487 caller_function_(caller_function),
1502 caller_inlining_id_(caller_inlining_id) {} 1488 caller_inlining_id_(caller_inlining_id) {}
1503 1489
1504
1505 Isolate* PolymorphicInliner::isolate() const { 1490 Isolate* PolymorphicInliner::isolate() const {
1506 return owner_->caller_graph()->isolate(); 1491 return owner_->caller_graph()->isolate();
1507 } 1492 }
1508 1493
1509
1510 Zone* PolymorphicInliner::zone() const { 1494 Zone* PolymorphicInliner::zone() const {
1511 return owner_->caller_graph()->zone(); 1495 return owner_->caller_graph()->zone();
1512 } 1496 }
1513 1497
1514
1515 intptr_t PolymorphicInliner::AllocateBlockId() const { 1498 intptr_t PolymorphicInliner::AllocateBlockId() const {
1516 return owner_->caller_graph()->allocate_block_id(); 1499 return owner_->caller_graph()->allocate_block_id();
1517 } 1500 }
1518 1501
1519
1520 // Inlined bodies are shared if two different class ids have the same 1502 // Inlined bodies are shared if two different class ids have the same
1521 // inlined target. This sharing is represented by using three different 1503 // inlined target. This sharing is represented by using three different
1522 // types of entries in the inlined_entries_ array: 1504 // types of entries in the inlined_entries_ array:
1523 // 1505 //
1524 // * GraphEntry: the inlined body is not shared. 1506 // * GraphEntry: the inlined body is not shared.
1525 // 1507 //
1526 // * TargetEntry: the inlined body is shared and this is the first variant. 1508 // * TargetEntry: the inlined body is shared and this is the first variant.
1527 // 1509 //
1528 // * JoinEntry: the inlined body is shared and this is a subsequent variant. 1510 // * JoinEntry: the inlined body is shared and this is a subsequent variant.
1529 bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) { 1511 bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1570 inlined_entries_[i]->last_instruction()->SuccessorAt(0); 1552 inlined_entries_[i]->last_instruction()->SuccessorAt(0);
1571 ASSERT(join->IsJoinEntry()); 1553 ASSERT(join->IsJoinEntry());
1572 inlined_entries_.Add(join); 1554 inlined_entries_.Add(join);
1573 return true; 1555 return true;
1574 } 1556 }
1575 } 1557 }
1576 1558
1577 return false; 1559 return false;
1578 } 1560 }
1579 1561
1580
1581 bool PolymorphicInliner::CheckNonInlinedDuplicate(const Function& target) { 1562 bool PolymorphicInliner::CheckNonInlinedDuplicate(const Function& target) {
1582 for (intptr_t i = 0; i < non_inlined_variants_->length(); ++i) { 1563 for (intptr_t i = 0; i < non_inlined_variants_->length(); ++i) {
1583 if (target.raw() == non_inlined_variants_->TargetAt(i)->target->raw()) { 1564 if (target.raw() == non_inlined_variants_->TargetAt(i)->target->raw()) {
1584 return true; 1565 return true;
1585 } 1566 }
1586 } 1567 }
1587 1568
1588 return false; 1569 return false;
1589 } 1570 }
1590 1571
1591
1592 bool PolymorphicInliner::TryInliningPoly(const TargetInfo& target_info) { 1572 bool PolymorphicInliner::TryInliningPoly(const TargetInfo& target_info) {
1593 if ((!FLAG_precompiled_mode || 1573 if ((!FLAG_precompiled_mode ||
1594 owner_->inliner_->use_speculative_inlining()) && 1574 owner_->inliner_->use_speculative_inlining()) &&
1595 target_info.IsSingleCid() && 1575 target_info.IsSingleCid() &&
1596 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) { 1576 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) {
1597 owner_->inlined_ = true; 1577 owner_->inlined_ = true;
1598 return true; 1578 return true;
1599 } 1579 }
1600 1580
1601 GrowableArray<Value*> arguments(call_->ArgumentCount()); 1581 GrowableArray<Value*> arguments(call_->ArgumentCount());
(...skipping 11 matching lines...) Expand all
1613 FlowGraph* callee_graph = call_data.callee_graph; 1593 FlowGraph* callee_graph = call_data.callee_graph;
1614 call_data.exit_collector->PrepareGraphs(callee_graph); 1594 call_data.exit_collector->PrepareGraphs(callee_graph);
1615 inlined_entries_.Add(callee_graph->graph_entry()); 1595 inlined_entries_.Add(callee_graph->graph_entry());
1616 exit_collector_->Union(call_data.exit_collector); 1596 exit_collector_->Union(call_data.exit_collector);
1617 1597
1618 ReplaceParameterStubs(zone(), owner_->caller_graph(), &call_data, 1598 ReplaceParameterStubs(zone(), owner_->caller_graph(), &call_data,
1619 &target_info); 1599 &target_info);
1620 return true; 1600 return true;
1621 } 1601 }
1622 1602
1623
1624 static Instruction* AppendInstruction(Instruction* first, Instruction* second) { 1603 static Instruction* AppendInstruction(Instruction* first, Instruction* second) {
1625 for (intptr_t i = second->InputCount() - 1; i >= 0; --i) { 1604 for (intptr_t i = second->InputCount() - 1; i >= 0; --i) {
1626 Value* input = second->InputAt(i); 1605 Value* input = second->InputAt(i);
1627 input->definition()->AddInputUse(input); 1606 input->definition()->AddInputUse(input);
1628 } 1607 }
1629 first->LinkTo(second); 1608 first->LinkTo(second);
1630 return second; 1609 return second;
1631 } 1610 }
1632 1611
1633
1634 bool PolymorphicInliner::TryInlineRecognizedMethod(intptr_t receiver_cid, 1612 bool PolymorphicInliner::TryInlineRecognizedMethod(intptr_t receiver_cid,
1635 const Function& target) { 1613 const Function& target) {
1636 TargetEntryInstr* entry; 1614 TargetEntryInstr* entry;
1637 Definition* last; 1615 Definition* last;
1638 // Replace the receiver argument with a redefinition to prevent code from 1616 // Replace the receiver argument with a redefinition to prevent code from
1639 // the inlined body from being hoisted above the inlined entry. 1617 // the inlined body from being hoisted above the inlined entry.
1640 GrowableArray<Definition*> arguments(call_->ArgumentCount()); 1618 GrowableArray<Definition*> arguments(call_->ArgumentCount());
1641 Definition* receiver = call_->ArgumentAt(0); 1619 Definition* receiver = call_->ArgumentAt(0);
1642 RedefinitionInstr* redefinition = 1620 RedefinitionInstr* redefinition =
1643 new (Z) RedefinitionInstr(new (Z) Value(receiver)); 1621 new (Z) RedefinitionInstr(new (Z) Value(receiver));
(...skipping 22 matching lines...) Expand all
1666 GraphEntryInstr* graph_entry = new (Z) 1644 GraphEntryInstr* graph_entry = new (Z)
1667 GraphEntryInstr(*temp_parsed_function, entry, Compiler::kNoOSRDeoptId); 1645 GraphEntryInstr(*temp_parsed_function, entry, Compiler::kNoOSRDeoptId);
1668 // Update polymorphic inliner state. 1646 // Update polymorphic inliner state.
1669 inlined_entries_.Add(graph_entry); 1647 inlined_entries_.Add(graph_entry);
1670 exit_collector_->Union(exit_collector); 1648 exit_collector_->Union(exit_collector);
1671 return true; 1649 return true;
1672 } 1650 }
1673 return false; 1651 return false;
1674 } 1652 }
1675 1653
1676
1677 // Build a DAG to dispatch to the inlined function bodies. Load the class 1654 // Build a DAG to dispatch to the inlined function bodies. Load the class
1678 // id of the receiver and make explicit comparisons for each inlined body, 1655 // id of the receiver and make explicit comparisons for each inlined body,
1679 // in frequency order. If all variants are inlined, the entry to the last 1656 // in frequency order. If all variants are inlined, the entry to the last
1680 // inlined body is guarded by a CheckClassId instruction which can deopt. 1657 // inlined body is guarded by a CheckClassId instruction which can deopt.
1681 // If not all variants are inlined, we add a PolymorphicInstanceCall 1658 // If not all variants are inlined, we add a PolymorphicInstanceCall
1682 // instruction to handle the non-inlined variants. 1659 // instruction to handle the non-inlined variants.
1683 TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() { 1660 TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
1684 const intptr_t try_idx = call_->GetBlock()->try_index(); 1661 const intptr_t try_idx = call_->GetBlock()->try_index();
1685 1662
1686 // Start with a fresh target entry. 1663 // Start with a fresh target entry.
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
1912 // Remove push arguments of the call. 1889 // Remove push arguments of the call.
1913 for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) { 1890 for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) {
1914 PushArgumentInstr* push = call_->PushArgumentAt(i); 1891 PushArgumentInstr* push = call_->PushArgumentAt(i);
1915 push->ReplaceUsesWith(push->value()->definition()); 1892 push->ReplaceUsesWith(push->value()->definition());
1916 push->RemoveFromGraph(); 1893 push->RemoveFromGraph();
1917 } 1894 }
1918 } 1895 }
1919 return entry; 1896 return entry;
1920 } 1897 }
1921 1898
1922
1923 static void TracePolyInlining(const CallTargets& targets, 1899 static void TracePolyInlining(const CallTargets& targets,
1924 intptr_t idx, 1900 intptr_t idx,
1925 intptr_t total, 1901 intptr_t total,
1926 const char* message) { 1902 const char* message) {
1927 String& name = 1903 String& name =
1928 String::Handle(targets.TargetAt(idx)->target->QualifiedUserVisibleName()); 1904 String::Handle(targets.TargetAt(idx)->target->QualifiedUserVisibleName());
1929 int percent = total == 0 ? 0 : (100 * targets.TargetAt(idx)->count) / total; 1905 int percent = total == 0 ? 0 : (100 * targets.TargetAt(idx)->count) / total;
1930 THR_Print("%s cid %" Pd "-%" Pd ": %" Pd "/%" Pd " %d%% %s\n", 1906 THR_Print("%s cid %" Pd "-%" Pd ": %" Pd "/%" Pd " %d%% %s\n",
1931 name.ToCString(), targets[idx].cid_start, targets[idx].cid_end, 1907 name.ToCString(), targets[idx].cid_start, targets[idx].cid_end,
1932 targets.TargetAt(idx)->count, total, percent, message); 1908 targets.TargetAt(idx)->count, total, percent, message);
1933 } 1909 }
1934 1910
1935
1936 bool PolymorphicInliner::trace_inlining() const { 1911 bool PolymorphicInliner::trace_inlining() const {
1937 return owner_->trace_inlining(); 1912 return owner_->trace_inlining();
1938 } 1913 }
1939 1914
1940
1941 void PolymorphicInliner::Inline() { 1915 void PolymorphicInliner::Inline() {
1942 ASSERT(&variants_ == &call_->targets_); 1916 ASSERT(&variants_ == &call_->targets_);
1943 1917
1944 intptr_t total = call_->total_call_count(); 1918 intptr_t total = call_->total_call_count();
1945 for (intptr_t var_idx = 0; var_idx < variants_.length(); ++var_idx) { 1919 for (intptr_t var_idx = 0; var_idx < variants_.length(); ++var_idx) {
1946 TargetInfo* info = variants_.TargetAt(var_idx); 1920 TargetInfo* info = variants_.TargetAt(var_idx);
1947 if (variants_.length() > FLAG_max_polymorphic_checks) { 1921 if (variants_.length() > FLAG_max_polymorphic_checks) {
1948 non_inlined_variants_->Add(info); 1922 non_inlined_variants_->Add(info);
1949 continue; 1923 continue;
1950 } 1924 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2012 1986
2013 // If there are no inlined variants, leave the call in place. 1987 // If there are no inlined variants, leave the call in place.
2014 if (inlined_variants_.is_empty()) return; 1988 if (inlined_variants_.is_empty()) return;
2015 1989
2016 // Now build a decision tree (a DAG because of shared inline variants) and 1990 // Now build a decision tree (a DAG because of shared inline variants) and
2017 // inline it at the call site. 1991 // inline it at the call site.
2018 TargetEntryInstr* entry = BuildDecisionGraph(); 1992 TargetEntryInstr* entry = BuildDecisionGraph();
2019 exit_collector_->ReplaceCall(entry); 1993 exit_collector_->ReplaceCall(entry);
2020 } 1994 }
2021 1995
2022
2023 static uint16_t ClampUint16(intptr_t v) { 1996 static uint16_t ClampUint16(intptr_t v) {
2024 return (v > 0xFFFF) ? 0xFFFF : static_cast<uint16_t>(v); 1997 return (v > 0xFFFF) ? 0xFFFF : static_cast<uint16_t>(v);
2025 } 1998 }
2026 1999
2027
2028 static bool ShouldTraceInlining(FlowGraph* flow_graph) { 2000 static bool ShouldTraceInlining(FlowGraph* flow_graph) {
2029 const Function& top = flow_graph->parsed_function().function(); 2001 const Function& top = flow_graph->parsed_function().function();
2030 return FLAG_trace_inlining && FlowGraphPrinter::ShouldPrint(top); 2002 return FLAG_trace_inlining && FlowGraphPrinter::ShouldPrint(top);
2031 } 2003 }
2032 2004
2033
2034 FlowGraphInliner::FlowGraphInliner( 2005 FlowGraphInliner::FlowGraphInliner(
2035 FlowGraph* flow_graph, 2006 FlowGraph* flow_graph,
2036 GrowableArray<const Function*>* inline_id_to_function, 2007 GrowableArray<const Function*>* inline_id_to_function,
2037 GrowableArray<TokenPosition>* inline_id_to_token_pos, 2008 GrowableArray<TokenPosition>* inline_id_to_token_pos,
2038 GrowableArray<intptr_t>* caller_inline_id, 2009 GrowableArray<intptr_t>* caller_inline_id,
2039 bool use_speculative_inlining, 2010 bool use_speculative_inlining,
2040 GrowableArray<intptr_t>* inlining_black_list, 2011 GrowableArray<intptr_t>* inlining_black_list,
2041 Precompiler* precompiler) 2012 Precompiler* precompiler)
2042 : flow_graph_(flow_graph), 2013 : flow_graph_(flow_graph),
2043 inline_id_to_function_(inline_id_to_function), 2014 inline_id_to_function_(inline_id_to_function),
2044 inline_id_to_token_pos_(inline_id_to_token_pos), 2015 inline_id_to_token_pos_(inline_id_to_token_pos),
2045 caller_inline_id_(caller_inline_id), 2016 caller_inline_id_(caller_inline_id),
2046 trace_inlining_(ShouldTraceInlining(flow_graph)), 2017 trace_inlining_(ShouldTraceInlining(flow_graph)),
2047 use_speculative_inlining_(use_speculative_inlining), 2018 use_speculative_inlining_(use_speculative_inlining),
2048 inlining_black_list_(inlining_black_list), 2019 inlining_black_list_(inlining_black_list),
2049 precompiler_(precompiler) { 2020 precompiler_(precompiler) {
2050 ASSERT(!use_speculative_inlining || (inlining_black_list != NULL)); 2021 ASSERT(!use_speculative_inlining || (inlining_black_list != NULL));
2051 } 2022 }
2052 2023
2053
2054 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph, bool force) { 2024 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph, bool force) {
2055 const Function& function = flow_graph->function(); 2025 const Function& function = flow_graph->function();
2056 if (force || (function.optimized_instruction_count() == 0)) { 2026 if (force || (function.optimized_instruction_count() == 0)) {
2057 GraphInfoCollector info; 2027 GraphInfoCollector info;
2058 info.Collect(*flow_graph); 2028 info.Collect(*flow_graph);
2059 2029
2060 function.set_optimized_instruction_count( 2030 function.set_optimized_instruction_count(
2061 ClampUint16(info.instruction_count())); 2031 ClampUint16(info.instruction_count()));
2062 function.set_optimized_call_site_count(ClampUint16(info.call_site_count())); 2032 function.set_optimized_call_site_count(ClampUint16(info.call_site_count()));
2063 } 2033 }
2064 } 2034 }
2065 2035
2066
2067 // TODO(srdjan): This is only needed when disassembling and/or profiling. 2036 // TODO(srdjan): This is only needed when disassembling and/or profiling.
2068 // Sets inlining id for all instructions of this flow-graph, as well for the 2037 // Sets inlining id for all instructions of this flow-graph, as well for the
2069 // FlowGraph itself. 2038 // FlowGraph itself.
2070 void FlowGraphInliner::SetInliningId(FlowGraph* flow_graph, 2039 void FlowGraphInliner::SetInliningId(FlowGraph* flow_graph,
2071 intptr_t inlining_id) { 2040 intptr_t inlining_id) {
2072 ASSERT(flow_graph->inlining_id() < 0); 2041 ASSERT(flow_graph->inlining_id() < 0);
2073 flow_graph->set_inlining_id(inlining_id); 2042 flow_graph->set_inlining_id(inlining_id);
2074 for (BlockIterator block_it = flow_graph->postorder_iterator(); 2043 for (BlockIterator block_it = flow_graph->postorder_iterator();
2075 !block_it.Done(); block_it.Advance()) { 2044 !block_it.Done(); block_it.Advance()) {
2076 for (ForwardInstructionIterator it(block_it.Current()); !it.Done(); 2045 for (ForwardInstructionIterator it(block_it.Current()); !it.Done();
2077 it.Advance()) { 2046 it.Advance()) {
2078 Instruction* current = it.Current(); 2047 Instruction* current = it.Current();
2079 // Do not overwrite owner function. 2048 // Do not overwrite owner function.
2080 ASSERT(!current->has_inlining_id()); 2049 ASSERT(!current->has_inlining_id());
2081 current->set_inlining_id(inlining_id); 2050 current->set_inlining_id(inlining_id);
2082 } 2051 }
2083 } 2052 }
2084 } 2053 }
2085 2054
2086
2087 // Use function name to determine if inlineable operator. 2055 // Use function name to determine if inlineable operator.
2088 // Add names as necessary. 2056 // Add names as necessary.
2089 static bool IsInlineableOperator(const Function& function) { 2057 static bool IsInlineableOperator(const Function& function) {
2090 return (function.name() == Symbols::IndexToken().raw()) || 2058 return (function.name() == Symbols::IndexToken().raw()) ||
2091 (function.name() == Symbols::AssignIndexToken().raw()) || 2059 (function.name() == Symbols::AssignIndexToken().raw()) ||
2092 (function.name() == Symbols::Plus().raw()) || 2060 (function.name() == Symbols::Plus().raw()) ||
2093 (function.name() == Symbols::Minus().raw()); 2061 (function.name() == Symbols::Minus().raw());
2094 } 2062 }
2095 2063
2096
2097 bool FlowGraphInliner::AlwaysInline(const Function& function) { 2064 bool FlowGraphInliner::AlwaysInline(const Function& function) {
2098 const char* kAlwaysInlineAnnotation = "AlwaysInline"; 2065 const char* kAlwaysInlineAnnotation = "AlwaysInline";
2099 if (FLAG_enable_inlining_annotations && 2066 if (FLAG_enable_inlining_annotations &&
2100 HasAnnotation(function, kAlwaysInlineAnnotation)) { 2067 HasAnnotation(function, kAlwaysInlineAnnotation)) {
2101 TRACE_INLINING( 2068 TRACE_INLINING(
2102 THR_Print("AlwaysInline annotation for %s\n", function.ToCString())); 2069 THR_Print("AlwaysInline annotation for %s\n", function.ToCString()));
2103 return true; 2070 return true;
2104 } 2071 }
2105 2072
2106 if (function.IsDispatcherOrImplicitAccessor()) { 2073 if (function.IsDispatcherOrImplicitAccessor()) {
(...skipping 10 matching lines...) Expand all
2117 IsInlineableOperator(function) || 2084 IsInlineableOperator(function) ||
2118 (function.kind() == RawFunction::kConstructor)) { 2085 (function.kind() == RawFunction::kConstructor)) {
2119 const intptr_t count = function.optimized_instruction_count(); 2086 const intptr_t count = function.optimized_instruction_count();
2120 if ((count != 0) && (count < FLAG_inline_getters_setters_smaller_than)) { 2087 if ((count != 0) && (count < FLAG_inline_getters_setters_smaller_than)) {
2121 return true; 2088 return true;
2122 } 2089 }
2123 } 2090 }
2124 return MethodRecognizer::AlwaysInline(function); 2091 return MethodRecognizer::AlwaysInline(function);
2125 } 2092 }
2126 2093
2127
2128 void FlowGraphInliner::Inline() { 2094 void FlowGraphInliner::Inline() {
2129 // Collect graph info and store it on the function. 2095 // Collect graph info and store it on the function.
2130 // We might later use it for an early bailout from the inlining. 2096 // We might later use it for an early bailout from the inlining.
2131 CollectGraphInfo(flow_graph_); 2097 CollectGraphInfo(flow_graph_);
2132 2098
2133 const Function& top = flow_graph_->function(); 2099 const Function& top = flow_graph_->function();
2134 if ((FLAG_inlining_filter != NULL) && 2100 if ((FLAG_inlining_filter != NULL) &&
2135 (strstr(top.ToFullyQualifiedCString(), FLAG_inlining_filter) == NULL)) { 2101 (strstr(top.ToFullyQualifiedCString(), FLAG_inlining_filter) == NULL)) {
2136 return; 2102 return;
2137 } 2103 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { 2135 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
2170 THR_Print("After Inlining of %s\n", 2136 THR_Print("After Inlining of %s\n",
2171 flow_graph_->function().ToFullyQualifiedCString()); 2137 flow_graph_->function().ToFullyQualifiedCString());
2172 FlowGraphPrinter printer(*flow_graph_); 2138 FlowGraphPrinter printer(*flow_graph_);
2173 printer.PrintBlocks(); 2139 printer.PrintBlocks();
2174 } 2140 }
2175 } 2141 }
2176 } 2142 }
2177 } 2143 }
2178 2144
2179
2180 intptr_t FlowGraphInliner::NextInlineId(const Function& function, 2145 intptr_t FlowGraphInliner::NextInlineId(const Function& function,
2181 TokenPosition tp, 2146 TokenPosition tp,
2182 intptr_t parent_id) { 2147 intptr_t parent_id) {
2183 const intptr_t id = inline_id_to_function_->length(); 2148 const intptr_t id = inline_id_to_function_->length();
2184 // TODO(johnmccutchan): Do not allow IsNoSource once all nodes have proper 2149 // TODO(johnmccutchan): Do not allow IsNoSource once all nodes have proper
2185 // source positions. 2150 // source positions.
2186 ASSERT(tp.IsReal() || tp.IsSynthetic() || tp.IsNoSource()); 2151 ASSERT(tp.IsReal() || tp.IsSynthetic() || tp.IsNoSource());
2187 inline_id_to_function_->Add(&function); 2152 inline_id_to_function_->Add(&function);
2188 inline_id_to_token_pos_->Add(tp); 2153 inline_id_to_token_pos_->Add(tp);
2189 caller_inline_id_->Add(parent_id); 2154 caller_inline_id_->Add(parent_id);
2190 // We always have one less token position than functions. 2155 // We always have one less token position than functions.
2191 ASSERT(inline_id_to_token_pos_->length() == 2156 ASSERT(inline_id_to_token_pos_->length() ==
2192 (inline_id_to_function_->length() - 1)); 2157 (inline_id_to_function_->length() - 1));
2193 return id; 2158 return id;
2194 } 2159 }
2195 2160
2196
2197 static bool ShouldInlineSimd() { 2161 static bool ShouldInlineSimd() {
2198 return FlowGraphCompiler::SupportsUnboxedSimd128(); 2162 return FlowGraphCompiler::SupportsUnboxedSimd128();
2199 } 2163 }
2200 2164
2201
2202 static bool CanUnboxDouble() { 2165 static bool CanUnboxDouble() {
2203 return FlowGraphCompiler::SupportsUnboxedDoubles(); 2166 return FlowGraphCompiler::SupportsUnboxedDoubles();
2204 } 2167 }
2205 2168
2206
2207 static bool ShouldInlineInt64ArrayOps() { 2169 static bool ShouldInlineInt64ArrayOps() {
2208 #if defined(TARGET_ARCH_X64) 2170 #if defined(TARGET_ARCH_X64)
2209 return true; 2171 return true;
2210 #else 2172 #else
2211 return false; 2173 return false;
2212 #endif 2174 #endif
2213 } 2175 }
2214 2176
2215
2216 static bool CanUnboxInt32() { 2177 static bool CanUnboxInt32() {
2217 // Int32/Uint32 can be unboxed if it fits into a smi or the platform 2178 // Int32/Uint32 can be unboxed if it fits into a smi or the platform
2218 // supports unboxed mints. 2179 // supports unboxed mints.
2219 return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints(); 2180 return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints();
2220 } 2181 }
2221 2182
2222
2223 // Quick access to the current one. 2183 // Quick access to the current one.
2224 #undef Z 2184 #undef Z
2225 #define Z (flow_graph->zone()) 2185 #define Z (flow_graph->zone())
2226 2186
2227 static intptr_t PrepareInlineIndexedOp(FlowGraph* flow_graph, 2187 static intptr_t PrepareInlineIndexedOp(FlowGraph* flow_graph,
2228 Instruction* call, 2188 Instruction* call,
2229 intptr_t array_cid, 2189 intptr_t array_cid,
2230 Definition** array, 2190 Definition** array,
2231 Definition* index, 2191 Definition* index,
2232 Instruction** cursor) { 2192 Instruction** cursor) {
(...skipping 26 matching lines...) Expand all
2259 array_cid = kArrayCid; 2219 array_cid = kArrayCid;
2260 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { 2220 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
2261 LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr( 2221 LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
2262 new (Z) Value(*array), ExternalTypedData::data_offset()); 2222 new (Z) Value(*array), ExternalTypedData::data_offset());
2263 *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue); 2223 *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
2264 *array = elements; 2224 *array = elements;
2265 } 2225 }
2266 return array_cid; 2226 return array_cid;
2267 } 2227 }
2268 2228
2269
2270 static bool InlineGetIndexed(FlowGraph* flow_graph, 2229 static bool InlineGetIndexed(FlowGraph* flow_graph,
2271 MethodRecognizer::Kind kind, 2230 MethodRecognizer::Kind kind,
2272 Instruction* call, 2231 Instruction* call,
2273 Definition* receiver, 2232 Definition* receiver,
2274 TargetEntryInstr** entry, 2233 TargetEntryInstr** entry,
2275 Definition** last) { 2234 Definition** last) {
2276 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); 2235 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
2277 2236
2278 Definition* array = receiver; 2237 Definition* array = receiver;
2279 Definition* index = call->ArgumentAt(1); 2238 Definition* index = call->ArgumentAt(1);
(...skipping 24 matching lines...) Expand all
2304 2263
2305 if (array_cid == kTypedDataFloat32ArrayCid) { 2264 if (array_cid == kTypedDataFloat32ArrayCid) {
2306 *last = new (Z) FloatToDoubleInstr(new (Z) Value(*last), deopt_id); 2265 *last = new (Z) FloatToDoubleInstr(new (Z) Value(*last), deopt_id);
2307 flow_graph->AppendTo(cursor, *last, 2266 flow_graph->AppendTo(cursor, *last,
2308 deopt_id != Thread::kNoDeoptId ? call->env() : NULL, 2267 deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
2309 FlowGraph::kValue); 2268 FlowGraph::kValue);
2310 } 2269 }
2311 return true; 2270 return true;
2312 } 2271 }
2313 2272
2314
2315 static bool InlineSetIndexed(FlowGraph* flow_graph, 2273 static bool InlineSetIndexed(FlowGraph* flow_graph,
2316 MethodRecognizer::Kind kind, 2274 MethodRecognizer::Kind kind,
2317 const Function& target, 2275 const Function& target,
2318 Instruction* call, 2276 Instruction* call,
2319 Definition* receiver, 2277 Definition* receiver,
2320 TokenPosition token_pos, 2278 TokenPosition token_pos,
2321 const Cids* value_check, 2279 const Cids* value_check,
2322 TargetEntryInstr** entry, 2280 TargetEntryInstr** entry,
2323 Definition** last) { 2281 Definition** last) {
2324 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); 2282 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2445 2403
2446 const intptr_t index_scale = Instance::ElementSizeFor(array_cid); 2404 const intptr_t index_scale = Instance::ElementSizeFor(array_cid);
2447 *last = new (Z) StoreIndexedInstr( 2405 *last = new (Z) StoreIndexedInstr(
2448 new (Z) Value(array), new (Z) Value(index), new (Z) Value(stored_value), 2406 new (Z) Value(array), new (Z) Value(index), new (Z) Value(stored_value),
2449 needs_store_barrier, index_scale, array_cid, kAlignedAccess, 2407 needs_store_barrier, index_scale, array_cid, kAlignedAccess,
2450 call->deopt_id(), call->token_pos()); 2408 call->deopt_id(), call->token_pos());
2451 flow_graph->AppendTo(cursor, *last, call->env(), FlowGraph::kEffect); 2409 flow_graph->AppendTo(cursor, *last, call->env(), FlowGraph::kEffect);
2452 return true; 2410 return true;
2453 } 2411 }
2454 2412
2455
2456 static bool InlineDoubleOp(FlowGraph* flow_graph, 2413 static bool InlineDoubleOp(FlowGraph* flow_graph,
2457 Token::Kind op_kind, 2414 Token::Kind op_kind,
2458 Instruction* call, 2415 Instruction* call,
2459 Definition* receiver, 2416 Definition* receiver,
2460 TargetEntryInstr** entry, 2417 TargetEntryInstr** entry,
2461 Definition** last) { 2418 Definition** last) {
2462 if (!CanUnboxDouble()) { 2419 if (!CanUnboxDouble()) {
2463 return false; 2420 return false;
2464 } 2421 }
2465 Definition* left = receiver; 2422 Definition* left = receiver;
2466 Definition* right = call->ArgumentAt(1); 2423 Definition* right = call->ArgumentAt(1);
2467 2424
2468 *entry = new (Z) 2425 *entry = new (Z)
2469 TargetEntryInstr(flow_graph->allocate_block_id(), 2426 TargetEntryInstr(flow_graph->allocate_block_id(),
2470 call->GetBlock()->try_index(), Thread::kNoDeoptId); 2427 call->GetBlock()->try_index(), Thread::kNoDeoptId);
2471 (*entry)->InheritDeoptTarget(Z, call); 2428 (*entry)->InheritDeoptTarget(Z, call);
2472 // Arguments are checked. No need for class check. 2429 // Arguments are checked. No need for class check.
2473 BinaryDoubleOpInstr* double_bin_op = new (Z) 2430 BinaryDoubleOpInstr* double_bin_op = new (Z)
2474 BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right), 2431 BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right),
2475 call->deopt_id(), call->token_pos()); 2432 call->deopt_id(), call->token_pos());
2476 flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); 2433 flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
2477 *last = double_bin_op; 2434 *last = double_bin_op;
2478 2435
2479 return true; 2436 return true;
2480 } 2437 }
2481 2438
2482
2483 static bool InlineDoubleTestOp(FlowGraph* flow_graph, 2439 static bool InlineDoubleTestOp(FlowGraph* flow_graph,
2484 Instruction* call, 2440 Instruction* call,
2485 Definition* receiver, 2441 Definition* receiver,
2486 MethodRecognizer::Kind kind, 2442 MethodRecognizer::Kind kind,
2487 TargetEntryInstr** entry, 2443 TargetEntryInstr** entry,
2488 Definition** last) { 2444 Definition** last) {
2489 if (!CanUnboxDouble()) { 2445 if (!CanUnboxDouble()) {
2490 return false; 2446 return false;
2491 } 2447 }
2492 2448
2493 *entry = new (Z) 2449 *entry = new (Z)
2494 TargetEntryInstr(flow_graph->allocate_block_id(), 2450 TargetEntryInstr(flow_graph->allocate_block_id(),
2495 call->GetBlock()->try_index(), Thread::kNoDeoptId); 2451 call->GetBlock()->try_index(), Thread::kNoDeoptId);
2496 (*entry)->InheritDeoptTarget(Z, call); 2452 (*entry)->InheritDeoptTarget(Z, call);
2497 // Arguments are checked. No need for class check. 2453 // Arguments are checked. No need for class check.
2498 2454
2499 DoubleTestOpInstr* double_test_op = new (Z) DoubleTestOpInstr( 2455 DoubleTestOpInstr* double_test_op = new (Z) DoubleTestOpInstr(
2500 kind, new (Z) Value(receiver), call->deopt_id(), call->token_pos()); 2456 kind, new (Z) Value(receiver), call->deopt_id(), call->token_pos());
2501 flow_graph->AppendTo(*entry, double_test_op, call->env(), FlowGraph::kValue); 2457 flow_graph->AppendTo(*entry, double_test_op, call->env(), FlowGraph::kValue);
2502 *last = double_test_op; 2458 *last = double_test_op;
2503 2459
2504 return true; 2460 return true;
2505 } 2461 }
2506 2462
2507
2508 static bool InlineSmiBitAndFromSmi(FlowGraph* flow_graph, 2463 static bool InlineSmiBitAndFromSmi(FlowGraph* flow_graph,
2509 Instruction* call, 2464 Instruction* call,
2510 Definition* receiver, 2465 Definition* receiver,
2511 TargetEntryInstr** entry, 2466 TargetEntryInstr** entry,
2512 Definition** last) { 2467 Definition** last) {
2513 Definition* left = receiver; 2468 Definition* left = receiver;
2514 Definition* right = call->ArgumentAt(1); 2469 Definition* right = call->ArgumentAt(1);
2515 2470
2516 *entry = new (Z) 2471 *entry = new (Z)
2517 TargetEntryInstr(flow_graph->allocate_block_id(), 2472 TargetEntryInstr(flow_graph->allocate_block_id(),
2518 call->GetBlock()->try_index(), Thread::kNoDeoptId); 2473 call->GetBlock()->try_index(), Thread::kNoDeoptId);
2519 (*entry)->InheritDeoptTarget(Z, call); 2474 (*entry)->InheritDeoptTarget(Z, call);
2520 // Right arguments is known to be smi: other._bitAndFromSmi(this); 2475 // Right arguments is known to be smi: other._bitAndFromSmi(this);
2521 BinarySmiOpInstr* smi_op = 2476 BinarySmiOpInstr* smi_op =
2522 new (Z) BinarySmiOpInstr(Token::kBIT_AND, new (Z) Value(left), 2477 new (Z) BinarySmiOpInstr(Token::kBIT_AND, new (Z) Value(left),
2523 new (Z) Value(right), call->deopt_id()); 2478 new (Z) Value(right), call->deopt_id());
2524 flow_graph->AppendTo(*entry, smi_op, call->env(), FlowGraph::kValue); 2479 flow_graph->AppendTo(*entry, smi_op, call->env(), FlowGraph::kValue);
2525 *last = smi_op; 2480 *last = smi_op;
2526 2481
2527 return true; 2482 return true;
2528 } 2483 }
2529 2484
2530
2531 static bool InlineGrowableArraySetter(FlowGraph* flow_graph, 2485 static bool InlineGrowableArraySetter(FlowGraph* flow_graph,
2532 intptr_t offset, 2486 intptr_t offset,
2533 StoreBarrierType store_barrier_type, 2487 StoreBarrierType store_barrier_type,
2534 Instruction* call, 2488 Instruction* call,
2535 Definition* receiver, 2489 Definition* receiver,
2536 TargetEntryInstr** entry, 2490 TargetEntryInstr** entry,
2537 Definition** last) { 2491 Definition** last) {
2538 Definition* array = receiver; 2492 Definition* array = receiver;
2539 Definition* value = call->ArgumentAt(1); 2493 Definition* value = call->ArgumentAt(1);
2540 2494
2541 *entry = new (Z) 2495 *entry = new (Z)
2542 TargetEntryInstr(flow_graph->allocate_block_id(), 2496 TargetEntryInstr(flow_graph->allocate_block_id(),
2543 call->GetBlock()->try_index(), Thread::kNoDeoptId); 2497 call->GetBlock()->try_index(), Thread::kNoDeoptId);
2544 (*entry)->InheritDeoptTarget(Z, call); 2498 (*entry)->InheritDeoptTarget(Z, call);
2545 2499
2546 // This is an internal method, no need to check argument types. 2500 // This is an internal method, no need to check argument types.
2547 StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr( 2501 StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
2548 offset, new (Z) Value(array), new (Z) Value(value), store_barrier_type, 2502 offset, new (Z) Value(array), new (Z) Value(value), store_barrier_type,
2549 call->token_pos()); 2503 call->token_pos());
2550 flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect); 2504 flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect);
2551 *last = store; 2505 *last = store;
2552 2506
2553 return true; 2507 return true;
2554 } 2508 }
2555 2509
2556
2557 static void PrepareInlineByteArrayBaseOp(FlowGraph* flow_graph, 2510 static void PrepareInlineByteArrayBaseOp(FlowGraph* flow_graph,
2558 Instruction* call, 2511 Instruction* call,
2559 intptr_t array_cid, 2512 intptr_t array_cid,
2560 intptr_t view_cid, 2513 intptr_t view_cid,
2561 Definition** array, 2514 Definition** array,
2562 Definition* byte_index, 2515 Definition* byte_index,
2563 Instruction** cursor) { 2516 Instruction** cursor) {
2564 LoadFieldInstr* length = new (Z) LoadFieldInstr( 2517 LoadFieldInstr* length = new (Z) LoadFieldInstr(
2565 new (Z) Value(*array), CheckArrayBoundInstr::LengthOffsetFor(array_cid), 2518 new (Z) Value(*array), CheckArrayBoundInstr::LengthOffsetFor(array_cid),
2566 Type::ZoneHandle(Z, Type::SmiType()), call->token_pos()); 2519 Type::ZoneHandle(Z, Type::SmiType()), call->token_pos());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2607 call->env(), FlowGraph::kEffect); 2560 call->env(), FlowGraph::kEffect);
2608 2561
2609 if (RawObject::IsExternalTypedDataClassId(array_cid)) { 2562 if (RawObject::IsExternalTypedDataClassId(array_cid)) {
2610 LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr( 2563 LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
2611 new (Z) Value(*array), ExternalTypedData::data_offset()); 2564 new (Z) Value(*array), ExternalTypedData::data_offset());
2612 *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue); 2565 *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
2613 *array = elements; 2566 *array = elements;
2614 } 2567 }
2615 } 2568 }
2616 2569
2617
2618 static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph, 2570 static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph,
2619 Instruction* call, 2571 Instruction* call,
2620 Definition* receiver, 2572 Definition* receiver,
2621 intptr_t array_cid, 2573 intptr_t array_cid,
2622 intptr_t view_cid, 2574 intptr_t view_cid,
2623 TargetEntryInstr** entry, 2575 TargetEntryInstr** entry,
2624 Definition** last) { 2576 Definition** last) {
2625 ASSERT(array_cid != kIllegalCid); 2577 ASSERT(array_cid != kIllegalCid);
2626 Definition* array = receiver; 2578 Definition* array = receiver;
2627 Definition* index = call->ArgumentAt(1); 2579 Definition* index = call->ArgumentAt(1);
(...skipping 22 matching lines...) Expand all
2650 2602
2651 if (view_cid == kTypedDataFloat32ArrayCid) { 2603 if (view_cid == kTypedDataFloat32ArrayCid) {
2652 *last = new (Z) FloatToDoubleInstr(new (Z) Value(*last), deopt_id); 2604 *last = new (Z) FloatToDoubleInstr(new (Z) Value(*last), deopt_id);
2653 flow_graph->AppendTo(cursor, *last, 2605 flow_graph->AppendTo(cursor, *last,
2654 deopt_id != Thread::kNoDeoptId ? call->env() : NULL, 2606 deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
2655 FlowGraph::kValue); 2607 FlowGraph::kValue);
2656 } 2608 }
2657 return true; 2609 return true;
2658 } 2610 }
2659 2611
2660
2661 static bool InlineByteArrayBaseStore(FlowGraph* flow_graph, 2612 static bool InlineByteArrayBaseStore(FlowGraph* flow_graph,
2662 const Function& target, 2613 const Function& target,
2663 Instruction* call, 2614 Instruction* call,
2664 Definition* receiver, 2615 Definition* receiver,
2665 intptr_t array_cid, 2616 intptr_t array_cid,
2666 intptr_t view_cid, 2617 intptr_t view_cid,
2667 TargetEntryInstr** entry, 2618 TargetEntryInstr** entry,
2668 Definition** last) { 2619 Definition** last) {
2669 ASSERT(array_cid != kIllegalCid); 2620 ASSERT(array_cid != kIllegalCid);
2670 Definition* array = receiver; 2621 Definition* array = receiver;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
2763 1, // Index scale 2714 1, // Index scale
2764 view_cid, kUnalignedAccess, call->deopt_id(), call->token_pos()); 2715 view_cid, kUnalignedAccess, call->deopt_id(), call->token_pos());
2765 2716
2766 flow_graph->AppendTo( 2717 flow_graph->AppendTo(
2767 cursor, *last, 2718 cursor, *last,
2768 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, 2719 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
2769 FlowGraph::kEffect); 2720 FlowGraph::kEffect);
2770 return true; 2721 return true;
2771 } 2722 }
2772 2723
2773
2774 // Returns the LoadIndexedInstr. 2724 // Returns the LoadIndexedInstr.
2775 static Definition* PrepareInlineStringIndexOp(FlowGraph* flow_graph, 2725 static Definition* PrepareInlineStringIndexOp(FlowGraph* flow_graph,
2776 Instruction* call, 2726 Instruction* call,
2777 intptr_t cid, 2727 intptr_t cid,
2778 Definition* str, 2728 Definition* str,
2779 Definition* index, 2729 Definition* index,
2780 Instruction* cursor) { 2730 Instruction* cursor) {
2781 // Load the length of the string. 2731 // Load the length of the string.
2782 // Treat length loads as mutable (i.e. affected by side effects) to avoid 2732 // Treat length loads as mutable (i.e. affected by side effects) to avoid
2783 // hoisting them since we can't hoist the preceding class-check. This 2733 // hoisting them since we can't hoist the preceding class-check. This
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2816 2766
2817 LoadIndexedInstr* load_indexed = new (Z) LoadIndexedInstr( 2767 LoadIndexedInstr* load_indexed = new (Z) LoadIndexedInstr(
2818 new (Z) Value(str), new (Z) Value(index), Instance::ElementSizeFor(cid), 2768 new (Z) Value(str), new (Z) Value(index), Instance::ElementSizeFor(cid),
2819 cid, kAlignedAccess, Thread::kNoDeoptId, call->token_pos()); 2769 cid, kAlignedAccess, Thread::kNoDeoptId, call->token_pos());
2820 2770
2821 cursor = flow_graph->AppendTo(cursor, load_indexed, NULL, FlowGraph::kValue); 2771 cursor = flow_graph->AppendTo(cursor, load_indexed, NULL, FlowGraph::kValue);
2822 ASSERT(cursor == load_indexed); 2772 ASSERT(cursor == load_indexed);
2823 return load_indexed; 2773 return load_indexed;
2824 } 2774 }
2825 2775
2826
2827 static bool InlineStringBaseCharAt(FlowGraph* flow_graph, 2776 static bool InlineStringBaseCharAt(FlowGraph* flow_graph,
2828 Instruction* call, 2777 Instruction* call,
2829 Definition* receiver, 2778 Definition* receiver,
2830 intptr_t cid, 2779 intptr_t cid,
2831 TargetEntryInstr** entry, 2780 TargetEntryInstr** entry,
2832 Definition** last) { 2781 Definition** last) {
2833 if ((cid != kOneByteStringCid) && (cid != kExternalOneByteStringCid)) { 2782 if ((cid != kOneByteStringCid) && (cid != kExternalOneByteStringCid)) {
2834 return false; 2783 return false;
2835 } 2784 }
2836 Definition* str = receiver; 2785 Definition* str = receiver;
2837 Definition* index = call->ArgumentAt(1); 2786 Definition* index = call->ArgumentAt(1);
2838 2787
2839 *entry = new (Z) 2788 *entry = new (Z)
2840 TargetEntryInstr(flow_graph->allocate_block_id(), 2789 TargetEntryInstr(flow_graph->allocate_block_id(),
2841 call->GetBlock()->try_index(), Thread::kNoDeoptId); 2790 call->GetBlock()->try_index(), Thread::kNoDeoptId);
2842 (*entry)->InheritDeoptTarget(Z, call); 2791 (*entry)->InheritDeoptTarget(Z, call);
2843 2792
2844 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); 2793 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry);
2845 2794
2846 OneByteStringFromCharCodeInstr* char_at = 2795 OneByteStringFromCharCodeInstr* char_at =
2847 new (Z) OneByteStringFromCharCodeInstr(new (Z) Value(*last)); 2796 new (Z) OneByteStringFromCharCodeInstr(new (Z) Value(*last));
2848 2797
2849 flow_graph->AppendTo(*last, char_at, NULL, FlowGraph::kValue); 2798 flow_graph->AppendTo(*last, char_at, NULL, FlowGraph::kValue);
2850 *last = char_at; 2799 *last = char_at;
2851 2800
2852 return true; 2801 return true;
2853 } 2802 }
2854 2803
2855
2856 static bool InlineStringCodeUnitAt(FlowGraph* flow_graph, 2804 static bool InlineStringCodeUnitAt(FlowGraph* flow_graph,
2857 Instruction* call, 2805 Instruction* call,
2858 Definition* receiver, 2806 Definition* receiver,
2859 intptr_t cid, 2807 intptr_t cid,
2860 TargetEntryInstr** entry, 2808 TargetEntryInstr** entry,
2861 Definition** last) { 2809 Definition** last) {
2862 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || 2810 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) ||
2863 (cid == kExternalOneByteStringCid) || 2811 (cid == kExternalOneByteStringCid) ||
2864 (cid == kExternalTwoByteStringCid)); 2812 (cid == kExternalTwoByteStringCid));
2865 Definition* str = receiver; 2813 Definition* str = receiver;
2866 Definition* index = call->ArgumentAt(1); 2814 Definition* index = call->ArgumentAt(1);
2867 2815
2868 *entry = new (Z) 2816 *entry = new (Z)
2869 TargetEntryInstr(flow_graph->allocate_block_id(), 2817 TargetEntryInstr(flow_graph->allocate_block_id(),
2870 call->GetBlock()->try_index(), Thread::kNoDeoptId); 2818 call->GetBlock()->try_index(), Thread::kNoDeoptId);
2871 (*entry)->InheritDeoptTarget(Z, call); 2819 (*entry)->InheritDeoptTarget(Z, call);
2872 2820
2873 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); 2821 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry);
2874 2822
2875 return true; 2823 return true;
2876 } 2824 }
2877 2825
2878
2879 // Only used for monomorphic calls. 2826 // Only used for monomorphic calls.
2880 bool FlowGraphInliner::TryReplaceInstanceCallWithInline( 2827 bool FlowGraphInliner::TryReplaceInstanceCallWithInline(
2881 FlowGraph* flow_graph, 2828 FlowGraph* flow_graph,
2882 ForwardInstructionIterator* iterator, 2829 ForwardInstructionIterator* iterator,
2883 InstanceCallInstr* call) { 2830 InstanceCallInstr* call) {
2884 Function& target = Function::Handle(Z); 2831 Function& target = Function::Handle(Z);
2885 GrowableArray<intptr_t> class_ids; 2832 GrowableArray<intptr_t> class_ids;
2886 call->ic_data()->GetCheckAt(0, &class_ids, &target); 2833 call->ic_data()->GetCheckAt(0, &class_ids, &target);
2887 const intptr_t receiver_cid = class_ids[0]; 2834 const intptr_t receiver_cid = class_ids[0];
2888 2835
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2922 // Remove through the iterator. 2869 // Remove through the iterator.
2923 ASSERT(iterator->Current() == call); 2870 ASSERT(iterator->Current() == call);
2924 iterator->RemoveCurrentFromGraph(); 2871 iterator->RemoveCurrentFromGraph();
2925 call->set_previous(NULL); 2872 call->set_previous(NULL);
2926 call->set_next(NULL); 2873 call->set_next(NULL);
2927 return true; 2874 return true;
2928 } 2875 }
2929 return false; 2876 return false;
2930 } 2877 }
2931 2878
2932
2933 bool FlowGraphInliner::TryReplaceStaticCallWithInline( 2879 bool FlowGraphInliner::TryReplaceStaticCallWithInline(
2934 FlowGraph* flow_graph, 2880 FlowGraph* flow_graph,
2935 ForwardInstructionIterator* iterator, 2881 ForwardInstructionIterator* iterator,
2936 StaticCallInstr* call) { 2882 StaticCallInstr* call) {
2937 TargetEntryInstr* entry; 2883 TargetEntryInstr* entry;
2938 Definition* last; 2884 Definition* last;
2939 if (FlowGraphInliner::TryInlineRecognizedMethod( 2885 if (FlowGraphInliner::TryInlineRecognizedMethod(
2940 flow_graph, kIllegalCid, call->function(), call, NULL, 2886 flow_graph, kIllegalCid, call->function(), call, NULL,
2941 call->token_pos(), *call->ic_data(), &entry, &last)) { 2887 call->token_pos(), *call->ic_data(), &entry, &last)) {
2942 // Remove the original push arguments. 2888 // Remove the original push arguments.
(...skipping 18 matching lines...) Expand all
2961 // Remove through the iterator. 2907 // Remove through the iterator.
2962 ASSERT(iterator->Current() == call); 2908 ASSERT(iterator->Current() == call);
2963 iterator->RemoveCurrentFromGraph(); 2909 iterator->RemoveCurrentFromGraph();
2964 call->set_previous(NULL); 2910 call->set_previous(NULL);
2965 call->set_next(NULL); 2911 call->set_next(NULL);
2966 return true; 2912 return true;
2967 } 2913 }
2968 return false; 2914 return false;
2969 } 2915 }
2970 2916
2971
2972 static bool InlineFloat32x4Method(FlowGraph* flow_graph, 2917 static bool InlineFloat32x4Method(FlowGraph* flow_graph,
2973 Instruction* call, 2918 Instruction* call,
2974 Definition* receiver, 2919 Definition* receiver,
2975 MethodRecognizer::Kind kind, 2920 MethodRecognizer::Kind kind,
2976 TargetEntryInstr** entry, 2921 TargetEntryInstr** entry,
2977 Definition** last) { 2922 Definition** last) {
2978 if (!ShouldInlineSimd()) { 2923 if (!ShouldInlineSimd()) {
2979 return false; 2924 return false;
2980 } 2925 }
2981 2926
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
3067 UNREACHABLE(); 3012 UNREACHABLE();
3068 return false; 3013 return false;
3069 } 3014 }
3070 flow_graph->AppendTo( 3015 flow_graph->AppendTo(
3071 cursor, *last, 3016 cursor, *last,
3072 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, 3017 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
3073 FlowGraph::kValue); 3018 FlowGraph::kValue);
3074 return true; 3019 return true;
3075 } 3020 }
3076 3021
3077
3078 static bool CheckMask(Definition* definition, intptr_t* mask_ptr) { 3022 static bool CheckMask(Definition* definition, intptr_t* mask_ptr) {
3079 if (!definition->IsConstant()) return false; 3023 if (!definition->IsConstant()) return false;
3080 ConstantInstr* constant_instruction = definition->AsConstant(); 3024 ConstantInstr* constant_instruction = definition->AsConstant();
3081 const Object& constant_mask = constant_instruction->value(); 3025 const Object& constant_mask = constant_instruction->value();
3082 if (!constant_mask.IsSmi()) return false; 3026 if (!constant_mask.IsSmi()) return false;
3083 const intptr_t mask = Smi::Cast(constant_mask).Value(); 3027 const intptr_t mask = Smi::Cast(constant_mask).Value();
3084 if ((mask < 0) || (mask > 255)) { 3028 if ((mask < 0) || (mask > 255)) {
3085 return false; // Not a valid mask. 3029 return false; // Not a valid mask.
3086 } 3030 }
3087 *mask_ptr = mask; 3031 *mask_ptr = mask;
3088 return true; 3032 return true;
3089 } 3033 }
3090 3034
3091
3092 static bool InlineSimdShuffleMethod(FlowGraph* flow_graph, 3035 static bool InlineSimdShuffleMethod(FlowGraph* flow_graph,
3093 Instruction* call, 3036 Instruction* call,
3094 Definition* receiver, 3037 Definition* receiver,
3095 MethodRecognizer::Kind kind, 3038 MethodRecognizer::Kind kind,
3096 TargetEntryInstr** entry, 3039 TargetEntryInstr** entry,
3097 Definition** last) { 3040 Definition** last) {
3098 if (!ShouldInlineSimd()) { 3041 if (!ShouldInlineSimd()) {
3099 return false; 3042 return false;
3100 } 3043 }
3101 *entry = new (Z) 3044 *entry = new (Z)
3102 TargetEntryInstr(flow_graph->allocate_block_id(), 3045 TargetEntryInstr(flow_graph->allocate_block_id(),
3103 call->GetBlock()->try_index(), Thread::kNoDeoptId); 3046 call->GetBlock()->try_index(), Thread::kNoDeoptId);
3104 (*entry)->InheritDeoptTarget(Z, call); 3047 (*entry)->InheritDeoptTarget(Z, call);
3105 Instruction* cursor = *entry; 3048 Instruction* cursor = *entry;
3106 Definition* mask_definition = call->ArgumentAt(1); 3049 Definition* mask_definition = call->ArgumentAt(1);
3107 intptr_t mask = 0; 3050 intptr_t mask = 0;
3108 if (!CheckMask(mask_definition, &mask)) { 3051 if (!CheckMask(mask_definition, &mask)) {
3109 return false; 3052 return false;
3110 } 3053 }
3111 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(call->ArgumentAt(0)), 3054 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(call->ArgumentAt(0)),
3112 mask, call->deopt_id()); 3055 mask, call->deopt_id());
3113 flow_graph->AppendTo( 3056 flow_graph->AppendTo(
3114 cursor, *last, 3057 cursor, *last,
3115 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, 3058 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
3116 FlowGraph::kValue); 3059 FlowGraph::kValue);
3117 return true; 3060 return true;
3118 } 3061 }
3119 3062
3120
3121 static bool InlineSimdShuffleMixMethod(FlowGraph* flow_graph, 3063 static bool InlineSimdShuffleMixMethod(FlowGraph* flow_graph,
3122 Instruction* call, 3064 Instruction* call,
3123 Definition* receiver, 3065 Definition* receiver,
3124 MethodRecognizer::Kind kind, 3066 MethodRecognizer::Kind kind,
3125 TargetEntryInstr** entry, 3067 TargetEntryInstr** entry,
3126 Definition** last) { 3068 Definition** last) {
3127 if (!ShouldInlineSimd()) { 3069 if (!ShouldInlineSimd()) {
3128 return false; 3070 return false;
3129 } 3071 }
3130 *entry = new (Z) 3072 *entry = new (Z)
3131 TargetEntryInstr(flow_graph->allocate_block_id(), 3073 TargetEntryInstr(flow_graph->allocate_block_id(),
3132 call->GetBlock()->try_index(), Thread::kNoDeoptId); 3074 call->GetBlock()->try_index(), Thread::kNoDeoptId);
3133 (*entry)->InheritDeoptTarget(Z, call); 3075 (*entry)->InheritDeoptTarget(Z, call);
3134 Instruction* cursor = *entry; 3076 Instruction* cursor = *entry;
3135 Definition* mask_definition = call->ArgumentAt(2); 3077 Definition* mask_definition = call->ArgumentAt(2);
3136 intptr_t mask = 0; 3078 intptr_t mask = 0;
3137 if (!CheckMask(mask_definition, &mask)) { 3079 if (!CheckMask(mask_definition, &mask)) {
3138 return false; 3080 return false;
3139 } 3081 }
3140 *last = new (Z) Simd32x4ShuffleMixInstr(kind, new (Z) Value(receiver), 3082 *last = new (Z) Simd32x4ShuffleMixInstr(kind, new (Z) Value(receiver),
3141 new (Z) Value(call->ArgumentAt(1)), 3083 new (Z) Value(call->ArgumentAt(1)),
3142 mask, call->deopt_id()); 3084 mask, call->deopt_id());
3143 flow_graph->AppendTo( 3085 flow_graph->AppendTo(
3144 cursor, *last, 3086 cursor, *last,
3145 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, 3087 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
3146 FlowGraph::kValue); 3088 FlowGraph::kValue);
3147 return true; 3089 return true;
3148 } 3090 }
3149 3091
3150
3151 static bool InlineInt32x4Method(FlowGraph* flow_graph, 3092 static bool InlineInt32x4Method(FlowGraph* flow_graph,
3152 Instruction* call, 3093 Instruction* call,
3153 Definition* receiver, 3094 Definition* receiver,
3154 MethodRecognizer::Kind kind, 3095 MethodRecognizer::Kind kind,
3155 TargetEntryInstr** entry, 3096 TargetEntryInstr** entry,
3156 Definition** last) { 3097 Definition** last) {
3157 if (!ShouldInlineSimd()) { 3098 if (!ShouldInlineSimd()) {
3158 return false; 3099 return false;
3159 } 3100 }
3160 *entry = new (Z) 3101 *entry = new (Z)
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3197 default: 3138 default:
3198 return false; 3139 return false;
3199 } 3140 }
3200 flow_graph->AppendTo( 3141 flow_graph->AppendTo(
3201 cursor, *last, 3142 cursor, *last,
3202 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, 3143 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
3203 FlowGraph::kValue); 3144 FlowGraph::kValue);
3204 return true; 3145 return true;
3205 } 3146 }
3206 3147
3207
3208 static bool InlineFloat64x2Method(FlowGraph* flow_graph, 3148 static bool InlineFloat64x2Method(FlowGraph* flow_graph,
3209 Instruction* call, 3149 Instruction* call,
3210 Definition* receiver, 3150 Definition* receiver,
3211 MethodRecognizer::Kind kind, 3151 MethodRecognizer::Kind kind,
3212 TargetEntryInstr** entry, 3152 TargetEntryInstr** entry,
3213 Definition** last) { 3153 Definition** last) {
3214 if (!ShouldInlineSimd()) { 3154 if (!ShouldInlineSimd()) {
3215 return false; 3155 return false;
3216 } 3156 }
3217 *entry = new (Z) 3157 *entry = new (Z)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3250 UNREACHABLE(); 3190 UNREACHABLE();
3251 return false; 3191 return false;
3252 } 3192 }
3253 flow_graph->AppendTo( 3193 flow_graph->AppendTo(
3254 cursor, *last, 3194 cursor, *last,
3255 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, 3195 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
3256 FlowGraph::kValue); 3196 FlowGraph::kValue);
3257 return true; 3197 return true;
3258 } 3198 }
3259 3199
3260
3261 static bool InlineSimdConstructor(FlowGraph* flow_graph, 3200 static bool InlineSimdConstructor(FlowGraph* flow_graph,
3262 Instruction* call, 3201 Instruction* call,
3263 MethodRecognizer::Kind kind, 3202 MethodRecognizer::Kind kind,
3264 TargetEntryInstr** entry, 3203 TargetEntryInstr** entry,
3265 Definition** last) { 3204 Definition** last) {
3266 if (!ShouldInlineSimd()) { 3205 if (!ShouldInlineSimd()) {
3267 return false; 3206 return false;
3268 } 3207 }
3269 *entry = new (Z) 3208 *entry = new (Z)
3270 TargetEntryInstr(flow_graph->allocate_block_id(), 3209 TargetEntryInstr(flow_graph->allocate_block_id(),
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
3332 UNREACHABLE(); 3271 UNREACHABLE();
3333 return false; 3272 return false;
3334 } 3273 }
3335 flow_graph->AppendTo( 3274 flow_graph->AppendTo(
3336 cursor, *last, 3275 cursor, *last,
3337 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, 3276 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
3338 FlowGraph::kValue); 3277 FlowGraph::kValue);
3339 return true; 3278 return true;
3340 } 3279 }
3341 3280
3342
3343 static bool InlineMathCFunction(FlowGraph* flow_graph, 3281 static bool InlineMathCFunction(FlowGraph* flow_graph,
3344 Instruction* call, 3282 Instruction* call,
3345 MethodRecognizer::Kind kind, 3283 MethodRecognizer::Kind kind,
3346 TargetEntryInstr** entry, 3284 TargetEntryInstr** entry,
3347 Definition** last) { 3285 Definition** last) {
3348 if (!CanUnboxDouble()) { 3286 if (!CanUnboxDouble()) {
3349 return false; 3287 return false;
3350 } 3288 }
3351 *entry = new (Z) 3289 *entry = new (Z)
3352 TargetEntryInstr(flow_graph->allocate_block_id(), 3290 TargetEntryInstr(flow_graph->allocate_block_id(),
(...skipping 19 matching lines...) Expand all
3372 break; 3310 break;
3373 } 3311 }
3374 } 3312 }
3375 flow_graph->AppendTo( 3313 flow_graph->AppendTo(
3376 cursor, *last, 3314 cursor, *last,
3377 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, 3315 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
3378 FlowGraph::kValue); 3316 FlowGraph::kValue);
3379 return true; 3317 return true;
3380 } 3318 }
3381 3319
3382
3383 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph, 3320 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph,
3384 intptr_t receiver_cid, 3321 intptr_t receiver_cid,
3385 const Function& target, 3322 const Function& target,
3386 Definition* call, 3323 Definition* call,
3387 Definition* receiver, 3324 Definition* receiver,
3388 TokenPosition token_pos, 3325 TokenPosition token_pos,
3389 const ICData& ic_data, 3326 const ICData& ic_data,
3390 TargetEntryInstr** entry, 3327 TargetEntryInstr** entry,
3391 Definition** last) { 3328 Definition** last) {
3392 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target); 3329 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
3795 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, 3732 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
3796 FlowGraph::kEffect); 3733 FlowGraph::kEffect);
3797 return true; 3734 return true;
3798 } 3735 }
3799 3736
3800 default: 3737 default:
3801 return false; 3738 return false;
3802 } 3739 }
3803 } 3740 }
3804 3741
3805
3806 } // namespace dart 3742 } // namespace dart
3807 #endif // !defined(DART_PRECOMPILED_RUNTIME) 3743 #endif // !defined(DART_PRECOMPILED_RUNTIME)
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/flow_graph_range_analysis.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698