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

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

Issue 868913002: Add Zone-based handle allocation interface and reduce use of Isolate-based interfaces. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/flow_graph_optimizer.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 4
5 #include "vm/flow_graph_inliner.h" 5 #include "vm/flow_graph_inliner.h"
6 6
7 #include "vm/block_scheduler.h" 7 #include "vm/block_scheduler.h"
8 #include "vm/compiler.h" 8 #include "vm/compiler.h"
9 #include "vm/flags.h" 9 #include "vm/flags.h"
10 #include "vm/flow_graph.h" 10 #include "vm/flow_graph.h"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 DEFINE_FLAG(bool, enable_inlining_annotations, false, 57 DEFINE_FLAG(bool, enable_inlining_annotations, false,
58 "Enable inlining annotations"); 58 "Enable inlining annotations");
59 59
60 DECLARE_FLAG(bool, compiler_stats); 60 DECLARE_FLAG(bool, compiler_stats);
61 DECLARE_FLAG(bool, enable_type_checks); 61 DECLARE_FLAG(bool, enable_type_checks);
62 DECLARE_FLAG(int, deoptimization_counter_threshold); 62 DECLARE_FLAG(int, deoptimization_counter_threshold);
63 DECLARE_FLAG(bool, print_flow_graph); 63 DECLARE_FLAG(bool, print_flow_graph);
64 DECLARE_FLAG(bool, print_flow_graph_optimized); 64 DECLARE_FLAG(bool, print_flow_graph_optimized);
65 DECLARE_FLAG(bool, verify_compiler); 65 DECLARE_FLAG(bool, verify_compiler);
66 66
67 // Quick access to the current zone.
68 #define Z (zone())
69
67 #define TRACE_INLINING(statement) \ 70 #define TRACE_INLINING(statement) \
68 do { \ 71 do { \
69 if (FLAG_trace_inlining) statement; \ 72 if (FLAG_trace_inlining) statement; \
70 } while (false) 73 } while (false)
71 74
72 #define PRINT_INLINING_TREE(comment, caller, target, instance_call) \ 75 #define PRINT_INLINING_TREE(comment, caller, target, instance_call) \
73 do { \ 76 do { \
74 if (FLAG_print_inlining_tree) { \ 77 if (FLAG_print_inlining_tree) { \
75 inlined_info_.Add(InlinedInfo( \ 78 inlined_info_.Add(InlinedInfo( \
76 caller, target, inlining_depth_, instance_call, comment)); \ 79 caller, target, inlining_depth_, instance_call, comment)); \
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 private: 434 private:
432 bool CheckInlinedDuplicate(const Function& target); 435 bool CheckInlinedDuplicate(const Function& target);
433 bool CheckNonInlinedDuplicate(const Function& target); 436 bool CheckNonInlinedDuplicate(const Function& target);
434 437
435 bool TryInliningPoly(intptr_t receiver_cid, const Function& target); 438 bool TryInliningPoly(intptr_t receiver_cid, const Function& target);
436 bool TryInlineRecognizedMethod(intptr_t receiver_cid, const Function& target); 439 bool TryInlineRecognizedMethod(intptr_t receiver_cid, const Function& target);
437 440
438 TargetEntryInstr* BuildDecisionGraph(); 441 TargetEntryInstr* BuildDecisionGraph();
439 442
440 Isolate* isolate() const; 443 Isolate* isolate() const;
444 Zone* zone() const;
441 445
442 CallSiteInliner* const owner_; 446 CallSiteInliner* const owner_;
443 PolymorphicInstanceCallInstr* const call_; 447 PolymorphicInstanceCallInstr* const call_;
444 const intptr_t num_variants_; 448 const intptr_t num_variants_;
445 GrowableArray<CidTarget> variants_; 449 GrowableArray<CidTarget> variants_;
446 450
447 GrowableArray<CidTarget> inlined_variants_; 451 GrowableArray<CidTarget> inlined_variants_;
448 GrowableArray<CidTarget> non_inlined_variants_; 452 GrowableArray<CidTarget> non_inlined_variants_;
449 GrowableArray<BlockEntryInstr*> inlined_entries_; 453 GrowableArray<BlockEntryInstr*> inlined_entries_;
450 InlineExitCollector* exit_collector_; 454 InlineExitCollector* exit_collector_;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 inlined_recursive_call_(false), 487 inlined_recursive_call_(false),
484 inlining_depth_(1), 488 inlining_depth_(1),
485 inlining_recursion_depth_(0), 489 inlining_recursion_depth_(0),
486 collected_call_sites_(NULL), 490 collected_call_sites_(NULL),
487 inlining_call_sites_(NULL), 491 inlining_call_sites_(NULL),
488 function_cache_(), 492 function_cache_(),
489 inlined_info_() { } 493 inlined_info_() { }
490 494
491 FlowGraph* caller_graph() const { return caller_graph_; } 495 FlowGraph* caller_graph() const { return caller_graph_; }
492 496
497 Thread* thread() const { return caller_graph_->thread(); }
493 Isolate* isolate() const { return caller_graph_->isolate(); } 498 Isolate* isolate() const { return caller_graph_->isolate(); }
499 Zone* zone() const { return caller_graph_->zone(); }
494 500
495 // Inlining heuristics based on Cooper et al. 2008. 501 // Inlining heuristics based on Cooper et al. 2008.
496 bool ShouldWeInline(const Function& callee, 502 bool ShouldWeInline(const Function& callee,
497 intptr_t instr_count, 503 intptr_t instr_count,
498 intptr_t call_site_count, 504 intptr_t call_site_count,
499 intptr_t const_arg_count) { 505 intptr_t const_arg_count) {
500 if (FlowGraphInliner::AlwaysInline(callee)) { 506 if (FlowGraphInliner::AlwaysInline(callee)) {
501 return true; 507 return true;
502 } 508 }
503 if (inlined_size_ > FLAG_inlining_caller_size_threshold) { 509 if (inlined_size_ > FLAG_inlining_caller_size_threshold) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 return static_cast<double>(inlined_size_) / 584 return static_cast<double>(inlined_size_) /
579 static_cast<double>(initial_size_); 585 static_cast<double>(initial_size_);
580 } 586 }
581 587
582 // Helper to create a parameter stub from an actual argument. 588 // Helper to create a parameter stub from an actual argument.
583 Definition* CreateParameterStub(intptr_t i, 589 Definition* CreateParameterStub(intptr_t i,
584 Value* argument, 590 Value* argument,
585 FlowGraph* graph) { 591 FlowGraph* graph) {
586 ConstantInstr* constant = argument->definition()->AsConstant(); 592 ConstantInstr* constant = argument->definition()->AsConstant();
587 if (constant != NULL) { 593 if (constant != NULL) {
588 return new(isolate()) ConstantInstr(constant->value()); 594 return new(Z) ConstantInstr(constant->value());
589 } else { 595 } else {
590 return new(isolate()) ParameterInstr(i, graph->graph_entry()); 596 return new(Z) ParameterInstr(i, graph->graph_entry());
591 } 597 }
592 } 598 }
593 599
594 bool TryInlining(const Function& function, 600 bool TryInlining(const Function& function,
595 const Array& argument_names, 601 const Array& argument_names,
596 InlinedCallData* call_data) { 602 InlinedCallData* call_data) {
597 TRACE_INLINING(OS::Print(" => %s (deopt count %d)\n", 603 TRACE_INLINING(OS::Print(" => %s (deopt count %d)\n",
598 function.ToCString(), 604 function.ToCString(),
599 function.deoptimization_counter())); 605 function.deoptimization_counter()));
600 606
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 ParsedFunction* parsed_function; 673 ParsedFunction* parsed_function;
668 { 674 {
669 TimerScope timer(FLAG_compiler_stats, 675 TimerScope timer(FLAG_compiler_stats,
670 &CompilerStats::graphinliner_parse_timer, 676 &CompilerStats::graphinliner_parse_timer,
671 isolate()); 677 isolate());
672 parsed_function = GetParsedFunction(function, &in_cache); 678 parsed_function = GetParsedFunction(function, &in_cache);
673 } 679 }
674 680
675 // Load IC data for the callee. 681 // Load IC data for the callee.
676 ZoneGrowableArray<const ICData*>* ic_data_array = 682 ZoneGrowableArray<const ICData*>* ic_data_array =
677 new(isolate()) ZoneGrowableArray<const ICData*>(); 683 new(Z) ZoneGrowableArray<const ICData*>();
678 function.RestoreICDataMap(ic_data_array); 684 function.RestoreICDataMap(ic_data_array);
679 685
680 // Build the callee graph. 686 // Build the callee graph.
681 InlineExitCollector* exit_collector = 687 InlineExitCollector* exit_collector =
682 new(isolate()) InlineExitCollector(caller_graph_, call); 688 new(Z) InlineExitCollector(caller_graph_, call);
683 FlowGraphBuilder builder(parsed_function, 689 FlowGraphBuilder builder(parsed_function,
684 *ic_data_array, 690 *ic_data_array,
685 exit_collector, 691 exit_collector,
686 Isolate::kNoDeoptId); 692 Isolate::kNoDeoptId);
687 builder.SetInitialBlockId(caller_graph_->max_block_id()); 693 builder.SetInitialBlockId(caller_graph_->max_block_id());
688 FlowGraph* callee_graph; 694 FlowGraph* callee_graph;
689 { 695 {
690 TimerScope timer(FLAG_compiler_stats, 696 TimerScope timer(FLAG_compiler_stats,
691 &CompilerStats::graphinliner_build_timer, 697 &CompilerStats::graphinliner_build_timer,
692 isolate()); 698 isolate());
693 callee_graph = builder.BuildGraph(); 699 callee_graph = builder.BuildGraph();
694 } 700 }
695 701
696 // The parameter stubs are a copy of the actual arguments providing 702 // The parameter stubs are a copy of the actual arguments providing
697 // concrete information about the values, for example constant values, 703 // concrete information about the values, for example constant values,
698 // without linking between the caller and callee graphs. 704 // without linking between the caller and callee graphs.
699 // TODO(zerny): Put more information in the stubs, eg, type information. 705 // TODO(zerny): Put more information in the stubs, eg, type information.
700 ZoneGrowableArray<Definition*>* param_stubs = 706 ZoneGrowableArray<Definition*>* param_stubs =
701 new(isolate()) ZoneGrowableArray<Definition*>( 707 new(Z) ZoneGrowableArray<Definition*>(
702 function.NumParameters()); 708 function.NumParameters());
703 709
704 // Create a parameter stub for each fixed positional parameter. 710 // Create a parameter stub for each fixed positional parameter.
705 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { 711 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) {
706 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph)); 712 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph));
707 } 713 }
708 714
709 // If the callee has optional parameters, rebuild the argument and stub 715 // If the callee has optional parameters, rebuild the argument and stub
710 // arrays so that actual arguments are in one-to-one with the formal 716 // arrays so that actual arguments are in one-to-one with the formal
711 // parameters. 717 // parameters.
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 callee_graph->graph_entry()->initial_definitions(); 972 callee_graph->graph_entry()->initial_definitions();
967 for (intptr_t i = 0; i < defns->length(); ++i) { 973 for (intptr_t i = 0; i < defns->length(); ++i) {
968 ConstantInstr* constant = (*defns)[i]->AsConstant(); 974 ConstantInstr* constant = (*defns)[i]->AsConstant();
969 if ((constant != NULL) && constant->HasUses()) { 975 if ((constant != NULL) && constant->HasUses()) {
970 constant->ReplaceUsesWith( 976 constant->ReplaceUsesWith(
971 caller_graph_->GetConstant(constant->value())); 977 caller_graph_->GetConstant(constant->value()));
972 } 978 }
973 CurrentContextInstr* context = (*defns)[i]->AsCurrentContext(); 979 CurrentContextInstr* context = (*defns)[i]->AsCurrentContext();
974 if ((context != NULL) && context->HasUses()) { 980 if ((context != NULL) && context->HasUses()) {
975 ASSERT(call->IsClosureCall()); 981 ASSERT(call->IsClosureCall());
976 LoadFieldInstr* context_load = new(isolate()) LoadFieldInstr( 982 LoadFieldInstr* context_load = new(Z) LoadFieldInstr(
977 new Value((*arguments)[0]->definition()), 983 new Value((*arguments)[0]->definition()),
978 Closure::context_offset(), 984 Closure::context_offset(),
979 AbstractType::ZoneHandle(isolate(), AbstractType::null()), 985 AbstractType::ZoneHandle(isolate(), AbstractType::null()),
980 call_data->call->token_pos()); 986 call_data->call->token_pos());
981 context_load->set_is_immutable(true); 987 context_load->set_is_immutable(true);
982 context_load->set_ssa_temp_index( 988 context_load->set_ssa_temp_index(
983 caller_graph_->alloc_ssa_temp_index()); 989 caller_graph_->alloc_ssa_temp_index());
984 context_load->InsertBefore(callee_entry->next()); 990 context_load->InsertBefore(callee_entry->next());
985 context->ReplaceUsesWith(context_load); 991 context->ReplaceUsesWith(context_load);
986 } 992 }
(...skipping 16 matching lines...) Expand all
1003 // TODO(zerny): Use a hash map for the cache. 1009 // TODO(zerny): Use a hash map for the cache.
1004 for (intptr_t i = 0; i < function_cache_.length(); ++i) { 1010 for (intptr_t i = 0; i < function_cache_.length(); ++i) {
1005 ParsedFunction* parsed_function = function_cache_[i]; 1011 ParsedFunction* parsed_function = function_cache_[i];
1006 if (parsed_function->function().raw() == function.raw()) { 1012 if (parsed_function->function().raw() == function.raw()) {
1007 *in_cache = true; 1013 *in_cache = true;
1008 return parsed_function; 1014 return parsed_function;
1009 } 1015 }
1010 } 1016 }
1011 *in_cache = false; 1017 *in_cache = false;
1012 ParsedFunction* parsed_function = 1018 ParsedFunction* parsed_function =
1013 new(isolate()) ParsedFunction(isolate(), function); 1019 new(Z) ParsedFunction(thread(), function);
1014 Parser::ParseFunction(parsed_function); 1020 Parser::ParseFunction(parsed_function);
1015 parsed_function->AllocateVariables(); 1021 parsed_function->AllocateVariables();
1016 return parsed_function; 1022 return parsed_function;
1017 } 1023 }
1018 1024
1019 // Include special handling for List. factory: inlining it is not helpful 1025 // Include special handling for List. factory: inlining it is not helpful
1020 // if the incoming argument is a non-constant value. 1026 // if the incoming argument is a non-constant value.
1021 // TODO(srdjan): Fix inlining of List. factory. 1027 // TODO(srdjan): Fix inlining of List. factory.
1022 void InlineStaticCalls() { 1028 void InlineStaticCalls() {
1023 const GrowableArray<CallSites::StaticCallInfo>& call_info = 1029 const GrowableArray<CallSites::StaticCallInfo>& call_info =
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 } 1171 }
1166 ASSERT(function.NumOptionalPositionalParameters() == 1172 ASSERT(function.NumOptionalPositionalParameters() ==
1167 (param_count - fixed_param_count)); 1173 (param_count - fixed_param_count));
1168 // For each optional positional parameter without an actual, add its 1174 // For each optional positional parameter without an actual, add its
1169 // default value. 1175 // default value.
1170 for (intptr_t i = arg_count; i < param_count; ++i) { 1176 for (intptr_t i = arg_count; i < param_count; ++i) {
1171 const Object& object = 1177 const Object& object =
1172 Object::ZoneHandle( 1178 Object::ZoneHandle(
1173 parsed_function.default_parameter_values().At( 1179 parsed_function.default_parameter_values().At(
1174 i - fixed_param_count)); 1180 i - fixed_param_count));
1175 ConstantInstr* constant = new(isolate()) ConstantInstr(object); 1181 ConstantInstr* constant = new(Z) ConstantInstr(object);
1176 arguments->Add(NULL); 1182 arguments->Add(NULL);
1177 param_stubs->Add(constant); 1183 param_stubs->Add(constant);
1178 } 1184 }
1179 return true; 1185 return true;
1180 } 1186 }
1181 1187
1182 ASSERT(function.HasOptionalNamedParameters()); 1188 ASSERT(function.HasOptionalNamedParameters());
1183 1189
1184 // Passed arguments must match fixed parameters plus named arguments. 1190 // Passed arguments must match fixed parameters plus named arguments.
1185 intptr_t argument_names_count = 1191 intptr_t argument_names_count =
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner, 1259 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner,
1254 PolymorphicInstanceCallInstr* call, 1260 PolymorphicInstanceCallInstr* call,
1255 const Function& caller_function) 1261 const Function& caller_function)
1256 : owner_(owner), 1262 : owner_(owner),
1257 call_(call), 1263 call_(call),
1258 num_variants_(call->ic_data().NumberOfChecks()), 1264 num_variants_(call->ic_data().NumberOfChecks()),
1259 variants_(num_variants_), 1265 variants_(num_variants_),
1260 inlined_variants_(num_variants_), 1266 inlined_variants_(num_variants_),
1261 non_inlined_variants_(num_variants_), 1267 non_inlined_variants_(num_variants_),
1262 inlined_entries_(num_variants_), 1268 inlined_entries_(num_variants_),
1263 exit_collector_(new(isolate()) 1269 exit_collector_(new(Z)
1264 InlineExitCollector(owner->caller_graph(), call)), 1270 InlineExitCollector(owner->caller_graph(), call)),
1265 caller_function_(caller_function) { 1271 caller_function_(caller_function) {
1266 } 1272 }
1267 1273
1268 1274
1269 Isolate* PolymorphicInliner::isolate() const { 1275 Isolate* PolymorphicInliner::isolate() const {
1270 return owner_->caller_graph()->isolate(); 1276 return owner_->caller_graph()->isolate();
1271 } 1277 }
1272 1278
1273 1279
1280 Zone* PolymorphicInliner::zone() const {
1281 return owner_->caller_graph()->zone();
1282 }
1283
1284
1274 // Inlined bodies are shared if two different class ids have the same 1285 // Inlined bodies are shared if two different class ids have the same
1275 // inlined target. This sharing is represented by using three different 1286 // inlined target. This sharing is represented by using three different
1276 // types of entries in the inlined_entries_ array: 1287 // types of entries in the inlined_entries_ array:
1277 // 1288 //
1278 // * GraphEntry: the inlined body is not shared. 1289 // * GraphEntry: the inlined body is not shared.
1279 // 1290 //
1280 // * TargetEntry: the inlined body is shared and this is the first variant. 1291 // * TargetEntry: the inlined body is shared and this is the first variant.
1281 // 1292 //
1282 // * JoinEntry: the inlined body is shared and this is a subsequent variant. 1293 // * JoinEntry: the inlined body is shared and this is a subsequent variant.
1283 bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) { 1294 bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) {
(...skipping 19 matching lines...) Expand all
1303 old_target->ReplaceAsPredecessorWith(new_join); 1314 old_target->ReplaceAsPredecessorWith(new_join);
1304 for (intptr_t j = 0; j < old_target->dominated_blocks().length(); ++j) { 1315 for (intptr_t j = 0; j < old_target->dominated_blocks().length(); ++j) {
1305 BlockEntryInstr* block = old_target->dominated_blocks()[j]; 1316 BlockEntryInstr* block = old_target->dominated_blocks()[j];
1306 new_join->AddDominatedBlock(block); 1317 new_join->AddDominatedBlock(block);
1307 } 1318 }
1308 // Create a new target with the join as unconditional successor. 1319 // Create a new target with the join as unconditional successor.
1309 TargetEntryInstr* new_target = 1320 TargetEntryInstr* new_target =
1310 new TargetEntryInstr(owner_->caller_graph()->allocate_block_id(), 1321 new TargetEntryInstr(owner_->caller_graph()->allocate_block_id(),
1311 old_target->try_index()); 1322 old_target->try_index());
1312 new_target->InheritDeoptTarget(isolate(), new_join); 1323 new_target->InheritDeoptTarget(isolate(), new_join);
1313 GotoInstr* new_goto = new(isolate()) GotoInstr(new_join); 1324 GotoInstr* new_goto = new(Z) GotoInstr(new_join);
1314 new_goto->InheritDeoptTarget(isolate(), new_join); 1325 new_goto->InheritDeoptTarget(isolate(), new_join);
1315 new_target->LinkTo(new_goto); 1326 new_target->LinkTo(new_goto);
1316 new_target->set_last_instruction(new_goto); 1327 new_target->set_last_instruction(new_goto);
1317 new_join->predecessors_.Add(new_target); 1328 new_join->predecessors_.Add(new_target);
1318 1329
1319 // Record the new target for the first variant. 1330 // Record the new target for the first variant.
1320 inlined_entries_[i] = new_target; 1331 inlined_entries_[i] = new_target;
1321 } 1332 }
1322 ASSERT(inlined_entries_[i]->IsTargetEntry()); 1333 ASSERT(inlined_entries_[i]->IsTargetEntry());
1323 // Record the shared join for this variant. 1334 // Record the shared join for this variant.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 FlowGraph* callee_graph = call_data.callee_graph; 1376 FlowGraph* callee_graph = call_data.callee_graph;
1366 call_data.exit_collector->PrepareGraphs(callee_graph); 1377 call_data.exit_collector->PrepareGraphs(callee_graph);
1367 inlined_entries_.Add(callee_graph->graph_entry()); 1378 inlined_entries_.Add(callee_graph->graph_entry());
1368 exit_collector_->Union(call_data.exit_collector); 1379 exit_collector_->Union(call_data.exit_collector);
1369 1380
1370 // Replace parameter stubs and constants. Replace the receiver argument 1381 // Replace parameter stubs and constants. Replace the receiver argument
1371 // with a redefinition to prevent code from the inlined body from being 1382 // with a redefinition to prevent code from the inlined body from being
1372 // hoisted above the inlined entry. 1383 // hoisted above the inlined entry.
1373 ASSERT(arguments.length() > 0); 1384 ASSERT(arguments.length() > 0);
1374 Value* actual = arguments[0]; 1385 Value* actual = arguments[0];
1375 RedefinitionInstr* redefinition = new(isolate()) 1386 RedefinitionInstr* redefinition = new(Z)
1376 RedefinitionInstr(actual->Copy(isolate())); 1387 RedefinitionInstr(actual->Copy(isolate()));
1377 redefinition->set_ssa_temp_index( 1388 redefinition->set_ssa_temp_index(
1378 owner_->caller_graph()->alloc_ssa_temp_index()); 1389 owner_->caller_graph()->alloc_ssa_temp_index());
1379 redefinition->UpdateType(CompileType::FromCid(receiver_cid)); 1390 redefinition->UpdateType(CompileType::FromCid(receiver_cid));
1380 redefinition->InsertAfter(callee_graph->graph_entry()->normal_entry()); 1391 redefinition->InsertAfter(callee_graph->graph_entry()->normal_entry());
1381 Definition* stub = (*call_data.parameter_stubs)[0]; 1392 Definition* stub = (*call_data.parameter_stubs)[0];
1382 stub->ReplaceUsesWith(redefinition); 1393 stub->ReplaceUsesWith(redefinition);
1383 1394
1384 for (intptr_t i = 1; i < arguments.length(); ++i) { 1395 for (intptr_t i = 1; i < arguments.length(); ++i) {
1385 actual = arguments[i]; 1396 actual = arguments[i];
1386 if (actual != NULL) { 1397 if (actual != NULL) {
1387 stub = (*call_data.parameter_stubs)[i]; 1398 stub = (*call_data.parameter_stubs)[i];
1388 stub->ReplaceUsesWith(actual->definition()); 1399 stub->ReplaceUsesWith(actual->definition());
1389 } 1400 }
1390 } 1401 }
1391 GrowableArray<Definition*>* defns = 1402 GrowableArray<Definition*>* defns =
1392 callee_graph->graph_entry()->initial_definitions(); 1403 callee_graph->graph_entry()->initial_definitions();
1393 for (intptr_t i = 0; i < defns->length(); ++i) { 1404 for (intptr_t i = 0; i < defns->length(); ++i) {
1394 ConstantInstr* constant = (*defns)[i]->AsConstant(); 1405 ConstantInstr* constant = (*defns)[i]->AsConstant();
1395 if ((constant != NULL) && constant->HasUses()) { 1406 if ((constant != NULL) && constant->HasUses()) {
1396 constant->ReplaceUsesWith( 1407 constant->ReplaceUsesWith(
1397 owner_->caller_graph()->GetConstant(constant->value())); 1408 owner_->caller_graph()->GetConstant(constant->value()));
1398 } 1409 }
1399 CurrentContextInstr* context = (*defns)[i]->AsCurrentContext(); 1410 CurrentContextInstr* context = (*defns)[i]->AsCurrentContext();
1400 if ((context != NULL) && context->HasUses()) { 1411 if ((context != NULL) && context->HasUses()) {
1401 ASSERT(call_data.call->IsClosureCall()); 1412 ASSERT(call_data.call->IsClosureCall());
1402 LoadFieldInstr* context_load = new(isolate()) LoadFieldInstr( 1413 LoadFieldInstr* context_load = new(Z) LoadFieldInstr(
1403 new Value(redefinition), 1414 new Value(redefinition),
1404 Closure::context_offset(), 1415 Closure::context_offset(),
1405 AbstractType::ZoneHandle(isolate(), AbstractType::null()), 1416 AbstractType::ZoneHandle(isolate(), AbstractType::null()),
1406 call_data.call->token_pos()); 1417 call_data.call->token_pos());
1407 context_load->set_is_immutable(true); 1418 context_load->set_is_immutable(true);
1408 context_load->set_ssa_temp_index( 1419 context_load->set_ssa_temp_index(
1409 owner_->caller_graph()->alloc_ssa_temp_index()); 1420 owner_->caller_graph()->alloc_ssa_temp_index());
1410 context_load->InsertAfter(redefinition); 1421 context_load->InsertAfter(redefinition);
1411 context->ReplaceUsesWith(context_load); 1422 context->ReplaceUsesWith(context_load);
1412 } 1423 }
(...skipping 16 matching lines...) Expand all
1429 bool PolymorphicInliner::TryInlineRecognizedMethod(intptr_t receiver_cid, 1440 bool PolymorphicInliner::TryInlineRecognizedMethod(intptr_t receiver_cid,
1430 const Function& target) { 1441 const Function& target) {
1431 FlowGraphOptimizer optimizer(owner_->caller_graph()); 1442 FlowGraphOptimizer optimizer(owner_->caller_graph());
1432 TargetEntryInstr* entry; 1443 TargetEntryInstr* entry;
1433 Definition* last; 1444 Definition* last;
1434 // Replace the receiver argument with a redefinition to prevent code from 1445 // Replace the receiver argument with a redefinition to prevent code from
1435 // the inlined body from being hoisted above the inlined entry. 1446 // the inlined body from being hoisted above the inlined entry.
1436 GrowableArray<Definition*> arguments(call_->ArgumentCount()); 1447 GrowableArray<Definition*> arguments(call_->ArgumentCount());
1437 Definition* receiver = call_->ArgumentAt(0); 1448 Definition* receiver = call_->ArgumentAt(0);
1438 RedefinitionInstr* redefinition = 1449 RedefinitionInstr* redefinition =
1439 new(isolate()) RedefinitionInstr(new(isolate()) Value(receiver)); 1450 new(Z) RedefinitionInstr(new(Z) Value(receiver));
1440 redefinition->set_ssa_temp_index( 1451 redefinition->set_ssa_temp_index(
1441 owner_->caller_graph()->alloc_ssa_temp_index()); 1452 owner_->caller_graph()->alloc_ssa_temp_index());
1442 if (optimizer.TryInlineRecognizedMethod(receiver_cid, 1453 if (optimizer.TryInlineRecognizedMethod(receiver_cid,
1443 target, 1454 target,
1444 call_, 1455 call_,
1445 redefinition, 1456 redefinition,
1446 call_->instance_call()->token_pos(), 1457 call_->instance_call()->token_pos(),
1447 *call_->instance_call()->ic_data(), 1458 *call_->instance_call()->ic_data(),
1448 &entry, &last)) { 1459 &entry, &last)) {
1449 // Create a graph fragment. 1460 // Create a graph fragment.
1450 redefinition->InsertAfter(entry); 1461 redefinition->InsertAfter(entry);
1451 InlineExitCollector* exit_collector = 1462 InlineExitCollector* exit_collector =
1452 new(isolate()) InlineExitCollector(owner_->caller_graph(), call_); 1463 new(Z) InlineExitCollector(owner_->caller_graph(), call_);
1453 1464
1454 ReturnInstr* result = 1465 ReturnInstr* result =
1455 new(isolate()) ReturnInstr(call_->instance_call()->token_pos(), 1466 new(Z) ReturnInstr(call_->instance_call()->token_pos(),
1456 new(isolate()) Value(last)); 1467 new(Z) Value(last));
1457 owner_->caller_graph()->AppendTo( 1468 owner_->caller_graph()->AppendTo(
1458 last, 1469 last,
1459 result, 1470 result,
1460 call_->env(), // Return can become deoptimization target. 1471 call_->env(), // Return can become deoptimization target.
1461 FlowGraph::kEffect); 1472 FlowGraph::kEffect);
1462 entry->set_last_instruction(result); 1473 entry->set_last_instruction(result);
1463 exit_collector->AddExit(result); 1474 exit_collector->AddExit(result);
1464 GraphEntryInstr* graph_entry = 1475 GraphEntryInstr* graph_entry =
1465 new(isolate()) GraphEntryInstr(NULL, // No parsed function. 1476 new(Z) GraphEntryInstr(NULL, // No parsed function.
1466 entry, 1477 entry,
1467 Isolate::kNoDeoptId); // No OSR id. 1478 Isolate::kNoDeoptId); // No OSR id.
1468 // Update polymorphic inliner state. 1479 // Update polymorphic inliner state.
1469 inlined_entries_.Add(graph_entry); 1480 inlined_entries_.Add(graph_entry);
1470 exit_collector_->Union(exit_collector); 1481 exit_collector_->Union(exit_collector);
1471 return true; 1482 return true;
1472 } 1483 }
1473 return false; 1484 return false;
1474 } 1485 }
1475 1486
1476 1487
1477 // Build a DAG to dispatch to the inlined function bodies. Load the class 1488 // Build a DAG to dispatch to the inlined function bodies. Load the class
1478 // id of the receiver and make explicit comparisons for each inlined body, 1489 // id of the receiver and make explicit comparisons for each inlined body,
1479 // in frequency order. If all variants are inlined, the entry to the last 1490 // in frequency order. If all variants are inlined, the entry to the last
1480 // inlined body is guarded by a CheckClassId instruction which can deopt. 1491 // inlined body is guarded by a CheckClassId instruction which can deopt.
1481 // If not all variants are inlined, we add a PolymorphicInstanceCall 1492 // If not all variants are inlined, we add a PolymorphicInstanceCall
1482 // instruction to handle the non-inlined variants. 1493 // instruction to handle the non-inlined variants.
1483 TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() { 1494 TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
1484 // Start with a fresh target entry. 1495 // Start with a fresh target entry.
1485 TargetEntryInstr* entry = 1496 TargetEntryInstr* entry =
1486 new(isolate()) TargetEntryInstr( 1497 new(Z) TargetEntryInstr(
1487 owner_->caller_graph()->allocate_block_id(), 1498 owner_->caller_graph()->allocate_block_id(),
1488 call_->GetBlock()->try_index()); 1499 call_->GetBlock()->try_index());
1489 entry->InheritDeoptTarget(isolate(), call_); 1500 entry->InheritDeoptTarget(isolate(), call_);
1490 1501
1491 // This function uses a cursor (a pointer to the 'current' instruction) to 1502 // This function uses a cursor (a pointer to the 'current' instruction) to
1492 // build the graph. The next instruction will be inserted after the 1503 // build the graph. The next instruction will be inserted after the
1493 // cursor. 1504 // cursor.
1494 TargetEntryInstr* current_block = entry; 1505 TargetEntryInstr* current_block = entry;
1495 Instruction* cursor = entry; 1506 Instruction* cursor = entry;
1496 1507
1497 Definition* receiver = call_->ArgumentAt(0); 1508 Definition* receiver = call_->ArgumentAt(0);
1498 // There are at least two variants including non-inlined ones, so we have 1509 // There are at least two variants including non-inlined ones, so we have
1499 // at least one branch on the class id. 1510 // at least one branch on the class id.
1500 LoadClassIdInstr* load_cid = 1511 LoadClassIdInstr* load_cid =
1501 new(isolate()) LoadClassIdInstr(new(isolate()) Value(receiver)); 1512 new(Z) LoadClassIdInstr(new(Z) Value(receiver));
1502 load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index()); 1513 load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index());
1503 cursor = AppendInstruction(cursor, load_cid); 1514 cursor = AppendInstruction(cursor, load_cid);
1504 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) { 1515 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) {
1505 // 1. Guard the body with a class id check. 1516 // 1. Guard the body with a class id check.
1506 if ((i == (inlined_variants_.length() - 1)) && 1517 if ((i == (inlined_variants_.length() - 1)) &&
1507 non_inlined_variants_.is_empty()) { 1518 non_inlined_variants_.is_empty()) {
1508 // If it is the last variant use a check class id instruction which can 1519 // If it is the last variant use a check class id instruction which can
1509 // deoptimize, followed unconditionally by the body. 1520 // deoptimize, followed unconditionally by the body.
1510 RedefinitionInstr* cid_redefinition = 1521 RedefinitionInstr* cid_redefinition =
1511 new RedefinitionInstr(new(isolate()) Value(load_cid)); 1522 new RedefinitionInstr(new(Z) Value(load_cid));
1512 cid_redefinition->set_ssa_temp_index( 1523 cid_redefinition->set_ssa_temp_index(
1513 owner_->caller_graph()->alloc_ssa_temp_index()); 1524 owner_->caller_graph()->alloc_ssa_temp_index());
1514 cursor = AppendInstruction(cursor, cid_redefinition); 1525 cursor = AppendInstruction(cursor, cid_redefinition);
1515 CheckClassIdInstr* check_class_id = new(isolate()) CheckClassIdInstr( 1526 CheckClassIdInstr* check_class_id = new(Z) CheckClassIdInstr(
1516 new(isolate()) Value(cid_redefinition), 1527 new(Z) Value(cid_redefinition),
1517 inlined_variants_[i].cid, 1528 inlined_variants_[i].cid,
1518 call_->deopt_id()); 1529 call_->deopt_id());
1519 check_class_id->InheritDeoptTarget(isolate(), call_); 1530 check_class_id->InheritDeoptTarget(isolate(), call_);
1520 cursor = AppendInstruction(cursor, check_class_id); 1531 cursor = AppendInstruction(cursor, check_class_id);
1521 1532
1522 // The next instruction is the first instruction of the inlined body. 1533 // The next instruction is the first instruction of the inlined body.
1523 // Handle the two possible cases (unshared and shared subsequent 1534 // Handle the two possible cases (unshared and shared subsequent
1524 // predecessors) separately. 1535 // predecessors) separately.
1525 BlockEntryInstr* callee_entry = inlined_entries_[i]; 1536 BlockEntryInstr* callee_entry = inlined_entries_[i];
1526 if (callee_entry->IsGraphEntry()) { 1537 if (callee_entry->IsGraphEntry()) {
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
1815 1826
1816 1827
1817 intptr_t FlowGraphInliner::NextInlineId(const Function& function) { 1828 intptr_t FlowGraphInliner::NextInlineId(const Function& function) {
1818 const intptr_t id = inline_id_to_function_->length(); 1829 const intptr_t id = inline_id_to_function_->length();
1819 inline_id_to_function_->Add(&function); 1830 inline_id_to_function_->Add(&function);
1820 return id; 1831 return id;
1821 } 1832 }
1822 1833
1823 1834
1824 } // namespace dart 1835 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/flow_graph_optimizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698