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

Unified Diff: runtime/vm/flow_graph_builder.cc

Issue 10014006: Try/catch in graph builder. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 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
Index: runtime/vm/flow_graph_builder.cc
===================================================================
--- runtime/vm/flow_graph_builder.cc (revision 6367)
+++ runtime/vm/flow_graph_builder.cc (working copy)
@@ -5,6 +5,7 @@
#include "vm/flow_graph_builder.h"
#include "vm/ast_printer.h"
+#include "vm/code_descriptors.h"
#include "vm/dart_entry.h"
#include "vm/flags.h"
#include "vm/intermediate_language.h"
@@ -21,6 +22,22 @@
DECLARE_FLAG(bool, enable_type_checks);
DECLARE_FLAG(bool, print_ast);
+
+FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function)
+ : parsed_function_(parsed_function),
+ preorder_block_entries_(),
+ postorder_block_entries_(),
+ context_level_(0),
+ last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
+ try_index_(CatchClauseNode::kInvalidTryIndex),
+ catch_entries_() {}
+
+
+void FlowGraphBuilder::AddCatchEntry(intptr_t try_index, Instruction* entry) {
+ catch_entries_.Add(entry);
+}
+
+
void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) {
ASSERT(is_open());
if (other_fragment.is_empty()) return;
@@ -117,6 +134,31 @@
}
+// Stores current context into the 'variable'
+void EffectGraphVisitor::BuildStoreContext(const LocalVariable& variable,
+ intptr_t start_index) {
+ AddInstruction(new BindInstr(start_index, new CurrentContextComp()));
+ StoreLocalComp* store_context = new StoreLocalComp(
+ variable,
+ new TempVal(start_index),
+ owner()->context_level());
+ AddInstruction(new DoInstr(store_context));
+}
+
+
+// Loads context saved in 'context_variable' into the current context.
+void EffectGraphVisitor::BuildLoadContext(
+ const LocalVariable& context_variable, intptr_t start_index) {
regis 2012/04/10 22:58:24 Should you also call the variable in BuildStoreCon
srdjan 2012/04/10 23:11:58 -> variable
+ LoadLocalComp* load_saved_context =
+ new LoadLocalComp(context_variable, owner()->context_level());
+ AddInstruction(new BindInstr(start_index, load_saved_context));
+ StoreContextComp* store_context =
+ new StoreContextComp(new TempVal(start_index));
+ AddInstruction(new DoInstr(store_context));
+}
+
+
+
void TestGraphVisitor::ReturnValue(Value* value) {
BranchInstr* branch = new BranchInstr(value);
AddInstruction(branch);
@@ -178,12 +220,7 @@
ASSERT(current_context_level >= 0);
if (owner()->parsed_function().saved_context_var() != NULL) {
// CTX on entry was saved, but not linked as context parent.
- LoadLocalComp* load_comp =
- new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0);
- AddInstruction(new BindInstr(temp_index(), load_comp));
- TempVal* local_value = new TempVal(temp_index());
- StoreContextComp* store_context = new StoreContextComp(local_value);
- AddInstruction(new DoInstr(store_context));
+ BuildLoadContext(*owner()->parsed_function().saved_context_var(), 0);
} else {
while (current_context_level-- > 0) {
UnchainContext();
@@ -258,9 +295,13 @@
arguments->Add(for_left_value.value());
arguments->Add(for_right_value.value());
const String& name = String::ZoneHandle(String::NewSymbol(node->Name()));
- InstanceCallComp* call =
- new InstanceCallComp(node->id(), node->token_index(), name,
- arguments, Array::ZoneHandle(), 2);
+ InstanceCallComp* call = new InstanceCallComp(node->id(),
+ node->token_index(),
+ owner()->try_index(),
+ name,
+ arguments,
+ Array::ZoneHandle(),
+ 2);
ReturnComputation(call);
}
@@ -377,6 +418,7 @@
TranslateArgumentList(*interpol_arg, temp_index(), values);
StaticCallComp* call =
new StaticCallComp(node->token_index(),
+ owner()->try_index(),
interpol_func,
interpol_arg->names(),
values);
@@ -395,6 +437,7 @@
InstanceOfComp* instance_of = new InstanceOfComp(
node->id(),
node->token_index(),
+ owner()->try_index(),
for_left_value.value(),
node->right()->AsTypeNode()->type(),
(node->kind() == Token::kISNOT));
@@ -428,9 +471,9 @@
// Boolean negation '!' cannot be overloaded neither.
if (node->kind() == Token::kNE) {
const String& name = String::ZoneHandle(String::NewSymbol("=="));
- InstanceCallComp* call_equal =
- new InstanceCallComp(node->id(), node->token_index(), name,
- arguments, Array::ZoneHandle(), 2);
+ InstanceCallComp* call_equal = new InstanceCallComp(
+ node->id(), node->token_index(), owner()->try_index(), name,
+ arguments, Array::ZoneHandle(), 2);
AddInstruction(new BindInstr(temp_index(), call_equal));
Value* eq_result = new TempVal(temp_index());
if (FLAG_enable_type_checks) {
@@ -440,9 +483,9 @@
ReturnComputation(negate);
} else {
const String& name = String::ZoneHandle(String::NewSymbol(node->Name()));
- InstanceCallComp* call =
- new InstanceCallComp(node->id(), node->token_index(), name,
- arguments, Array::ZoneHandle(), 2);
+ InstanceCallComp* call = new InstanceCallComp(
+ node->id(), node->token_index(), owner()->try_index(), name,
+ arguments, Array::ZoneHandle(), 2);
ReturnComputation(call);
}
}
@@ -470,9 +513,9 @@
String::ZoneHandle(String::NewSymbol((node->kind() == Token::kSUB)
? Token::Str(Token::kNEGATE)
: node->Name()));
- InstanceCallComp* call =
- new InstanceCallComp(node->id(), node->token_index(), name,
- arguments, Array::ZoneHandle(), 1);
+ InstanceCallComp* call = new InstanceCallComp(
+ node->id(), node->token_index(), owner()->try_index(), name,
+ arguments, Array::ZoneHandle(), 1);
ReturnComputation(call);
}
@@ -541,9 +584,9 @@
String::ZoneHandle(Field::GetterSymbol(node->field_name()));
ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(1);
arguments->Add(new TempVal(next_index));
- InstanceCallComp* load =
- new InstanceCallComp(node->getter_id(), node->token_index(), getter_name,
- arguments, Array::ZoneHandle(), 1);
+ InstanceCallComp* load = new InstanceCallComp(
+ node->getter_id(), node->token_index(), owner()->try_index(),
+ getter_name, arguments, Array::ZoneHandle(), 1);
AddInstruction(new BindInstr(next_index, load));
return next_index;
@@ -565,9 +608,9 @@
arguments->Add(new TempVal(start_index));
const String& op_name =
String::ZoneHandle(String::NewSymbol((kind == Token::kINCR) ? "+" : "-"));
- InstanceCallComp* add =
- new InstanceCallComp(node_id, token_index, op_name,
- arguments, Array::ZoneHandle(), 2);
+ InstanceCallComp* add = new InstanceCallComp(
+ node_id, token_index, owner()->try_index(), op_name,
+ arguments, Array::ZoneHandle(), 2);
AddInstruction(new BindInstr(start_index - 1, add));
}
@@ -585,7 +628,9 @@
value_index + 1);
// 3. Perform the store, returning the stored value.
InstanceSetterComp* store =
- new InstanceSetterComp(node->setter_id(), node->token_index(),
+ new InstanceSetterComp(node->setter_id(),
+ node->token_index(),
+ owner()->try_index(),
node->field_name(),
new TempVal(value_index - 1),
new TempVal(value_index));
@@ -620,9 +665,9 @@
ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
arguments->Add(new TempVal(value_index - 1));
arguments->Add(new TempVal(value_index));
- InstanceCallComp* store =
- new InstanceCallComp(node->setter_id(), node->token_index(),
- setter_name, arguments, Array::ZoneHandle(), 1);
+ InstanceCallComp* store = new InstanceCallComp(
+ node->setter_id(), node->token_index(), owner()->try_index(),
+ setter_name, arguments, Array::ZoneHandle(), 1);
AddInstruction(new DoInstr(store));
ReturnValue(new TempVal(AllocateTempIndex()));
}
@@ -654,9 +699,9 @@
arguments->Add(new TempVal(next_index + 1));
const String& load_name =
String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX)));
- InstanceCallComp* load =
- new InstanceCallComp(node->load_id(), node->token_index(), load_name,
- arguments, Array::ZoneHandle(), 1);
+ InstanceCallComp* load = new InstanceCallComp(
+ node->load_id(), node->token_index(), owner()->try_index(),
+ load_name, arguments, Array::ZoneHandle(), 1);
AddInstruction(new BindInstr(next_index, load));
return next_index;
}
@@ -675,6 +720,7 @@
// 3. Perform the store, returning the stored value.
StoreIndexedComp* store = new StoreIndexedComp(node->store_id(),
node->token_index(),
+ owner()->try_index(),
new TempVal(value_index - 2),
new TempVal(value_index - 1),
new TempVal(value_index));
@@ -709,9 +755,9 @@
arguments->Add(new TempVal(value_index - 2));
arguments->Add(new TempVal(value_index - 1));
arguments->Add(new TempVal(value_index));
- InstanceCallComp* store =
- new InstanceCallComp(node->store_id(), node->token_index(), store_name,
- arguments, Array::ZoneHandle(), 1);
+ InstanceCallComp* store = new InstanceCallComp(
+ node->store_id(), node->token_index(), owner()->try_index(),
+ store_name, arguments, Array::ZoneHandle(), 1);
AddInstruction(new DoInstr(store));
ReturnValue(new TempVal(AllocateTempIndex()));
}
@@ -1156,7 +1202,9 @@
values->Add(for_value.value());
index = for_value.temp_index();
}
- CreateArrayComp* create = new CreateArrayComp(node, values);
+ CreateArrayComp* create = new CreateArrayComp(node,
+ owner()->try_index(),
+ values);
ReturnComputation(create);
}
@@ -1194,7 +1242,8 @@
BuildInstantiatorTypeArguments(node->token_index(), temp_index());
}
- CreateClosureComp* create = new CreateClosureComp(node, type_arguments);
+ CreateClosureComp* create =
+ new CreateClosureComp(node, owner()->try_index(), type_arguments);
ReturnComputation(create);
}
@@ -1223,9 +1272,9 @@
values->Add(for_receiver.value());
TranslateArgumentList(*arguments, for_receiver.temp_index(), values);
- InstanceCallComp* call =
- new InstanceCallComp(node->id(), node->token_index(),
- node->function_name(), values,
+ InstanceCallComp* call = new InstanceCallComp(
+ node->id(), node->token_index(), owner()->try_index(),
+ node->function_name(), values,
arguments->names(), 1);
ReturnComputation(call);
}
@@ -1239,6 +1288,7 @@
TranslateArgumentList(*node->arguments(), temp_index(), values);
StaticCallComp* call =
new StaticCallComp(node->token_index(),
+ owner()->try_index(),
node->function(),
node->arguments()->names(),
values);
@@ -1260,8 +1310,10 @@
arguments->Add(for_closure.value());
TranslateArgumentList(*node->arguments(), temp_index() + 2, arguments);
// First operand is the saved context, consumed by the call.
- ClosureCallComp* call =
- new ClosureCallComp(node, new TempVal(temp_index()), arguments);
+ ClosureCallComp* call = new ClosureCallComp(node,
+ owner()->try_index(),
+ new TempVal(temp_index()),
+ arguments);
ReturnComputation(call);
}
@@ -1270,7 +1322,10 @@
AddInstruction(new BindInstr(temp_index(), new CurrentContextComp()));
TempVal* ctx = new TempVal(temp_index());
AddInstruction(new BindInstr(temp_index(),
- new CloneContextComp(node->id(), node->token_index(), ctx)));
+ new CloneContextComp(node->id(),
+ node->token_index(),
+ owner()->try_index(),
+ ctx)));
TempVal* cloned_ctx = new TempVal(temp_index());
ReturnComputation(new StoreContextComp(cloned_ctx));
}
@@ -1287,7 +1342,9 @@
BuildConstructorTypeArguments(node, start_index, allocate_arguments);
}
AllocateObjectComp* alloc_comp =
- new AllocateObjectComp(node, allocate_arguments);
+ new AllocateObjectComp(node,
+ owner()->try_index(),
+ allocate_arguments);
AddInstruction(new BindInstr(start_index, alloc_comp));
return new TempVal(start_index);
}
@@ -1306,6 +1363,7 @@
TranslateArgumentList(*node->arguments(), start_index + 1, values);
StaticCallComp* call =
new StaticCallComp(node->token_index(),
+ owner()->try_index(),
node->constructor(),
node->arguments()->names(),
values);
@@ -1324,6 +1382,7 @@
factory_arguments);
StaticCallComp* call =
new StaticCallComp(node->token_index(),
+ owner()->try_index(),
node->constructor(),
node->arguments()->names(),
factory_arguments);
@@ -1399,7 +1458,9 @@
Value* instantiator_value =
BuildInstantiatorTypeArguments(node->token_index(), start_index);
ExtractFactoryTypeArgumentsComp* extract =
- new ExtractFactoryTypeArgumentsComp(node, instantiator_value);
+ new ExtractFactoryTypeArgumentsComp(node,
+ owner()->try_index(),
+ instantiator_value);
AddInstruction(new BindInstr(start_index, extract));
return new TempVal(start_index);
}
@@ -1482,9 +1543,9 @@
arguments->Add(for_receiver.value());
const String& name =
String::ZoneHandle(Field::GetterSymbol(node->field_name()));
- InstanceCallComp* call =
- new InstanceCallComp(node->id(), node->token_index(), name,
- arguments, Array::ZoneHandle(), 1);
+ InstanceCallComp* call = new InstanceCallComp(
+ node->id(), node->token_index(), owner()->try_index(), name,
+ arguments, Array::ZoneHandle(), 1);
ReturnComputation(call);
}
@@ -1496,11 +1557,13 @@
ArgumentGraphVisitor for_value(owner(), for_receiver.temp_index());
node->value()->Visit(&for_value);
Append(for_value);
- InstanceSetterComp* setter = new InstanceSetterComp(node->id(),
- node->token_index(),
- node->field_name(),
- for_receiver.value(),
- for_value.value());
+ InstanceSetterComp* setter =
+ new InstanceSetterComp(node->id(),
+ node->token_index(),
+ owner()->try_index(),
+ node->field_name(),
+ for_receiver.value(),
+ for_value.value());
ReturnComputation(setter);
}
@@ -1513,6 +1576,7 @@
ASSERT(!getter_function.IsNull());
ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>();
StaticCallComp* call = new StaticCallComp(node->token_index(),
+ owner()->try_index(),
getter_function,
Array::ZoneHandle(), // No names.
values);
@@ -1530,6 +1594,7 @@
node->value()->Visit(&for_value);
Append(for_value);
StaticSetterComp* call = new StaticSetterComp(node->token_index(),
+ owner()->try_index(),
setter_function,
for_value.value());
ReturnComputation(call);
@@ -1537,7 +1602,8 @@
void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) {
- NativeCallComp* native_call = new NativeCallComp(node);
+ NativeCallComp* native_call =
+ new NativeCallComp(node, owner()->try_index());
ReturnComputation(native_call);
}
@@ -1656,9 +1722,9 @@
arguments->Add(for_index.value());
const String& name =
String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX)));
- InstanceCallComp* call =
- new InstanceCallComp(node->id(), node->token_index(), name,
- arguments, Array::ZoneHandle(), 1);
+ InstanceCallComp* call = new InstanceCallComp(
+ node->id(), node->token_index(), owner()->try_index(), name,
+ arguments, Array::ZoneHandle(), 1);
ReturnComputation(call);
}
@@ -1675,6 +1741,7 @@
Append(for_value);
StoreIndexedComp* store = new StoreIndexedComp(node->id(),
node->token_index(),
+ owner()->try_index(),
for_array.value(),
for_index.value(),
for_value.value());
@@ -1711,8 +1778,10 @@
// The loop local scope declares variables that are captured.
// Allocate and chain a new context.
// Allocate context computation (uses current CTX)
- AllocateContextComp* comp = new AllocateContextComp(node->token_index(),
- num_context_variables);
+ AllocateContextComp* comp = new AllocateContextComp(
+ node->token_index(),
+ owner()->try_index(),
+ num_context_variables);
AddInstruction(new BindInstr(temp_index(), comp));
Value* allocated_context_value = new TempVal(temp_index());
@@ -1801,12 +1870,7 @@
if (is_open()) {
if (MustSaveRestoreContext(node)) {
ASSERT(num_context_variables > 0);
- LoadLocalComp* load_comp =
- new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0);
- AddInstruction(new BindInstr(temp_index(), load_comp));
- TempVal* local_value = new TempVal(temp_index());
- StoreContextComp* store_context = new StoreContextComp(local_value);
- AddInstruction(new DoInstr(store_context));
+ BuildLoadContext(*owner()->parsed_function().saved_context_var(), 0);
} else if (num_context_variables > 0) {
UnchainContext();
}
@@ -1834,12 +1898,59 @@
void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) {
- Bailout("EffectGraphVisitor::VisitCatchClauseNode");
+ // NOTE: The implicit variables ':saved_context', ':exception_var'
+ // and ':stacktrace_var' can never be captured variables.
+ // Restores CTX from local variable ':saved_context'.
+ CatchEntryComp* catch_entry = new CatchEntryComp(node->exception_var(),
+ node->stacktrace_var());
+ AddInstruction(new DoInstr(catch_entry));
+ BuildLoadContext(node->context_var(), temp_index());
+
+ EffectGraphVisitor for_catch(owner(), temp_index());
+ node->VisitChildren(&for_catch);
+ Append(for_catch);
}
void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) {
- Bailout("EffectGraphVisitor::VisitTryCatchNode");
+ intptr_t old_try_index = owner()->try_index();
+ intptr_t try_index = owner()->allocate_try_index();
+ owner()->set_try_index(try_index);
+
+ // Preserve CTX into local variable '%saved_context'.
+ BuildStoreContext(node->context_var(), temp_index());
+
+ EffectGraphVisitor for_try_block(owner(), temp_index());
+ node->try_block()->Visit(&for_try_block);
+ Append(for_try_block);
+
+ // We are done generating code for the try block.
+ owner()->set_try_index(old_try_index);
+
+ CatchClauseNode* catch_block = node->catch_block();
+ if (catch_block != NULL) {
+ // Set the corresponding try index for this catch block so
+ // that we can set the appropriate handler pc when we generate
+ // code for this catch block.
+ catch_block->set_try_index(try_index);
+ EffectGraphVisitor for_catch_block(owner(), temp_index());
+ for_catch_block.AddInstruction(new TargetEntryInstr(try_index));
+ catch_block->Visit(&for_catch_block);
+ owner()->AddCatchEntry(try_index, for_catch_block.entry());
+ ASSERT(!for_catch_block.is_open());
+ if ((node->end_catch_label() != NULL) &&
+ (node->end_catch_label()->join_for_continue() != NULL)) {
+ if (is_open()) {
+ AddInstruction(node->end_catch_label()->join_for_continue());
+ } else {
+ exit_ = node->end_catch_label()->join_for_continue();
+ }
+ }
+ }
+
+ if (node->finally_block() != NULL) {
+ Bailout("EffectGraphVisitor::VisitTryCatchNode finally");
+ }
}
@@ -1849,14 +1960,17 @@
Append(for_exception);
Instruction* instr = NULL;
if (node->stacktrace() == NULL) {
- instr = new ThrowInstr(
- node->id(), node->token_index(), for_exception.value());
+ instr = new ThrowInstr(node->id(),
+ node->token_index(),
+ owner()->try_index(),
+ for_exception.value());
} else {
ValueGraphVisitor for_stack_trace(owner(), temp_index() + 1);
node->stacktrace()->Visit(&for_stack_trace);
Append(for_stack_trace);
instr = new ReThrowInstr(node->id(),
node->token_index(),
+ owner()->try_index(),
for_exception.value(),
for_stack_trace.value());
}
@@ -2183,6 +2297,12 @@
}
+void FlowGraphPrinter::VisitCatchEntry(CatchEntryComp* comp) {
+ OS::Print("CatchEntry(%s, %s)", comp->exception_var().name().ToCString(),
+ comp->stacktrace_var().name().ToCString());
+}
+
+
void FlowGraphPrinter::VisitStoreContext(StoreContextComp* comp) {
OS::Print("StoreContext(");
comp->value()->Accept(this);
@@ -2196,7 +2316,12 @@
void FlowGraphPrinter::VisitTargetEntry(TargetEntryInstr* instr) {
- OS::Print("%2d: [target]", reverse_index(instr->postorder_number()));
+ OS::Print("%2d: [target", reverse_index(instr->postorder_number()));
+ if (instr->HasTryIndex()) {
+ OS::Print(" catch %d]", instr->try_index());
+ } else {
+ OS::Print("]");
+ }
}
@@ -2264,10 +2389,18 @@
parsed_function().node_sequence()->Visit(&for_effect);
// Check that the graph is properly terminated.
ASSERT(!for_effect.is_open());
+ GrowableArray<intptr_t> parent;
+ for (intptr_t i = 0; i < catch_entries_.length(); i++) {
+ Instruction* entry = catch_entries_[i];
+ entry->DiscoverBlocks(NULL, // Entry block predecessor.
+ &preorder_block_entries_,
+ &postorder_block_entries_,
+ &parent);
+ ComputeDominators(&preorder_block_entries_, &parent);
+ }
if (for_effect.entry() != NULL) {
// Perform a depth-first traversal of the graph to build preorder and
// postorder block orders.
- GrowableArray<intptr_t> parent;
for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor.
&preorder_block_entries_,
&postorder_block_entries_,

Powered by Google App Engine
This is Rietveld 408576698