| Index: runtime/vm/flow_graph_builder.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_builder.cc (revision 6388)
|
| +++ 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& variable, intptr_t start_index) {
|
| + LoadLocalComp* load_saved_context =
|
| + new LoadLocalComp(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()->AllocateTryIndex();
|
| + 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_,
|
|
|