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

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

Issue 14682020: Optimize functions containing try-catch. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: rebased Created 7 years, 7 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_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('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_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
11 #include "vm/hash_map.h" 11 #include "vm/hash_map.h"
12 #include "vm/il_printer.h" 12 #include "vm/il_printer.h"
13 #include "vm/intermediate_language.h" 13 #include "vm/intermediate_language.h"
14 #include "vm/object_store.h" 14 #include "vm/object_store.h"
15 #include "vm/parser.h" 15 #include "vm/parser.h"
16 #include "vm/resolver.h" 16 #include "vm/resolver.h"
17 #include "vm/scopes.h" 17 #include "vm/scopes.h"
18 #include "vm/stack_frame.h"
18 #include "vm/symbols.h" 19 #include "vm/symbols.h"
19 20
20 namespace dart { 21 namespace dart {
21 22
22 DEFINE_FLAG(bool, array_bounds_check_elimination, true, 23 DEFINE_FLAG(bool, array_bounds_check_elimination, true,
23 "Eliminate redundant bounds checks."); 24 "Eliminate redundant bounds checks.");
24 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); 25 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
25 DEFINE_FLAG(int, max_polymorphic_checks, 4, 26 DEFINE_FLAG(int, max_polymorphic_checks, 4,
26 "Maximum number of polymorphic check, otherwise it is megamorphic."); 27 "Maximum number of polymorphic check, otherwise it is megamorphic.");
27 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); 28 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis.");
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 BlockEntryInstr* entry = block_order_[i]; 449 BlockEntryInstr* entry = block_order_[i];
449 JoinEntryInstr* join_entry = entry->AsJoinEntry(); 450 JoinEntryInstr* join_entry = entry->AsJoinEntry();
450 if (join_entry != NULL) { 451 if (join_entry != NULL) {
451 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { 452 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
452 PhiInstr* phi = it.Current(); 453 PhiInstr* phi = it.Current();
453 ASSERT(phi != NULL); 454 ASSERT(phi != NULL);
454 ASSERT(phi->is_alive()); 455 ASSERT(phi->is_alive());
455 InsertConversionsFor(phi); 456 InsertConversionsFor(phi);
456 } 457 }
457 } 458 }
459 CatchBlockEntryInstr* catch_entry = entry->AsCatchBlockEntry();
460 if (catch_entry != NULL) {
461 for (intptr_t i = 0;
462 i < catch_entry->initial_definitions()->length();
463 i++) {
464 InsertConversionsFor((*catch_entry->initial_definitions())[i]);
465 }
466 }
458 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 467 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
459 Definition* def = it.Current()->AsDefinition(); 468 Definition* def = it.Current()->AsDefinition();
460 if (def != NULL) { 469 if (def != NULL) {
461 InsertConversionsFor(def); 470 InsertConversionsFor(def);
462 } 471 }
463 } 472 }
464 } 473 }
465 } 474 }
466 475
467 476
(...skipping 2235 matching lines...) Expand 10 before | Expand all | Expand 10 after
2703 Definition* current = initial[i]; 2712 Definition* current = initial[i];
2704 if (current->Type()->ToCid() == kSmiCid) { 2713 if (current->Type()->ToCid() == kSmiCid) {
2705 smi_values_.Add(current); 2714 smi_values_.Add(current);
2706 } 2715 }
2707 } 2716 }
2708 2717
2709 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 2718 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
2710 !block_it.Done(); 2719 !block_it.Done();
2711 block_it.Advance()) { 2720 block_it.Advance()) {
2712 BlockEntryInstr* block = block_it.Current(); 2721 BlockEntryInstr* block = block_it.Current();
2722
2723
2724 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) {
2725 const GrowableArray<Definition*>& initial = block->IsGraphEntry()
2726 ? *block->AsGraphEntry()->initial_definitions()
2727 : *block->AsCatchBlockEntry()->initial_definitions();
2728 for (intptr_t i = 0; i < initial.length(); ++i) {
2729 Definition* current = initial[i];
2730 if (current->Type()->ToCid() == kSmiCid) {
2731 smi_values_.Add(current);
2732 }
2733 }
2734 }
2735
2736 JoinEntryInstr* join = block->AsJoinEntry();
2737 if (join != NULL) {
2738 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
2739 PhiInstr* current = phi_it.Current();
2740 if (current->Type()->ToCid() == kSmiCid) {
2741 smi_values_.Add(current);
2742 }
2743 }
2744 }
2745
2713 for (ForwardInstructionIterator instr_it(block); 2746 for (ForwardInstructionIterator instr_it(block);
2714 !instr_it.Done(); 2747 !instr_it.Done();
2715 instr_it.Advance()) { 2748 instr_it.Advance()) {
2716 Instruction* current = instr_it.Current(); 2749 Instruction* current = instr_it.Current();
2717 Definition* defn = current->AsDefinition(); 2750 Definition* defn = current->AsDefinition();
2718 if (defn != NULL) { 2751 if (defn != NULL) {
2719 if ((defn->Type()->ToCid() == kSmiCid) && 2752 if ((defn->Type()->ToCid() == kSmiCid) &&
2720 (defn->ssa_temp_index() != -1)) { 2753 (defn->ssa_temp_index() != -1)) {
2721 smi_values_.Add(defn); 2754 smi_values_.Add(defn);
2722 } 2755 }
2723 } else if (current->IsCheckSmi()) { 2756 } else if (current->IsCheckSmi()) {
2724 smi_checks_.Add(current->AsCheckSmi()); 2757 smi_checks_.Add(current->AsCheckSmi());
2725 } 2758 }
2726 } 2759 }
2727
2728 JoinEntryInstr* join = block->AsJoinEntry();
2729 if (join != NULL) {
2730 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
2731 PhiInstr* current = phi_it.Current();
2732 if (current->Type()->ToCid() == kSmiCid) {
2733 smi_values_.Add(current);
2734 }
2735 }
2736 }
2737 } 2760 }
2738 } 2761 }
2739 2762
2740 2763
2741 // Returns true if use is dominated by the given instruction. 2764 // Returns true if use is dominated by the given instruction.
2742 // Note: uses that occur at instruction itself are not dominated by it. 2765 // Note: uses that occur at instruction itself are not dominated by it.
2743 static bool IsDominatedUse(Instruction* dom, Value* use) { 2766 static bool IsDominatedUse(Instruction* dom, Value* use) {
2744 BlockEntryInstr* dom_block = dom->GetBlock(); 2767 BlockEntryInstr* dom_block = dom->GetBlock();
2745 2768
2746 Instruction* instr = use->instruction(); 2769 Instruction* instr = use->instruction();
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
3164 } 3187 }
3165 } 3188 }
3166 3189
3167 3190
3168 void FlowGraphOptimizer::InferSmiRanges() { 3191 void FlowGraphOptimizer::InferSmiRanges() {
3169 RangeAnalysis range_analysis(flow_graph_); 3192 RangeAnalysis range_analysis(flow_graph_);
3170 range_analysis.Analyze(); 3193 range_analysis.Analyze();
3171 } 3194 }
3172 3195
3173 3196
3197 void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) {
3198 // For every catch-block: Iterate over all call instructions inside the
3199 // corresponding try-block and figure out for each environment value if it
3200 // is the same constant at all calls. If yes, replace the initial definition
3201 // at the catch-entry with this constant.
3202 const GrowableArray<CatchBlockEntryInstr*>& catch_entries =
3203 flow_graph->graph_entry()->catch_entries();
3204 intptr_t base = kFirstLocalSlotFromFp + flow_graph->num_non_copied_params();
3205 for (intptr_t catch_idx = 0;
3206 catch_idx < catch_entries.length();
3207 ++catch_idx) {
3208 CatchBlockEntryInstr* cb = catch_entries[catch_idx];
3209 CatchEntryInstr* catch_entry = cb->next()->AsCatchEntry();
3210
3211 // Initialize cdefs with the original initial definitions (ParameterInstr).
3212 // The following representation is used:
3213 // ParameterInstr => unknown
3214 // ConstantInstr => known constant
3215 // NULL => non-constant
3216 GrowableArray<Definition*>* idefs = cb->initial_definitions();
3217 GrowableArray<Definition*> cdefs(idefs->length());
3218 cdefs.AddArray(*idefs);
3219
3220 // exception_var and stacktrace_var are never constant.
3221 intptr_t ex_idx = base - catch_entry->exception_var().index();
3222 intptr_t st_idx = base - catch_entry->stacktrace_var().index();
3223 cdefs[ex_idx] = cdefs[st_idx] = NULL;
3224
3225 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
3226 !block_it.Done();
3227 block_it.Advance()) {
3228 BlockEntryInstr* block = block_it.Current();
3229 if (block->try_index() == cb->catch_try_index()) {
3230 for (ForwardInstructionIterator instr_it(block);
3231 !instr_it.Done();
3232 instr_it.Advance()) {
3233 Instruction* current = instr_it.Current();
3234 if (current->MayThrow()) {
3235 Environment* env = current->env();
3236 for (intptr_t env_idx = 0; env_idx < cdefs.length(); ++env_idx) {
3237 if (cdefs[env_idx] != NULL &&
3238 env->ValueAt(env_idx)->BindsToConstant()) {
3239 cdefs[env_idx] = env->ValueAt(env_idx)->definition();
3240 }
3241 if (cdefs[env_idx] != env->ValueAt(env_idx)->definition()) {
3242 cdefs[env_idx] = NULL;
3243 }
3244 }
3245 }
3246 }
3247 }
3248 }
3249 for (intptr_t j = 0; j < idefs->length(); ++j) {
3250 if (cdefs[j] != NULL && cdefs[j]->IsConstant()) {
3251 // TODO(fschneider): Use constants from the constant pool.
3252 Definition* old = (*idefs)[j];
3253 ConstantInstr* orig = cdefs[j]->AsConstant();
3254 ConstantInstr* copy = new ConstantInstr(orig->value());
3255 copy->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index());
3256 old->ReplaceUsesWith(copy);
3257 (*idefs)[j] = copy;
3258 }
3259 }
3260 }
3261 }
3262
3263
3174 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) { 3264 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) {
3175 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) { 3265 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) {
3176 BlockEntryInstr* candidate = header->PredecessorAt(j); 3266 BlockEntryInstr* candidate = header->PredecessorAt(j);
3177 if (header->dominator() == candidate) { 3267 if (header->dominator() == candidate) {
3178 return candidate; 3268 return candidate;
3179 } 3269 }
3180 } 3270 }
3181 return NULL; 3271 return NULL;
3182 } 3272 }
3183 3273
(...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after
4523 // -------------------------------------------------------------------------- 4613 // --------------------------------------------------------------------------
4524 // Analysis of blocks. Called at most once per block. The block is already 4614 // Analysis of blocks. Called at most once per block. The block is already
4525 // marked as reachable. All instructions in the block are analyzed. 4615 // marked as reachable. All instructions in the block are analyzed.
4526 void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) { 4616 void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) {
4527 const GrowableArray<Definition*>& defs = *block->initial_definitions(); 4617 const GrowableArray<Definition*>& defs = *block->initial_definitions();
4528 for (intptr_t i = 0; i < defs.length(); ++i) { 4618 for (intptr_t i = 0; i < defs.length(); ++i) {
4529 defs[i]->Accept(this); 4619 defs[i]->Accept(this);
4530 } 4620 }
4531 ASSERT(ForwardInstructionIterator(block).Done()); 4621 ASSERT(ForwardInstructionIterator(block).Done());
4532 4622
4533 SetReachable(block->normal_entry()); 4623 // TODO(fschneider): Improve this approximation. The catch entry is only
4624 // reachable if a call in the try-block is reachable.
4625 for (intptr_t i = 0; i < block->SuccessorCount(); ++i) {
4626 SetReachable(block->SuccessorAt(i));
4627 }
4534 } 4628 }
4535 4629
4536 4630
4537 void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) { 4631 void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) {
4538 // Phis are visited when visiting Goto at a predecessor. See VisitGoto. 4632 // Phis are visited when visiting Goto at a predecessor. See VisitGoto.
4539 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 4633 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
4540 it.Current()->Accept(this); 4634 it.Current()->Accept(this);
4541 } 4635 }
4542 } 4636 }
4543 4637
4544 4638
4545 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { 4639 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) {
4546 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 4640 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
4547 it.Current()->Accept(this); 4641 it.Current()->Accept(this);
4548 } 4642 }
4549 } 4643 }
4550 4644
4551 4645
4552 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { 4646 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) {
4647 const GrowableArray<Definition*>& defs = *block->initial_definitions();
4648 for (intptr_t i = 0; i < defs.length(); ++i) {
4649 defs[i]->Accept(this);
4650 }
4553 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 4651 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
4554 it.Current()->Accept(this); 4652 it.Current()->Accept(this);
4555 } 4653 }
4556 } 4654 }
4557 4655
4558 4656
4559 void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) { 4657 void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) {
4560 // Parallel moves have not yet been inserted in the graph. 4658 // Parallel moves have not yet been inserted in the graph.
4561 UNREACHABLE(); 4659 UNREACHABLE();
4562 } 4660 }
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after
5364 BlockEntryInstr* block = block_worklist_.RemoveLast(); 5462 BlockEntryInstr* block = block_worklist_.RemoveLast();
5365 block->Accept(this); 5463 block->Accept(this);
5366 } 5464 }
5367 } 5465 }
5368 } 5466 }
5369 5467
5370 5468
5371 void ConstantPropagator::VisitBranches() { 5469 void ConstantPropagator::VisitBranches() {
5372 GraphEntryInstr* entry = graph_->graph_entry(); 5470 GraphEntryInstr* entry = graph_->graph_entry();
5373 reachable_->Add(entry->preorder_number()); 5471 reachable_->Add(entry->preorder_number());
5374 // TODO(fschneider): Handle CatchEntry. 5472 block_worklist_.Add(entry);
5375 reachable_->Add(entry->normal_entry()->preorder_number());
5376 block_worklist_.Add(entry->normal_entry());
5377 5473
5378 while (!block_worklist_.is_empty()) { 5474 while (!block_worklist_.is_empty()) {
5379 BlockEntryInstr* block = block_worklist_.RemoveLast(); 5475 BlockEntryInstr* block = block_worklist_.RemoveLast();
5476 if (block->IsGraphEntry()) {
5477 // TODO(fschneider): Improve this approximation. Catch entries are only
5478 // reachable if a call in the corresponding try-block is reachable.
5479 for (intptr_t i = 0; i < block->SuccessorCount(); ++i) {
5480 SetReachable(block->SuccessorAt(i));
5481 }
5482 continue;
5483 }
5380 Instruction* last = block->last_instruction(); 5484 Instruction* last = block->last_instruction();
5381 if (last->IsGoto()) { 5485 if (last->IsGoto()) {
5382 SetReachable(last->AsGoto()->successor()); 5486 SetReachable(last->AsGoto()->successor());
5383 } else if (last->IsBranch()) { 5487 } else if (last->IsBranch()) {
5384 BranchInstr* branch = last->AsBranch(); 5488 BranchInstr* branch = last->AsBranch();
5385 // The current block must be reachable. 5489 // The current block must be reachable.
5386 ASSERT(reachable_->Contains(branch->GetBlock()->preorder_number())); 5490 ASSERT(reachable_->Contains(branch->GetBlock()->preorder_number()));
5387 if (branch->constant_target() != NULL) { 5491 if (branch->constant_target() != NULL) {
5388 // Found constant target computed by range analysis. 5492 // Found constant target computed by range analysis.
5389 if (branch->constant_target() == branch->true_successor()) { 5493 if (branch->constant_target() == branch->true_successor()) {
(...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after
6154 6258
6155 // Insert materializations at environment uses. 6259 // Insert materializations at environment uses.
6156 const Class& cls = Class::Handle(alloc->constructor().Owner()); 6260 const Class& cls = Class::Handle(alloc->constructor().Owner());
6157 for (intptr_t i = 0; i < exits.length(); i++) { 6261 for (intptr_t i = 0; i < exits.length(); i++) {
6158 CreateMaterializationAt(exits[i], alloc, cls, *fields); 6262 CreateMaterializationAt(exits[i], alloc, cls, *fields);
6159 } 6263 }
6160 } 6264 }
6161 6265
6162 6266
6163 } // namespace dart 6267 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698