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 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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), | 262 jump_count_(0), |
263 await_joins_(new(I) ZoneGrowableArray<JoinEntryInstr*>()), | 263 await_joins_(new(I) ZoneGrowableArray<JoinEntryInstr*>()), |
264 await_levels_(new(I) ZoneGrowableArray<intptr_t>()) { } | 264 await_levels_(new(I) ZoneGrowableArray<intptr_t>()) { } |
265 | 265 |
266 | 266 |
267 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { | 267 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { |
268 graph_entry_->AddCatchEntry(entry); | 268 graph_entry_->AddCatchEntry(entry); |
269 } | 269 } |
270 | 270 |
271 | 271 |
272 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { | 272 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { |
(...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1088 ASSERT(current_context_level >= 0); | 1088 ASSERT(current_context_level >= 0); |
1089 if (owner()->parsed_function()->saved_entry_context_var() != NULL) { | 1089 if (owner()->parsed_function()->saved_entry_context_var() != NULL) { |
1090 // CTX on entry was saved, but not linked as context parent. | 1090 // CTX on entry was saved, but not linked as context parent. |
1091 BuildRestoreContext(*owner()->parsed_function()->saved_entry_context_var()); | 1091 BuildRestoreContext(*owner()->parsed_function()->saved_entry_context_var()); |
1092 } else { | 1092 } else { |
1093 UnchainContexts(current_context_level); | 1093 UnchainContexts(current_context_level); |
1094 } | 1094 } |
1095 | 1095 |
1096 | 1096 |
1097 AddReturnExit(node->token_pos(), return_value); | 1097 AddReturnExit(node->token_pos(), return_value); |
| 1098 |
| 1099 if (function.is_async_closure() && |
| 1100 (node->return_type() == ReturnNode::kContinuationTarget)) { |
| 1101 JoinEntryInstr* const join = new(I) JoinEntryInstr( |
| 1102 owner()->AllocateBlockId(), owner()->try_index()); |
| 1103 owner()->await_joins()->Add(join); |
| 1104 exit_ = join; |
| 1105 } |
1098 } | 1106 } |
1099 | 1107 |
1100 | 1108 |
1101 // <Expression> ::= Literal { literal: Instance } | 1109 // <Expression> ::= Literal { literal: Instance } |
1102 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 1110 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
1103 ReturnDefinition(new(I) ConstantInstr(node->literal())); | 1111 ReturnDefinition(new(I) ConstantInstr(node->literal())); |
1104 } | 1112 } |
1105 | 1113 |
1106 | 1114 |
1107 // Type nodes are used when a type is referenced as a literal. Type nodes | 1115 // Type nodes are used when a type is referenced as a literal. Type nodes |
(...skipping 1099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2207 } | 2215 } |
2208 | 2216 |
2209 | 2217 |
2210 void EffectGraphVisitor::VisitAwaitNode(AwaitNode* node) { | 2218 void EffectGraphVisitor::VisitAwaitNode(AwaitNode* node) { |
2211 // Await nodes are temporary during parsing. | 2219 // Await nodes are temporary during parsing. |
2212 UNREACHABLE(); | 2220 UNREACHABLE(); |
2213 } | 2221 } |
2214 | 2222 |
2215 | 2223 |
2216 void EffectGraphVisitor::VisitAwaitMarkerNode(AwaitMarkerNode* node) { | 2224 void EffectGraphVisitor::VisitAwaitMarkerNode(AwaitMarkerNode* node) { |
2217 if (node->marker_type() == AwaitMarkerNode::kNewContinuationState) { | 2225 // We need to create a new await state which involves: |
2218 // We need to create a new await state which involves: | 2226 // * Increase the jump counter. Sanity check against the list of targets. |
2219 // * Increase the jump counter. Sanity check against the list of targets. | 2227 // * Save the current context for resuming. |
2220 // * Save the current context for resuming. | 2228 ASSERT(node->scope() != NULL); |
2221 ASSERT(node->scope() != NULL); | 2229 LocalVariable* jump_var = node->scope()->LookupVariable( |
2222 LocalVariable* jump_var = node->scope()->LookupVariable( | 2230 Symbols::AwaitJumpVar(), false); |
2223 Symbols::AwaitJumpVar(), false); | 2231 LocalVariable* ctx_var = node->scope()->LookupVariable( |
2224 LocalVariable* ctx_var = node->scope()->LookupVariable( | 2232 Symbols::AwaitContextVar(), false); |
2225 Symbols::AwaitContextVar(), false); | 2233 ASSERT((jump_var != NULL) && jump_var->is_captured()); |
2226 ASSERT((jump_var != NULL) && jump_var->is_captured()); | 2234 ASSERT((ctx_var != NULL) && ctx_var->is_captured()); |
2227 ASSERT((ctx_var != NULL) && ctx_var->is_captured()); | 2235 const intptr_t jump_count = owner()->next_await_counter(); |
2228 const intptr_t jump_cnt = owner()->next_await_counter(); | 2236 ASSERT(jump_count >= 0); |
2229 ASSERT(jump_cnt >= 0); | 2237 // Sanity check that we always add a JoinEntryInstr before adding a new |
2230 // Sanity check that we always add a JoinEntryInstr before adding a new | 2238 // state. |
2231 // state. | 2239 ASSERT(jump_count == owner()->await_joins()->length()); |
2232 ASSERT(jump_cnt == owner()->await_joins()->length()); | 2240 // Store the counter in :await_jump_var. |
2233 // Store the counter in :await_jump_var. | 2241 Value* jump_val = Bind(new (I) ConstantInstr( |
2234 Value* jump_val = Bind(new (I) ConstantInstr( | 2242 Smi::ZoneHandle(I, Smi::New(jump_count)))); |
2235 Smi::ZoneHandle(I, Smi::New(jump_cnt)))); | 2243 Do(BuildStoreLocal(*jump_var, jump_val)); |
2236 Do(BuildStoreLocal(*jump_var, jump_val)); | 2244 // Save the current context for resuming. |
2237 // Save the current context for resuming. | 2245 BuildSaveContext(*ctx_var); |
2238 BuildSaveContext(*ctx_var); | 2246 owner()->await_levels()->Add(owner()->context_level()); |
2239 owner()->await_levels()->Add(owner()->context_level()); | |
2240 return; | |
2241 } | |
2242 if (node->marker_type() == AwaitMarkerNode::kTargetForContinuation) { | |
2243 // We need to create a new await target which involves: | |
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 } | |
2253 UNREACHABLE(); | |
2254 } | 2247 } |
2255 | 2248 |
2256 | 2249 |
2257 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { | 2250 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { |
2258 return kFirstLocalSlotFromFp | 2251 return kFirstLocalSlotFromFp |
2259 - owner()->num_stack_locals() | 2252 - owner()->num_stack_locals() |
2260 - owner()->num_copied_params() | 2253 - owner()->num_copied_params() |
2261 - owner()->args_pushed() | 2254 - owner()->args_pushed() |
2262 - owner()->temp_count() + 1; | 2255 - owner()->temp_count() + 1; |
2263 } | 2256 } |
(...skipping 1613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3877 LocalScope* top_scope = node->scope(); | 3870 LocalScope* top_scope = node->scope(); |
3878 LocalVariable* jump_var = top_scope->LookupVariable( | 3871 LocalVariable* jump_var = top_scope->LookupVariable( |
3879 Symbols::AwaitJumpVar(), false); | 3872 Symbols::AwaitJumpVar(), false); |
3880 ASSERT(jump_var != NULL && jump_var->is_captured()); | 3873 ASSERT(jump_var != NULL && jump_var->is_captured()); |
3881 | 3874 |
3882 Instruction* saved_entry = entry_; | 3875 Instruction* saved_entry = entry_; |
3883 Instruction* saved_exit = exit_; | 3876 Instruction* saved_exit = exit_; |
3884 entry_ = NULL; | 3877 entry_ = NULL; |
3885 exit_ = NULL; | 3878 exit_ = NULL; |
3886 | 3879 |
3887 LoadLocalNode* load_jump_cnt = new(I) LoadLocalNode( | 3880 LoadLocalNode* load_jump_count = new(I) LoadLocalNode( |
3888 Scanner::kNoSourcePos, jump_var); | 3881 Scanner::kNoSourcePos, jump_var); |
3889 ComparisonNode* check_jump_cnt; | 3882 ComparisonNode* check_jump_count; |
3890 const intptr_t num_await_states = owner()->await_joins()->length(); | 3883 const intptr_t num_await_states = owner()->await_joins()->length(); |
3891 for (intptr_t i = 0; i < num_await_states; i++) { | 3884 for (intptr_t i = 0; i < num_await_states; i++) { |
3892 check_jump_cnt = new(I) ComparisonNode( | 3885 check_jump_count = new(I) ComparisonNode( |
3893 Scanner::kNoSourcePos, | 3886 Scanner::kNoSourcePos, |
3894 Token::kEQ, | 3887 Token::kEQ, |
3895 load_jump_cnt, | 3888 load_jump_count, |
3896 new(I) LiteralNode( | 3889 new(I) LiteralNode( |
3897 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i)))); | 3890 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i)))); |
3898 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos); | 3891 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos); |
3899 check_jump_cnt->Visit(&for_test); | 3892 check_jump_count->Visit(&for_test); |
3900 EffectGraphVisitor for_true(owner()); | 3893 EffectGraphVisitor for_true(owner()); |
3901 EffectGraphVisitor for_false(owner()); | 3894 EffectGraphVisitor for_false(owner()); |
3902 | 3895 |
3903 for_true.BuildAwaitJump(top_scope, | 3896 for_true.BuildAwaitJump(top_scope, |
3904 (*owner()->await_levels())[i], | 3897 (*owner()->await_levels())[i], |
3905 (*owner()->await_joins())[i]); | 3898 (*owner()->await_joins())[i]); |
3906 Join(for_test, for_true, for_false); | 3899 Join(for_test, for_true, for_false); |
3907 | 3900 |
3908 if (i == 0) { | 3901 if (i == 0) { |
3909 // Manually link up the preamble start. | 3902 // Manually link up the preamble start. |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4291 Report::MessageF(Report::kBailout, | 4284 Report::MessageF(Report::kBailout, |
4292 Script::Handle(function.script()), | 4285 Script::Handle(function.script()), |
4293 function.token_pos(), | 4286 function.token_pos(), |
4294 "FlowGraphBuilder Bailout: %s %s", | 4287 "FlowGraphBuilder Bailout: %s %s", |
4295 String::Handle(function.name()).ToCString(), | 4288 String::Handle(function.name()).ToCString(), |
4296 reason); | 4289 reason); |
4297 UNREACHABLE(); | 4290 UNREACHABLE(); |
4298 } | 4291 } |
4299 | 4292 |
4300 } // namespace dart | 4293 } // namespace dart |
OLD | NEW |