Index: runtime/vm/kernel_to_il.cc |
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc |
index 35062e9e32436f17ae4292dae9320c81afe582e0..a9406e50384e3c219f2846045d3d961c6a61aa1e 100644 |
--- a/runtime/vm/kernel_to_il.cc |
+++ b/runtime/vm/kernel_to_il.cc |
@@ -815,186 +815,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; |
@@ -2251,11 +2071,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. |
@@ -2279,9 +2105,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(); |
@@ -2294,9 +2126,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(); |
} |
@@ -3174,6 +3011,13 @@ dart::LocalVariable* FlowGraphBuilder::LookupVariable( |
} |
+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); |
@@ -3969,6 +3813,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) { |
@@ -4523,7 +4379,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->cannot_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_; |
} |
@@ -4544,7 +4408,12 @@ Fragment FlowGraphBuilder::TranslateCondition(Expression* expression, |
Fragment FlowGraphBuilder::TranslateExpression(Expression* expression) { |
- expression->AcceptExpressionVisitor(this); |
+ if (!expression->cannot_stream()) { |
+ fragment_ = streaming_flow_graph_builder_->BuildExpressionAt( |
+ expression->kernel_offset()); |
+ } else { |
+ expression->AcceptExpressionVisitor(this); |
+ } |
return fragment_; |
} |
@@ -4565,43 +4434,59 @@ ArgumentArray FlowGraphBuilder::GetArguments(int count) { |
} |
+#define STREAM_EXPRESSION_IF_POSSIBLE(node) \ |
+ if (!node->cannot_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()); |
} |
@@ -4900,8 +4785,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"); |
@@ -4926,11 +4812,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; |
@@ -4943,10 +4832,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. |
@@ -4976,6 +4863,8 @@ void FlowGraphBuilder::VisitStaticGet(StaticGet* node) { |
void FlowGraphBuilder::VisitStaticSet(StaticSet* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
CanonicalName* target = node->target(); |
if (H.IsField(target)) { |
const dart::Field& field = |
@@ -5013,6 +4902,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()); |
@@ -5022,6 +4913,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()); |
@@ -5037,6 +4930,8 @@ void FlowGraphBuilder::VisitPropertySet(PropertySet* node) { |
void FlowGraphBuilder::VisitDirectPropertyGet(DirectPropertyGet* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Function& target = Function::ZoneHandle(Z); |
CanonicalName* kernel_name = node->target(); |
if (H.IsProcedure(kernel_name)) { |
@@ -5063,6 +4958,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)); |
@@ -5082,6 +4979,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()); |
@@ -5201,6 +5100,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); |
@@ -5255,6 +5156,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); |
@@ -5276,6 +5179,8 @@ void FlowGraphBuilder::VisitDirectMethodInvocation( |
void FlowGraphBuilder::VisitConstructorInvocation(ConstructorInvocation* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
if (node->is_const()) { |
fragment_ = |
Constant(constant_evaluator_.EvaluateConstructorInvocation(node)); |
@@ -5364,6 +5269,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 |
@@ -5427,6 +5334,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 |
@@ -5474,6 +5383,8 @@ void FlowGraphBuilder::VisitAsExpression(AsExpression* node) { |
void FlowGraphBuilder::VisitConditionalExpression(ConditionalExpression* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
bool negate; |
Fragment instructions = TranslateCondition(node->condition(), &negate); |
@@ -5506,6 +5417,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; |
@@ -5545,6 +5458,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(); |
@@ -5553,11 +5468,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; |
@@ -5587,6 +5505,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; |
@@ -5628,6 +5548,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; |
@@ -5684,6 +5606,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; |
@@ -5691,6 +5615,8 @@ void FlowGraphBuilder::VisitLet(Let* node) { |
void FlowGraphBuilder::VisitThrow(Throw* node) { |
+ STREAM_EXPRESSION_IF_POSSIBLE(node); |
+ |
Fragment instructions; |
instructions += TranslateExpression(node->expression()); |
@@ -5706,7 +5632,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()); |
} |
@@ -5732,18 +5659,29 @@ Fragment FlowGraphBuilder::TranslateArguments(Arguments* node, |
return instructions; |
} |
+#define STREAM_STATEMENT_IF_POSSIBLE(node) \ |
+ if (!node->cannot_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); |
@@ -5759,6 +5697,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 |
@@ -5790,6 +5730,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; |
@@ -5838,6 +5780,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; |
@@ -5868,6 +5812,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); |
@@ -5898,6 +5844,8 @@ void FlowGraphBuilder::VisitWhileStatement(WhileStatement* node) { |
void FlowGraphBuilder::VisitDoStatement(DoStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
++loop_depth_; |
Fragment body = TranslateStatement(node->body()); |
@@ -5926,6 +5874,8 @@ void FlowGraphBuilder::VisitDoStatement(DoStatement* node) { |
void FlowGraphBuilder::VisitForStatement(ForStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
Fragment declarations; |
bool new_context = false; |
@@ -5982,6 +5932,8 @@ void FlowGraphBuilder::VisitForStatement(ForStatement* node) { |
void FlowGraphBuilder::VisitForInStatement(ForInStatement* node) { |
+ STREAM_STATEMENT_IF_POSSIBLE(node); |
+ |
Fragment instructions = TranslateExpression(node->iterable()); |
instructions += PushArgument(); |
@@ -6035,6 +5987,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 |
@@ -6046,7 +6000,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()) { |
@@ -6060,26 +6014,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. |
@@ -6157,7 +6100,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); |
} |
} |
@@ -6177,10 +6120,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); |
@@ -6190,8 +6133,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]; |
} |
@@ -6263,22 +6206,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; |
@@ -6354,6 +6289,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: |
@@ -6385,7 +6322,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()); |
} |
@@ -6428,6 +6365,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(); |
@@ -6547,6 +6486,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: |
// |