Index: runtime/vm/kernel_to_il.cc |
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc |
index f5c2b833bb09697b1fca3b332673fe9215682d98..1130320dcf1afbdfa98ba157d685267494722cf6 100644 |
--- a/runtime/vm/kernel_to_il.cc |
+++ b/runtime/vm/kernel_to_il.cc |
@@ -816,186 +816,6 @@ void ScopeBuilder::VisitConstructor(Constructor* node) { |
} |
-class BreakableBlock { |
- public: |
- BreakableBlock(FlowGraphBuilder* builder, LabeledStatement* statement) |
- : builder_(builder), |
- labeled_statement_(statement), |
- outer_(builder->breakable_block_), |
- destination_(NULL), |
- outer_finally_(builder->try_finally_block_), |
- context_depth_(builder->context_depth_), |
- try_index_(builder->CurrentTryIndex()) { |
- builder_->breakable_block_ = this; |
- } |
- ~BreakableBlock() { builder_->breakable_block_ = outer_; } |
- |
- bool HadJumper() { return destination_ != NULL; } |
- |
- JoinEntryInstr* destination() { return destination_; } |
- |
- JoinEntryInstr* BreakDestination(LabeledStatement* label, |
- TryFinallyBlock** outer_finally, |
- intptr_t* context_depth) { |
- BreakableBlock* block = builder_->breakable_block_; |
- while (block->labeled_statement_ != label) { |
- block = block->outer_; |
- } |
- ASSERT(block != NULL); |
- *outer_finally = block->outer_finally_; |
- *context_depth = block->context_depth_; |
- return block->EnsureDestination(); |
- } |
- |
- private: |
- JoinEntryInstr* EnsureDestination() { |
- if (destination_ == NULL) { |
- destination_ = builder_->BuildJoinEntry(try_index_); |
- } |
- return destination_; |
- } |
- |
- FlowGraphBuilder* builder_; |
- LabeledStatement* labeled_statement_; |
- BreakableBlock* outer_; |
- JoinEntryInstr* destination_; |
- TryFinallyBlock* outer_finally_; |
- intptr_t context_depth_; |
- intptr_t try_index_; |
-}; |
- |
- |
-class SwitchBlock { |
- public: |
- SwitchBlock(FlowGraphBuilder* builder, SwitchStatement* switch_stmt) |
- : builder_(builder), |
- outer_(builder->switch_block_), |
- outer_finally_(builder->try_finally_block_), |
- switch_statement_(switch_stmt), |
- context_depth_(builder->context_depth_), |
- try_index_(builder->CurrentTryIndex()) { |
- builder_->switch_block_ = this; |
- } |
- ~SwitchBlock() { builder_->switch_block_ = outer_; } |
- |
- bool HadJumper(SwitchCase* switch_case) { |
- return destinations_.Lookup(switch_case) != NULL; |
- } |
- |
- JoinEntryInstr* Destination(SwitchCase* label, |
- TryFinallyBlock** outer_finally = NULL, |
- intptr_t* context_depth = NULL) { |
- // Find corresponding [SwitchStatement]. |
- SwitchBlock* block = this; |
- while (true) { |
- block->EnsureSwitchCaseMapping(); |
- if (block->Contains(label)) break; |
- block = block->outer_; |
- } |
- |
- // Set the outer finally block. |
- if (outer_finally != NULL) { |
- *outer_finally = block->outer_finally_; |
- *context_depth = block->context_depth_; |
- } |
- |
- // Ensure there's [JoinEntryInstr] for that [SwitchCase]. |
- return block->EnsureDestination(label); |
- } |
- |
- private: |
- typedef std::set<SwitchCase*> DestinationSwitches; |
- |
- JoinEntryInstr* EnsureDestination(SwitchCase* switch_case) { |
- JoinEntryInstr* cached_inst = destinations_.Lookup(switch_case); |
- if (cached_inst == NULL) { |
- JoinEntryInstr* inst = builder_->BuildJoinEntry(try_index_); |
- destinations_.Insert(switch_case, inst); |
- return inst; |
- } |
- return cached_inst; |
- } |
- |
- void EnsureSwitchCaseMapping() { |
- if (destination_switches_.begin() == destination_switches_.end()) { |
- List<SwitchCase>& cases = switch_statement_->cases(); |
- for (intptr_t i = 0; i < cases.length(); i++) { |
- destination_switches_.insert(cases[i]); |
- } |
- } |
- } |
- |
- bool Contains(SwitchCase* sc) { |
- return destination_switches_.find(sc) != destination_switches_.end(); |
- } |
- |
- FlowGraphBuilder* builder_; |
- SwitchBlock* outer_; |
- |
- Map<SwitchCase, JoinEntryInstr*> destinations_; |
- DestinationSwitches destination_switches_; |
- |
- TryFinallyBlock* outer_finally_; |
- SwitchStatement* switch_statement_; |
- intptr_t context_depth_; |
- intptr_t try_index_; |
-}; |
- |
- |
-class TryFinallyBlock { |
- public: |
- TryFinallyBlock(FlowGraphBuilder* builder, Statement* finalizer) |
- : builder_(builder), |
- outer_(builder->try_finally_block_), |
- finalizer_(finalizer), |
- context_depth_(builder->context_depth_), |
- // Finalizers are executed outside of the try block hence |
- // try depth of finalizers are one less than current try |
- // depth. |
- try_depth_(builder->try_depth_ - 1), |
- try_index_(builder_->CurrentTryIndex()) { |
- builder_->try_finally_block_ = this; |
- } |
- ~TryFinallyBlock() { builder_->try_finally_block_ = outer_; } |
- |
- Statement* finalizer() const { return finalizer_; } |
- intptr_t context_depth() const { return context_depth_; } |
- intptr_t try_depth() const { return try_depth_; } |
- intptr_t try_index() const { return try_index_; } |
- TryFinallyBlock* outer() const { return outer_; } |
- |
- private: |
- FlowGraphBuilder* const builder_; |
- TryFinallyBlock* const outer_; |
- Statement* const finalizer_; |
- const intptr_t context_depth_; |
- const intptr_t try_depth_; |
- const intptr_t try_index_; |
-}; |
- |
- |
-class TryCatchBlock { |
- public: |
- explicit TryCatchBlock(FlowGraphBuilder* builder, |
- intptr_t try_handler_index = -1) |
- : builder_(builder), |
- outer_(builder->try_catch_block_), |
- try_index_(try_handler_index) { |
- if (try_index_ == -1) try_index_ = builder->AllocateTryIndex(); |
- builder->try_catch_block_ = this; |
- } |
- ~TryCatchBlock() { builder_->try_catch_block_ = outer_; } |
- |
- intptr_t try_index() { return try_index_; } |
- TryCatchBlock* outer() const { return outer_; } |
- |
- private: |
- FlowGraphBuilder* builder_; |
- TryCatchBlock* outer_; |
- intptr_t try_index_; |
-}; |
- |
- |
Fragment& Fragment::operator+=(const Fragment& other) { |
if (entry == NULL) { |
entry = other.entry; |
@@ -2271,11 +2091,17 @@ Fragment FlowGraphBuilder::TranslateFinallyFinalizers( |
} |
Statement* finalizer = try_finally_block_->finalizer(); |
+ intptr_t finalizer_kernel_offset = |
+ try_finally_block_->finalizer_kernel_offset(); |
try_finally_block_ = try_finally_block_->outer(); |
- |
- // This will potentially have exceptional cases as described in |
- // [VisitTryFinally] and will handle them. |
- instructions += TranslateStatement(finalizer); |
+ if (finalizer != NULL) { |
+ // This will potentially have exceptional cases as described in |
+ // [VisitTryFinally] and will handle them. |
+ instructions += TranslateStatement(finalizer); |
+ } else { |
+ instructions += streaming_flow_graph_builder_->BuildStatementAt( |
+ finalizer_kernel_offset); |
+ } |
// We only need to make sure that if the finalizer ended normally, we |
// continue towards the next outer try-finally. |
@@ -2299,9 +2125,15 @@ Fragment FlowGraphBuilder::TranslateFinallyFinalizers( |
Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) { |
+ return EnterScope(node->kernel_offset(), new_context); |
+} |
+ |
+ |
+Fragment FlowGraphBuilder::EnterScope(intptr_t kernel_offset, |
+ bool* new_context) { |
Fragment instructions; |
const intptr_t context_size = |
- scopes_->scopes.Lookup(node->kernel_offset())->num_context_variables(); |
+ scopes_->scopes.Lookup(kernel_offset)->num_context_variables(); |
if (context_size > 0) { |
instructions += PushContext(context_size); |
instructions += Drop(); |
@@ -2314,9 +2146,14 @@ Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) { |
Fragment FlowGraphBuilder::ExitScope(TreeNode* node) { |
+ return ExitScope(node->kernel_offset()); |
+} |
+ |
+ |
+Fragment FlowGraphBuilder::ExitScope(intptr_t kernel_offset) { |
Fragment instructions; |
const intptr_t context_size = |
- scopes_->scopes.Lookup(node->kernel_offset())->num_context_variables(); |
+ scopes_->scopes.Lookup(kernel_offset)->num_context_variables(); |
if (context_size > 0) { |
instructions += PopContext(); |
} |
@@ -3193,6 +3030,13 @@ LocalVariable* FlowGraphBuilder::LookupVariable(VariableDeclaration* var) { |
} |
+dart::LocalVariable* FlowGraphBuilder::LookupVariable(intptr_t kernel_offset) { |
+ LocalVariable* local = scopes_->locals.Lookup(kernel_offset); |
+ ASSERT(local != NULL); |
+ return local; |
+} |
+ |
+ |
void FlowGraphBuilder::SetTempIndex(Definition* definition) { |
definition->set_temp_index( |
stack_ == NULL ? 0 : stack_->definition()->temp_index() + 1); |
@@ -3988,6 +3832,18 @@ Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode( |
return Fragment(); |
} |
+Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode( |
+ const AbstractType& dst_type, |
+ const dart::String& name_symbol) { |
+ if (I->type_checks()) { |
+ if (dst_type.IsMalformed()) { |
+ return ThrowTypeError(); |
+ } |
+ return CheckAssignableInCheckedMode(dst_type, name_symbol); |
+ } |
+ return Fragment(); |
+} |
+ |
bool FlowGraphBuilder::NeedsDebugStepCheck(const Function& function, |
TokenPosition position) { |
@@ -4541,7 +4397,15 @@ Fragment FlowGraphBuilder::TranslateStatement(Statement* statement) { |
#ifdef DEBUG |
intptr_t original_context_depth = context_depth_; |
#endif |
- statement->AcceptStatementVisitor(this); |
+ |
+ // TODO(jensj): VariableDeclaration doesn't necessarily have a tag. |
+ if (statement->can_stream() && |
+ statement->Type() != Node::kTypeVariableDeclaration) { |
+ fragment_ = streaming_flow_graph_builder_->BuildStatementAt( |
+ statement->kernel_offset()); |
+ } else { |
+ statement->AcceptStatementVisitor(this); |
+ } |
DEBUG_ASSERT(context_depth_ == original_context_depth); |
return fragment_; |
} |
@@ -4562,7 +4426,12 @@ Fragment FlowGraphBuilder::TranslateCondition(Expression* expression, |
Fragment FlowGraphBuilder::TranslateExpression(Expression* expression) { |
- expression->AcceptExpressionVisitor(this); |
+ if (expression->can_stream()) { |
+ fragment_ = streaming_flow_graph_builder_->BuildExpressionAt( |
+ expression->kernel_offset()); |
+ } else { |
+ expression->AcceptExpressionVisitor(this); |
+ } |
return fragment_; |
} |
@@ -4583,43 +4452,59 @@ ArgumentArray FlowGraphBuilder::GetArguments(int count) { |
} |
+#define STREAM_EXPRESSION_IF_POSSIBLE(node) \ |
+ if (node->can_stream()) { \ |
+ fragment_ = streaming_flow_graph_builder_->BuildExpressionAt( \ |
+ node->kernel_offset()); \ |
+ return; \ |
+ } |
+ |
+ |
void FlowGraphBuilder::VisitInvalidExpression(InvalidExpression* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitNullLiteral(NullLiteral* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitBoolLiteral(BoolLiteral* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitIntLiteral(IntLiteral* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitBigintLiteral(BigintLiteral* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitDoubleLiteral(DoubleLiteral* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitStringLiteral(StringLiteral* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitSymbolLiteral(SymbolLiteral* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
@@ -4922,8 +4807,9 @@ const Type& DartTypeTranslator::ReceiverType(const dart::Class& klass) { |
return type; |
} |
- |
void FlowGraphBuilder::VisitTypeLiteral(TypeLiteral* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
const AbstractType& type = T.TranslateType(node->type()); |
if (type.IsMalformed()) H.ReportError("Malformed type literal"); |
@@ -4948,11 +4834,14 @@ void FlowGraphBuilder::VisitTypeLiteral(TypeLiteral* node) { |
void FlowGraphBuilder::VisitVariableGet(VariableGet* node) { |
- fragment_ = LoadLocal(LookupVariable(node->variable())); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitVariableSet(VariableSet* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Fragment instructions = TranslateExpression(node->expression()); |
if (NeedsDebugStepCheck(stack_, node->position())) { |
instructions = DebugStepCheck(node->position()) + instructions; |
@@ -4965,10 +4854,8 @@ void FlowGraphBuilder::VisitVariableSet(VariableSet* node) { |
void FlowGraphBuilder::VisitStaticGet(StaticGet* node) { |
- if (node->kernel_offset() != -1) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
- return; |
- } |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
// A StaticGet will always have a kernel_offset, except for the StaticGet that |
// was manually created for _getMainClosure in dart:_builtin. Compile that |
// one specially here. |
@@ -4998,6 +4885,8 @@ void FlowGraphBuilder::VisitStaticGet(StaticGet* node) { |
void FlowGraphBuilder::VisitStaticSet(StaticSet* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
NameIndex target = node->target(); |
if (H.IsField(target)) { |
const dart::Field& field = |
@@ -5035,6 +4924,8 @@ void FlowGraphBuilder::VisitStaticSet(StaticSet* node) { |
void FlowGraphBuilder::VisitPropertyGet(PropertyGet* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Fragment instructions = TranslateExpression(node->receiver()); |
instructions += PushArgument(); |
const dart::String& getter_name = H.DartGetterName(node->name()); |
@@ -5044,6 +4935,8 @@ void FlowGraphBuilder::VisitPropertyGet(PropertyGet* node) { |
void FlowGraphBuilder::VisitPropertySet(PropertySet* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Fragment instructions(NullConstant()); |
LocalVariable* variable = MakeTemporary(); |
instructions += TranslateExpression(node->receiver()); |
@@ -5059,6 +4952,8 @@ void FlowGraphBuilder::VisitPropertySet(PropertySet* node) { |
void FlowGraphBuilder::VisitDirectPropertyGet(DirectPropertyGet* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Function& target = Function::ZoneHandle(Z); |
NameIndex kernel_name = node->target(); |
if (H.IsProcedure(kernel_name)) { |
@@ -5085,6 +4980,8 @@ void FlowGraphBuilder::VisitDirectPropertyGet(DirectPropertyGet* node) { |
void FlowGraphBuilder::VisitDirectPropertySet(DirectPropertySet* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
const dart::String& method_name = H.DartSetterName(node->target()); |
const Function& target = Function::ZoneHandle( |
Z, LookupMethodByMember(node->target(), method_name)); |
@@ -5104,6 +5001,8 @@ void FlowGraphBuilder::VisitDirectPropertySet(DirectPropertySet* node) { |
void FlowGraphBuilder::VisitStaticInvocation(StaticInvocation* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
const Function& target = Function::ZoneHandle( |
Z, H.LookupStaticMethodByKernelProcedure(node->procedure())); |
const dart::Class& klass = dart::Class::ZoneHandle(Z, target.Owner()); |
@@ -5223,6 +5122,8 @@ bool FlowGraphBuilder::RecognizeComparisonWithNull(Token::Kind token_kind, |
void FlowGraphBuilder::VisitMethodInvocation(MethodInvocation* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
const dart::String& name = H.DartMethodName(node->name()); |
const intptr_t argument_count = node->arguments()->count() + 1; |
const Token::Kind token_kind = MethodKind(name); |
@@ -5277,6 +5178,8 @@ void FlowGraphBuilder::VisitMethodInvocation(MethodInvocation* node) { |
void FlowGraphBuilder::VisitDirectMethodInvocation( |
DirectMethodInvocation* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
const dart::String& method_name = H.DartProcedureName(node->target()); |
const Token::Kind token_kind = MethodKind(method_name); |
@@ -5298,6 +5201,8 @@ void FlowGraphBuilder::VisitDirectMethodInvocation( |
void FlowGraphBuilder::VisitConstructorInvocation(ConstructorInvocation* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
if (node->is_const()) { |
fragment_ = |
Constant(constant_evaluator_.EvaluateConstructorInvocation(node)); |
@@ -5386,6 +5291,8 @@ void FlowGraphBuilder::VisitConstructorInvocation(ConstructorInvocation* node) { |
void FlowGraphBuilder::VisitIsExpression(IsExpression* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Fragment instructions = TranslateExpression(node->operand()); |
// The VM does not like an instanceOf call with a dynamic type. We need to |
@@ -5449,6 +5356,8 @@ void FlowGraphBuilder::VisitIsExpression(IsExpression* node) { |
void FlowGraphBuilder::VisitAsExpression(AsExpression* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Fragment instructions = TranslateExpression(node->operand()); |
// The VM does not like an Object_as call with a dynamic type. We need to |
@@ -5496,6 +5405,8 @@ void FlowGraphBuilder::VisitAsExpression(AsExpression* node) { |
void FlowGraphBuilder::VisitConditionalExpression(ConditionalExpression* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
bool negate; |
Fragment instructions = TranslateCondition(node->condition(), &negate); |
@@ -5528,6 +5439,8 @@ void FlowGraphBuilder::VisitConditionalExpression(ConditionalExpression* node) { |
void FlowGraphBuilder::VisitLogicalExpression(LogicalExpression* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
bool negate; |
Fragment instructions = TranslateCondition(node->left(), &negate); |
TargetEntryInstr* right_entry; |
@@ -5567,6 +5480,8 @@ void FlowGraphBuilder::VisitLogicalExpression(LogicalExpression* node) { |
void FlowGraphBuilder::VisitNot(Not* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Fragment instructions = TranslateExpression(node->expression()); |
instructions += CheckBooleanInCheckedMode(); |
instructions += BooleanNegate(); |
@@ -5575,11 +5490,14 @@ void FlowGraphBuilder::VisitNot(Not* node) { |
void FlowGraphBuilder::VisitThisExpression(ThisExpression* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitStringConcatenation(StringConcatenation* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
List<Expression>& expressions = node->expressions(); |
Fragment instructions; |
@@ -5609,6 +5527,8 @@ void FlowGraphBuilder::VisitStringConcatenation(StringConcatenation* node) { |
void FlowGraphBuilder::VisitListLiteral(ListLiteral* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
if (node->is_const()) { |
fragment_ = Constant(constant_evaluator_.EvaluateListLiteral(node)); |
return; |
@@ -5650,6 +5570,8 @@ void FlowGraphBuilder::VisitListLiteral(ListLiteral* node) { |
void FlowGraphBuilder::VisitMapLiteral(MapLiteral* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
if (node->is_const()) { |
fragment_ = Constant(constant_evaluator_.EvaluateMapLiteral(node)); |
return; |
@@ -5706,6 +5628,8 @@ void FlowGraphBuilder::VisitFunctionExpression(FunctionExpression* node) { |
void FlowGraphBuilder::VisitLet(Let* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Fragment instructions = TranslateStatement(node->variable()); |
instructions += TranslateExpression(node->body()); |
fragment_ = instructions; |
@@ -5713,6 +5637,8 @@ void FlowGraphBuilder::VisitLet(Let* node) { |
void FlowGraphBuilder::VisitThrow(Throw* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Fragment instructions; |
instructions += TranslateExpression(node->expression()); |
@@ -5728,7 +5654,8 @@ void FlowGraphBuilder::VisitThrow(Throw* node) { |
void FlowGraphBuilder::VisitRethrow(Rethrow* node) { |
- fragment_ = streaming_flow_graph_builder_->BuildAt(node->kernel_offset()); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
} |
@@ -5754,18 +5681,29 @@ Fragment FlowGraphBuilder::TranslateArguments(Arguments* node, |
return instructions; |
} |
+#define STREAM_STATEMENT_IF_POSSIBLE(node) \ |
+ if (node->can_stream()) { \ |
+ fragment_ = streaming_flow_graph_builder_->BuildStatementAt( \ |
+ node->kernel_offset()); \ |
+ return; \ |
+ } |
+ |
void FlowGraphBuilder::VisitInvalidStatement(InvalidStatement* node) { |
- H.ReportError("Invalid statements not implemented yet!"); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* node) { |
- fragment_ = Fragment(); |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitBlock(Block* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
Fragment instructions; |
instructions += EnterScope(node); |
@@ -5781,6 +5719,8 @@ void FlowGraphBuilder::VisitBlock(Block* node) { |
void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
bool inside_try_finally = try_finally_block_ != NULL; |
Fragment instructions = node->expression() == NULL |
@@ -5812,6 +5752,8 @@ void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* node) { |
void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
Fragment instructions = TranslateExpression(node->expression()); |
instructions += Drop(); |
fragment_ = instructions; |
@@ -5860,6 +5802,8 @@ void FlowGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* node) { |
void FlowGraphBuilder::VisitIfStatement(IfStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
bool negate; |
Fragment instructions = TranslateCondition(node->condition(), &negate); |
TargetEntryInstr* then_entry; |
@@ -5890,6 +5834,8 @@ void FlowGraphBuilder::VisitIfStatement(IfStatement* node) { |
void FlowGraphBuilder::VisitWhileStatement(WhileStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
++loop_depth_; |
bool negate; |
Fragment condition = TranslateCondition(node->condition(), &negate); |
@@ -5920,6 +5866,8 @@ void FlowGraphBuilder::VisitWhileStatement(WhileStatement* node) { |
void FlowGraphBuilder::VisitDoStatement(DoStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
++loop_depth_; |
Fragment body = TranslateStatement(node->body()); |
@@ -5948,6 +5896,8 @@ void FlowGraphBuilder::VisitDoStatement(DoStatement* node) { |
void FlowGraphBuilder::VisitForStatement(ForStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
Fragment declarations; |
bool new_context = false; |
@@ -6004,6 +5954,8 @@ void FlowGraphBuilder::VisitForStatement(ForStatement* node) { |
void FlowGraphBuilder::VisitForInStatement(ForInStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
Fragment instructions = TranslateExpression(node->iterable()); |
instructions += PushArgument(); |
@@ -6057,6 +6009,8 @@ void FlowGraphBuilder::VisitForInStatement(ForInStatement* node) { |
void FlowGraphBuilder::VisitLabeledStatement(LabeledStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
// There can be serveral cases: |
// |
// * the body contains a break |
@@ -6068,7 +6022,7 @@ void FlowGraphBuilder::VisitLabeledStatement(LabeledStatement* node) { |
// => We will only know which case we are in after the body has been |
// traversed. |
- BreakableBlock block(this, node); |
+ BreakableBlock block(this); |
Fragment instructions = TranslateStatement(node->body()); |
if (block.HadJumper()) { |
if (instructions.is_open()) { |
@@ -6082,26 +6036,15 @@ void FlowGraphBuilder::VisitLabeledStatement(LabeledStatement* node) { |
void FlowGraphBuilder::VisitBreakStatement(BreakStatement* node) { |
- TryFinallyBlock* outer_finally = NULL; |
- intptr_t target_context_depth = -1; |
- JoinEntryInstr* destination = breakable_block_->BreakDestination( |
- node->target(), &outer_finally, &target_context_depth); |
- |
- Fragment instructions; |
- instructions += |
- TranslateFinallyFinalizers(outer_finally, target_context_depth); |
- if (instructions.is_open()) { |
- if (NeedsDebugStepCheck(parsed_function_->function(), node->position())) { |
- instructions += DebugStepCheck(node->position()); |
- } |
- instructions += Goto(destination); |
- } |
- fragment_ = instructions; |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* node) { |
- SwitchBlock block(this, node); |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
+ SwitchBlock block(this, node->cases().length()); |
// Instead of using a variable we should reuse the expression on the stack, |
// since it won't be assigned again, we don't need phi nodes. |
@@ -6179,7 +6122,7 @@ void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* node) { |
// from `a == expr` and one from `a != expr && b == expr`). The |
// `block.Destination()` records the additional jump. |
if (switch_case->expressions().length() > 1) { |
- block.Destination(switch_case); |
+ block.DestinationDirect(i); |
} |
} |
@@ -6199,10 +6142,10 @@ void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* node) { |
constant_evaluator_.EvaluateExpression(switch_case->expressions()[k]); |
} |
- if (block.HadJumper(switch_case)) { |
+ if (block.HadJumper(i)) { |
// There are several branches to the body, so we will make a goto to |
// the join block (and prepend a join instruction to the real body). |
- JoinEntryInstr* join = block.Destination(switch_case); |
+ JoinEntryInstr* join = block.DestinationDirect(i); |
current_instructions += Goto(join); |
current_instructions = Fragment(current_instructions.entry, join); |
@@ -6212,8 +6155,8 @@ void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* node) { |
} |
} else { |
JoinEntryInstr* body_join = NULL; |
- if (block.HadJumper(switch_case)) { |
- body_join = block.Destination(switch_case); |
+ if (block.HadJumper(i)) { |
+ body_join = block.DestinationDirect(i); |
body_fragments[i] = Fragment(body_join) + body_fragments[i]; |
} |
@@ -6285,22 +6228,14 @@ void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* node) { |
void FlowGraphBuilder::VisitContinueSwitchStatement( |
ContinueSwitchStatement* node) { |
- TryFinallyBlock* outer_finally = NULL; |
- intptr_t target_context_depth = -1; |
- JoinEntryInstr* entry = switch_block_->Destination( |
- node->target(), &outer_finally, &target_context_depth); |
- |
- Fragment instructions; |
- instructions += |
- TranslateFinallyFinalizers(outer_finally, target_context_depth); |
- if (instructions.is_open()) { |
- instructions += Goto(entry); |
- } |
- fragment_ = instructions; |
+ fragment_ = |
+ streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset()); |
} |
void FlowGraphBuilder::VisitAssertStatement(AssertStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
if (!I->asserts()) { |
fragment_ = Fragment(); |
return; |
@@ -6376,6 +6311,8 @@ void FlowGraphBuilder::VisitAssertStatement(AssertStatement* node) { |
void FlowGraphBuilder::VisitTryFinally(TryFinally* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
InlineBailout("kernel::FlowgraphBuilder::VisitTryFinally"); |
// There are 5 different cases where we need to execute the finally block: |
@@ -6407,7 +6344,7 @@ void FlowGraphBuilder::VisitTryFinally(TryFinally* node) { |
// Fill in the body of the try. |
++try_depth_; |
{ |
- TryFinallyBlock tfb(this, node->finalizer()); |
+ TryFinallyBlock tfb(this, node->finalizer(), -1); |
TryCatchBlock tcb(this, try_handler_index); |
try_body += TranslateStatement(node->body()); |
} |
@@ -6450,6 +6387,8 @@ void FlowGraphBuilder::VisitTryFinally(TryFinally* node) { |
void FlowGraphBuilder::VisitTryCatch(class TryCatch* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
InlineBailout("kernel::FlowgraphBuilder::VisitTryCatch"); |
intptr_t try_handler_index = AllocateTryIndex(); |
@@ -6569,6 +6508,8 @@ void FlowGraphBuilder::VisitTryCatch(class TryCatch* node) { |
void FlowGraphBuilder::VisitYieldStatement(YieldStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
ASSERT(node->is_native()); // Must have been desugared. |
// Setup yield/continue point: |
// |