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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 22613)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -15,6 +15,7 @@
#include "vm/parser.h"
#include "vm/resolver.h"
#include "vm/scopes.h"
+#include "vm/stack_frame.h"
#include "vm/symbols.h"
namespace dart {
@@ -455,6 +456,14 @@
InsertConversionsFor(phi);
}
}
+ CatchBlockEntryInstr* catch_entry = entry->AsCatchBlockEntry();
+ if (catch_entry != NULL) {
+ for (intptr_t i = 0;
+ i < catch_entry->initial_definitions()->length();
+ i++) {
+ InsertConversionsFor((*catch_entry->initial_definitions())[i]);
+ }
+ }
for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
Definition* def = it.Current()->AsDefinition();
if (def != NULL) {
@@ -2710,6 +2719,30 @@
!block_it.Done();
block_it.Advance()) {
BlockEntryInstr* block = block_it.Current();
+
+
+ if (block->IsGraphEntry() || block->IsCatchBlockEntry()) {
+ const GrowableArray<Definition*>& initial = block->IsGraphEntry()
+ ? *block->AsGraphEntry()->initial_definitions()
+ : *block->AsCatchBlockEntry()->initial_definitions();
+ for (intptr_t i = 0; i < initial.length(); ++i) {
+ Definition* current = initial[i];
+ if (current->Type()->ToCid() == kSmiCid) {
+ smi_values_.Add(current);
+ }
+ }
+ }
+
+ JoinEntryInstr* join = block->AsJoinEntry();
+ if (join != NULL) {
+ for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
+ PhiInstr* current = phi_it.Current();
+ if (current->Type()->ToCid() == kSmiCid) {
+ smi_values_.Add(current);
+ }
+ }
+ }
+
for (ForwardInstructionIterator instr_it(block);
!instr_it.Done();
instr_it.Advance()) {
@@ -2724,16 +2757,6 @@
smi_checks_.Add(current->AsCheckSmi());
}
}
-
- JoinEntryInstr* join = block->AsJoinEntry();
- if (join != NULL) {
- for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
- PhiInstr* current = phi_it.Current();
- if (current->Type()->ToCid() == kSmiCid) {
- smi_values_.Add(current);
- }
- }
- }
}
}
@@ -3171,6 +3194,73 @@
}
+void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) {
+ // For every catch-block: Iterate over all call instructions inside the
+ // corresponding try-block and figure out for each environment value if it
+ // is the same constant at all calls. If yes, replace the initial definition
+ // at the catch-entry with this constant.
+ const GrowableArray<CatchBlockEntryInstr*>& catch_entries =
+ flow_graph->graph_entry()->catch_entries();
+ intptr_t base = kFirstLocalSlotFromFp + flow_graph->num_non_copied_params();
+ for (intptr_t catch_idx = 0;
+ catch_idx < catch_entries.length();
+ ++catch_idx) {
+ CatchBlockEntryInstr* cb = catch_entries[catch_idx];
+ CatchEntryInstr* catch_entry = cb->next()->AsCatchEntry();
+
+ // Initialize cdefs with the original initial definitions (ParameterInstr).
+ // The following representation is used:
+ // ParameterInstr => unknown
+ // ConstantInstr => known constant
+ // NULL => non-constant
+ GrowableArray<Definition*>* idefs = cb->initial_definitions();
+ GrowableArray<Definition*> cdefs(idefs->length());
+ cdefs.AddArray(*idefs);
+
+ // exception_var and stacktrace_var are never constant.
+ intptr_t ex_idx = base - catch_entry->exception_var().index();
+ intptr_t st_idx = base - catch_entry->stacktrace_var().index();
+ cdefs[ex_idx] = cdefs[st_idx] = NULL;
+
+ for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ BlockEntryInstr* block = block_it.Current();
+ if (block->try_index() == cb->catch_try_index()) {
+ for (ForwardInstructionIterator instr_it(block);
+ !instr_it.Done();
+ instr_it.Advance()) {
+ Instruction* current = instr_it.Current();
+ if (current->MayThrow()) {
+ Environment* env = current->env();
+ for (intptr_t env_idx = 0; env_idx < cdefs.length(); ++env_idx) {
+ if (cdefs[env_idx] != NULL &&
+ env->ValueAt(env_idx)->BindsToConstant()) {
+ cdefs[env_idx] = env->ValueAt(env_idx)->definition();
+ }
+ if (cdefs[env_idx] != env->ValueAt(env_idx)->definition()) {
+ cdefs[env_idx] = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+ for (intptr_t j = 0; j < idefs->length(); ++j) {
+ if (cdefs[j] != NULL && cdefs[j]->IsConstant()) {
+ // TODO(fschneider): Use constants from the constant pool.
+ Definition* old = (*idefs)[j];
+ ConstantInstr* orig = cdefs[j]->AsConstant();
+ ConstantInstr* copy = new ConstantInstr(orig->value());
+ copy->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index());
+ old->ReplaceUsesWith(copy);
+ (*idefs)[j] = copy;
+ }
+ }
+ }
+}
+
+
static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) {
for (intptr_t j = 0; j < header->PredecessorCount(); ++j) {
BlockEntryInstr* candidate = header->PredecessorAt(j);
@@ -4530,7 +4620,11 @@
}
ASSERT(ForwardInstructionIterator(block).Done());
- SetReachable(block->normal_entry());
+ // TODO(fschneider): Improve this approximation. The catch entry is only
+ // reachable if a call in the try-block is reachable.
+ for (intptr_t i = 0; i < block->SuccessorCount(); ++i) {
+ SetReachable(block->SuccessorAt(i));
+ }
}
@@ -4550,6 +4644,10 @@
void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) {
+ const GrowableArray<Definition*>& defs = *block->initial_definitions();
+ for (intptr_t i = 0; i < defs.length(); ++i) {
+ defs[i]->Accept(this);
+ }
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
@@ -5371,12 +5469,18 @@
void ConstantPropagator::VisitBranches() {
GraphEntryInstr* entry = graph_->graph_entry();
reachable_->Add(entry->preorder_number());
- // TODO(fschneider): Handle CatchEntry.
- reachable_->Add(entry->normal_entry()->preorder_number());
- block_worklist_.Add(entry->normal_entry());
+ block_worklist_.Add(entry);
while (!block_worklist_.is_empty()) {
BlockEntryInstr* block = block_worklist_.RemoveLast();
+ if (block->IsGraphEntry()) {
+ // TODO(fschneider): Improve this approximation. Catch entries are only
+ // reachable if a call in the corresponding try-block is reachable.
+ for (intptr_t i = 0; i < block->SuccessorCount(); ++i) {
+ SetReachable(block->SuccessorAt(i));
+ }
+ continue;
+ }
Instruction* last = block->last_instruction();
if (last->IsGoto()) {
SetReachable(last->AsGoto()->successor());
« 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