| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
| 9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 exit_collector_(exit_collector), | 251 exit_collector_(exit_collector), |
| 252 guarded_fields_(new(I) ZoneGrowableArray<const Field*>()), | 252 guarded_fields_(new(I) ZoneGrowableArray<const Field*>()), |
| 253 last_used_block_id_(0), // 0 is used for the graph entry. | 253 last_used_block_id_(0), // 0 is used for the graph entry. |
| 254 try_index_(CatchClauseNode::kInvalidTryIndex), | 254 try_index_(CatchClauseNode::kInvalidTryIndex), |
| 255 catch_try_index_(CatchClauseNode::kInvalidTryIndex), | 255 catch_try_index_(CatchClauseNode::kInvalidTryIndex), |
| 256 loop_depth_(0), | 256 loop_depth_(0), |
| 257 graph_entry_(NULL), | 257 graph_entry_(NULL), |
| 258 temp_count_(0), | 258 temp_count_(0), |
| 259 args_pushed_(0), | 259 args_pushed_(0), |
| 260 nesting_stack_(NULL), | 260 nesting_stack_(NULL), |
| 261 osr_id_(osr_id), | 261 osr_id_(osr_id) { } |
| 262 jump_cnt_(0), | |
| 263 await_joins_(new(I) ZoneGrowableArray<JoinEntryInstr*>()), | |
| 264 await_levels_(new(I) ZoneGrowableArray<intptr_t>()) { } | |
| 265 | 262 |
| 266 | 263 |
| 267 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { | 264 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { |
| 268 graph_entry_->AddCatchEntry(entry); | 265 graph_entry_->AddCatchEntry(entry); |
| 269 } | 266 } |
| 270 | 267 |
| 271 | 268 |
| 272 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { | 269 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { |
| 273 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); | 270 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); |
| 274 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id()); | 271 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id()); |
| (...skipping 813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1088 ASSERT(current_context_level >= 0); | 1085 ASSERT(current_context_level >= 0); |
| 1089 if (owner()->parsed_function()->saved_entry_context_var() != NULL) { | 1086 if (owner()->parsed_function()->saved_entry_context_var() != NULL) { |
| 1090 // CTX on entry was saved, but not linked as context parent. | 1087 // CTX on entry was saved, but not linked as context parent. |
| 1091 BuildRestoreContext(*owner()->parsed_function()->saved_entry_context_var()); | 1088 BuildRestoreContext(*owner()->parsed_function()->saved_entry_context_var()); |
| 1092 } else { | 1089 } else { |
| 1093 UnchainContexts(current_context_level); | 1090 UnchainContexts(current_context_level); |
| 1094 } | 1091 } |
| 1095 | 1092 |
| 1096 | 1093 |
| 1097 AddReturnExit(node->token_pos(), return_value); | 1094 AddReturnExit(node->token_pos(), return_value); |
| 1095 |
| 1096 if (function.is_async_closure() && |
| 1097 (node->return_type() == ReturnNode::kContinuationTarget)) { |
| 1098 JoinEntryInstr* const join = new(I) JoinEntryInstr( |
| 1099 owner()->AllocateBlockId(), owner()->try_index()); |
| 1100 owner()->await_joins().Add(join); |
| 1101 exit_ = join; |
| 1102 } |
| 1098 } | 1103 } |
| 1099 | 1104 |
| 1100 | 1105 |
| 1101 // <Expression> ::= Literal { literal: Instance } | 1106 // <Expression> ::= Literal { literal: Instance } |
| 1102 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 1107 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
| 1103 ReturnDefinition(new(I) ConstantInstr(node->literal())); | 1108 ReturnDefinition(new(I) ConstantInstr(node->literal())); |
| 1104 } | 1109 } |
| 1105 | 1110 |
| 1106 | 1111 |
| 1107 // Type nodes are used when a type is referenced as a literal. Type nodes | 1112 // Type nodes are used when a type is referenced as a literal. Type nodes |
| (...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2222 LocalVariable* jump_var = node->scope()->LookupVariable( | 2227 LocalVariable* jump_var = node->scope()->LookupVariable( |
| 2223 Symbols::AwaitJumpVar(), false); | 2228 Symbols::AwaitJumpVar(), false); |
| 2224 LocalVariable* ctx_var = node->scope()->LookupVariable( | 2229 LocalVariable* ctx_var = node->scope()->LookupVariable( |
| 2225 Symbols::AwaitContextVar(), false); | 2230 Symbols::AwaitContextVar(), false); |
| 2226 ASSERT((jump_var != NULL) && jump_var->is_captured()); | 2231 ASSERT((jump_var != NULL) && jump_var->is_captured()); |
| 2227 ASSERT((ctx_var != NULL) && ctx_var->is_captured()); | 2232 ASSERT((ctx_var != NULL) && ctx_var->is_captured()); |
| 2228 const intptr_t jump_cnt = owner()->next_await_counter(); | 2233 const intptr_t jump_cnt = owner()->next_await_counter(); |
| 2229 ASSERT(jump_cnt >= 0); | 2234 ASSERT(jump_cnt >= 0); |
| 2230 // Sanity check that we always add a JoinEntryInstr before adding a new | 2235 // Sanity check that we always add a JoinEntryInstr before adding a new |
| 2231 // state. | 2236 // state. |
| 2232 ASSERT(jump_cnt == owner()->await_joins()->length()); | 2237 ASSERT(jump_cnt == owner()->await_joins().length()); |
| 2233 // Store the counter in :await_jump_var. | 2238 // Store the counter in :await_jump_var. |
| 2234 Value* jump_val = Bind(new (I) ConstantInstr( | 2239 Value* jump_val = Bind(new (I) ConstantInstr( |
| 2235 Smi::ZoneHandle(I, Smi::New(jump_cnt)))); | 2240 Smi::ZoneHandle(I, Smi::New(jump_cnt)))); |
| 2236 Do(BuildStoreLocal(*jump_var, jump_val)); | 2241 Do(BuildStoreLocal(*jump_var, jump_val)); |
| 2237 // Save the current context for resuming. | 2242 // Save the current context for resuming. |
| 2238 BuildSaveContext(*ctx_var); | 2243 BuildSaveContext(*ctx_var); |
| 2239 owner()->await_levels()->Add(owner()->context_level()); | 2244 owner()->await_levels().Add(owner()->context_level()); |
| 2240 return; | 2245 return; |
| 2241 } | 2246 } |
| 2242 if (node->marker_type() == AwaitMarkerNode::kTargetForContinuation) { | 2247 if (node->marker_type() == AwaitMarkerNode::kTargetForContinuation) { |
| 2243 // We need to create a new await target which involves: | 2248 UNREACHABLE(); //XXX |
| 2244 // * Append a join that is also added to the list that will later result in | |
| 2245 // a preamble. | |
| 2246 JoinEntryInstr* const join = new(I) JoinEntryInstr( | |
| 2247 owner()->AllocateBlockId(), owner()->try_index()); | |
| 2248 owner()->await_joins()->Add(join); | |
| 2249 Goto(join); | |
| 2250 exit_ = join; | |
| 2251 return; | |
| 2252 } | 2249 } |
| 2253 UNREACHABLE(); | 2250 UNREACHABLE(); |
| 2254 } | 2251 } |
| 2255 | 2252 |
| 2256 | 2253 |
| 2257 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { | 2254 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { |
| 2258 return kFirstLocalSlotFromFp | 2255 return kFirstLocalSlotFromFp |
| 2259 - owner()->num_stack_locals() | 2256 - owner()->num_stack_locals() |
| 2260 - owner()->num_copied_params() | 2257 - owner()->num_copied_params() |
| 2261 - owner()->args_pushed() | 2258 - owner()->args_pushed() |
| (...skipping 1612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3874 ASSERT(jump_var != NULL && jump_var->is_captured()); | 3871 ASSERT(jump_var != NULL && jump_var->is_captured()); |
| 3875 | 3872 |
| 3876 Instruction* saved_entry = entry_; | 3873 Instruction* saved_entry = entry_; |
| 3877 Instruction* saved_exit = exit_; | 3874 Instruction* saved_exit = exit_; |
| 3878 entry_ = NULL; | 3875 entry_ = NULL; |
| 3879 exit_ = NULL; | 3876 exit_ = NULL; |
| 3880 | 3877 |
| 3881 LoadLocalNode* load_jump_cnt = new(I) LoadLocalNode( | 3878 LoadLocalNode* load_jump_cnt = new(I) LoadLocalNode( |
| 3882 Scanner::kNoSourcePos, jump_var); | 3879 Scanner::kNoSourcePos, jump_var); |
| 3883 ComparisonNode* check_jump_cnt; | 3880 ComparisonNode* check_jump_cnt; |
| 3884 const intptr_t num_await_states = owner()->await_joins()->length(); | 3881 const intptr_t num_await_states = owner()->await_joins().length(); |
| 3885 for (intptr_t i = 0; i < num_await_states; i++) { | 3882 for (intptr_t i = 0; i < num_await_states; i++) { |
| 3886 check_jump_cnt = new(I) ComparisonNode( | 3883 check_jump_cnt = new(I) ComparisonNode( |
| 3887 Scanner::kNoSourcePos, | 3884 Scanner::kNoSourcePos, |
| 3888 Token::kEQ, | 3885 Token::kEQ, |
| 3889 load_jump_cnt, | 3886 load_jump_cnt, |
| 3890 new(I) LiteralNode( | 3887 new(I) LiteralNode( |
| 3891 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i)))); | 3888 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i)))); |
| 3892 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos); | 3889 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos); |
| 3893 check_jump_cnt->Visit(&for_test); | 3890 check_jump_cnt->Visit(&for_test); |
| 3894 EffectGraphVisitor for_true(owner()); | 3891 EffectGraphVisitor for_true(owner()); |
| 3895 EffectGraphVisitor for_false(owner()); | 3892 EffectGraphVisitor for_false(owner()); |
| 3896 | 3893 |
| 3897 for_true.BuildAwaitJump(top_scope, | 3894 for_true.BuildAwaitJump(top_scope, |
| 3898 (*owner()->await_levels())[i], | 3895 owner()->await_levels()[i], |
| 3899 (*owner()->await_joins())[i]); | 3896 owner()->await_joins()[i]); |
| 3900 Join(for_test, for_true, for_false); | 3897 Join(for_test, for_true, for_false); |
| 3901 | 3898 |
| 3902 if (i == 0) { | 3899 if (i == 0) { |
| 3903 // Manually link up the preamble start. | 3900 // Manually link up the preamble start. |
| 3904 preamble_start->previous()->set_next(for_test.entry()); | 3901 preamble_start->previous()->set_next(for_test.entry()); |
| 3905 for_test.entry()->set_previous(preamble_start->previous()); | 3902 for_test.entry()->set_previous(preamble_start->previous()); |
| 3906 } | 3903 } |
| 3907 if (i == (num_await_states - 1)) { | 3904 if (i == (num_await_states - 1)) { |
| 3908 // Link up preamble end. | 3905 // Link up preamble end. |
| 3909 if (exit_ == NULL) { | 3906 if (exit_ == NULL) { |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4285 Report::MessageF(Report::kBailout, | 4282 Report::MessageF(Report::kBailout, |
| 4286 Script::Handle(function.script()), | 4283 Script::Handle(function.script()), |
| 4287 function.token_pos(), | 4284 function.token_pos(), |
| 4288 "FlowGraphBuilder Bailout: %s %s", | 4285 "FlowGraphBuilder Bailout: %s %s", |
| 4289 String::Handle(function.name()).ToCString(), | 4286 String::Handle(function.name()).ToCString(), |
| 4290 reason); | 4287 reason); |
| 4291 UNREACHABLE(); | 4288 UNREACHABLE(); |
| 4292 } | 4289 } |
| 4293 | 4290 |
| 4294 } // namespace dart | 4291 } // namespace dart |
| OLD | NEW |