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

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

Powered by Google App Engine
This is Rietveld 408576698