| 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 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1104 } | 1104 } |
| 1105 | 1105 |
| 1106 intptr_t current_context_level = owner()->context_level(); | 1106 intptr_t current_context_level = owner()->context_level(); |
| 1107 ASSERT(current_context_level >= 0); | 1107 ASSERT(current_context_level >= 0); |
| 1108 if (HasContextScope()) { | 1108 if (HasContextScope()) { |
| 1109 UnchainContexts(current_context_level); | 1109 UnchainContexts(current_context_level); |
| 1110 } | 1110 } |
| 1111 | 1111 |
| 1112 AddReturnExit(node->token_pos(), return_value); | 1112 AddReturnExit(node->token_pos(), return_value); |
| 1113 | 1113 |
| 1114 if ((function.IsAsyncClosure() || function.IsSyncGenClosure()) && | 1114 if ((function.IsAsyncClosure() || |
| 1115 function.IsSyncGenClosure() || |
| 1116 function.IsAsyncGenClosure()) && |
| 1115 (node->return_type() == ReturnNode::kContinuationTarget)) { | 1117 (node->return_type() == ReturnNode::kContinuationTarget)) { |
| 1116 JoinEntryInstr* const join = new(I) JoinEntryInstr( | 1118 JoinEntryInstr* const join = new(I) JoinEntryInstr( |
| 1117 owner()->AllocateBlockId(), owner()->try_index()); | 1119 owner()->AllocateBlockId(), owner()->try_index()); |
| 1118 owner()->await_joins()->Add(join); | 1120 owner()->await_joins()->Add(join); |
| 1119 exit_ = join; | 1121 exit_ = join; |
| 1120 } | 1122 } |
| 1121 } | 1123 } |
| 1122 | 1124 |
| 1123 | 1125 |
| 1124 // <Expression> ::= Literal { literal: Instance } | 1126 // <Expression> ::= Literal { literal: Instance } |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1476 return new(I) AssertAssignableInstr(token_pos, | 1478 return new(I) AssertAssignableInstr(token_pos, |
| 1477 value, | 1479 value, |
| 1478 instantiator, | 1480 instantiator, |
| 1479 instantiator_type_arguments, | 1481 instantiator_type_arguments, |
| 1480 dst_type, | 1482 dst_type, |
| 1481 dst_name, | 1483 dst_name, |
| 1482 deopt_id); | 1484 deopt_id); |
| 1483 } | 1485 } |
| 1484 | 1486 |
| 1485 | 1487 |
| 1486 void EffectGraphVisitor::BuildYieldJump(LocalVariable* old_context, | 1488 void EffectGraphVisitor::BuildSyncYieldJump(LocalVariable* old_context, |
| 1487 LocalVariable* iterator_param, | 1489 LocalVariable* iterator_param, |
| 1488 const intptr_t old_ctx_level, | 1490 const intptr_t old_ctx_level, |
| 1489 JoinEntryInstr* target) { | 1491 JoinEntryInstr* target) { |
| 1490 // Building a jump consists of the following actions: | 1492 // Building a jump consists of the following actions: |
| 1491 // * Load the generator body's iterator parameter (:iterator) | 1493 // * Load the generator body's iterator parameter (:iterator) |
| 1492 // from the current context into a temporary. | 1494 // from the current context into a temporary. |
| 1493 // * Restore the old context from :await_cxt_var. | 1495 // * Restore the old context from :await_cxt_var. |
| 1494 // * Copy the iterator saved above into the restored context. | 1496 // * Copy the iterator saved above into the restored context. |
| 1495 // * Append a Goto to the target's join. | 1497 // * Append a Goto to the target's join. |
| 1496 ASSERT((iterator_param != NULL) && iterator_param->is_captured()); | 1498 ASSERT((iterator_param != NULL) && iterator_param->is_captured()); |
| 1497 ASSERT((old_context != NULL) && old_context->is_captured()); | 1499 ASSERT((old_context != NULL) && old_context->is_captured()); |
| 1498 // Before restoring the context we need to temporarily save the | 1500 // Before restoring the context we need to temporarily save the |
| 1499 // iterator parameter. | 1501 // iterator parameter. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1532 Do(store); | 1534 Do(store); |
| 1533 | 1535 |
| 1534 Do(ExitTempLocalScope(temp_context_var)); | 1536 Do(ExitTempLocalScope(temp_context_var)); |
| 1535 Do(ExitTempLocalScope(temp_iterator_var)); | 1537 Do(ExitTempLocalScope(temp_iterator_var)); |
| 1536 | 1538 |
| 1537 // Goto saved join. | 1539 // Goto saved join. |
| 1538 Goto(target); | 1540 Goto(target); |
| 1539 } | 1541 } |
| 1540 | 1542 |
| 1541 | 1543 |
| 1542 void EffectGraphVisitor::BuildAwaitJump(LocalVariable* old_context, | 1544 void EffectGraphVisitor::BuildAsyncJump(LocalVariable* old_context, |
| 1543 LocalVariable* continuation_result, | 1545 LocalVariable* continuation_result, |
| 1544 LocalVariable* continuation_error, | 1546 LocalVariable* continuation_error, |
| 1545 LocalVariable* continuation_stack_trace, | 1547 LocalVariable* continuation_stack_trace, |
| 1546 const intptr_t old_ctx_level, | 1548 const intptr_t old_ctx_level, |
| 1547 JoinEntryInstr* target) { | 1549 JoinEntryInstr* target) { |
| 1548 // Building a jump consists of the following actions: | 1550 // Building a jump consists of the following actions: |
| 1549 // * Load the current continuation result parameter (:async_result) | 1551 // * Load the current continuation result parameter (:async_result) |
| 1550 // and continuation error parameter (:async_error_param) from | 1552 // and continuation error parameter (:async_error_param) from |
| 1551 // the current context into temporaries. | 1553 // the current context into temporaries. |
| 1552 // * Restore the old context from :await_cxt_var. | 1554 // * Restore the old context from :await_cxt_var. |
| (...skipping 2322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3875 pos++; | 3877 pos++; |
| 3876 } | 3878 } |
| 3877 } | 3879 } |
| 3878 | 3880 |
| 3879 // Continuation part: | 3881 // Continuation part: |
| 3880 // If this node sequence is the body of a function with continuations, | 3882 // If this node sequence is the body of a function with continuations, |
| 3881 // leave room for a preamble. | 3883 // leave room for a preamble. |
| 3882 // The preamble is generated after visiting the body. | 3884 // The preamble is generated after visiting the body. |
| 3883 GotoInstr* preamble_start = NULL; | 3885 GotoInstr* preamble_start = NULL; |
| 3884 if (is_top_level_sequence && | 3886 if (is_top_level_sequence && |
| 3885 (function.IsAsyncClosure() || function.IsSyncGenClosure())) { | 3887 (function.IsAsyncClosure() || |
| 3888 function.IsSyncGenClosure() || |
| 3889 function.IsAsyncGenClosure())) { |
| 3886 JoinEntryInstr* preamble_end = new(I) JoinEntryInstr( | 3890 JoinEntryInstr* preamble_end = new(I) JoinEntryInstr( |
| 3887 owner()->AllocateBlockId(), owner()->try_index()); | 3891 owner()->AllocateBlockId(), owner()->try_index()); |
| 3888 ASSERT(exit() != NULL); | 3892 ASSERT(exit() != NULL); |
| 3889 exit()->Goto(preamble_end); | 3893 exit()->Goto(preamble_end); |
| 3890 ASSERT(exit()->next()->IsGoto()); | 3894 ASSERT(exit()->next()->IsGoto()); |
| 3891 preamble_start = exit()->next()->AsGoto(); | 3895 preamble_start = exit()->next()->AsGoto(); |
| 3892 ASSERT(preamble_start->IsGoto()); | 3896 ASSERT(preamble_start->IsGoto()); |
| 3893 exit_ = preamble_end; | 3897 exit_ = preamble_end; |
| 3894 } | 3898 } |
| 3895 | 3899 |
| 3896 intptr_t i = 0; | 3900 intptr_t i = 0; |
| 3897 while (is_open() && (i < node->length())) { | 3901 while (is_open() && (i < node->length())) { |
| 3898 EffectGraphVisitor for_effect(owner()); | 3902 EffectGraphVisitor for_effect(owner()); |
| 3899 node->NodeAt(i++)->Visit(&for_effect); | 3903 node->NodeAt(i++)->Visit(&for_effect); |
| 3900 Append(for_effect); | 3904 Append(for_effect); |
| 3901 if (!is_open()) { | 3905 if (!is_open()) { |
| 3902 // E.g., because of a JumpNode. | 3906 // E.g., because of a JumpNode. |
| 3903 break; | 3907 break; |
| 3904 } | 3908 } |
| 3905 } | 3909 } |
| 3906 | 3910 |
| 3907 // Continuation part: | 3911 // Continuation part: |
| 3908 // After generating the CFG for the body we can create the preamble | 3912 // After generating the CFG for the body we can create the preamble |
| 3909 // because we know exactly how many continuation states we need. | 3913 // because we know exactly how many continuation states we need. |
| 3910 if (is_top_level_sequence && | 3914 if (is_top_level_sequence && |
| 3911 (function.IsAsyncClosure() || function.IsSyncGenClosure())) { | 3915 (function.IsAsyncClosure() || |
| 3916 function.IsSyncGenClosure() || |
| 3917 function.IsAsyncGenClosure())) { |
| 3912 ASSERT(preamble_start != NULL); | 3918 ASSERT(preamble_start != NULL); |
| 3913 // We are at the top level. Fetch the corresponding scope. | 3919 // We are at the top level. Fetch the corresponding scope. |
| 3914 LocalScope* top_scope = node->scope(); | 3920 LocalScope* top_scope = node->scope(); |
| 3915 LocalVariable* jump_var = top_scope->LookupVariable( | 3921 LocalVariable* jump_var = top_scope->LookupVariable( |
| 3916 Symbols::AwaitJumpVar(), false); | 3922 Symbols::AwaitJumpVar(), false); |
| 3917 ASSERT(jump_var != NULL && jump_var->is_captured()); | 3923 ASSERT(jump_var != NULL && jump_var->is_captured()); |
| 3918 Instruction* saved_entry = entry_; | 3924 Instruction* saved_entry = entry_; |
| 3919 Instruction* saved_exit = exit_; | 3925 Instruction* saved_exit = exit_; |
| 3920 entry_ = NULL; | 3926 entry_ = NULL; |
| 3921 exit_ = NULL; | 3927 exit_ = NULL; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3932 Scanner::kNoSourcePos, | 3938 Scanner::kNoSourcePos, |
| 3933 Token::kEQ, | 3939 Token::kEQ, |
| 3934 load_jump_count, | 3940 load_jump_count, |
| 3935 new(I) LiteralNode( | 3941 new(I) LiteralNode( |
| 3936 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i)))); | 3942 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i)))); |
| 3937 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos); | 3943 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos); |
| 3938 check_jump_count->Visit(&for_test); | 3944 check_jump_count->Visit(&for_test); |
| 3939 EffectGraphVisitor for_true(owner()); | 3945 EffectGraphVisitor for_true(owner()); |
| 3940 EffectGraphVisitor for_false(owner()); | 3946 EffectGraphVisitor for_false(owner()); |
| 3941 | 3947 |
| 3942 if (function.IsAsyncClosure()) { | 3948 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) { |
| 3943 LocalVariable* result_param = | 3949 LocalVariable* result_param = |
| 3944 top_scope->LookupVariable(Symbols::AsyncOperationParam(), false); | 3950 top_scope->LookupVariable(Symbols::AsyncOperationParam(), false); |
| 3945 LocalVariable* error_param = | 3951 LocalVariable* error_param = |
| 3946 top_scope->LookupVariable(Symbols::AsyncOperationErrorParam(), | 3952 top_scope->LookupVariable(Symbols::AsyncOperationErrorParam(), |
| 3947 false); | 3953 false); |
| 3948 LocalVariable* stack_trace_param = | 3954 LocalVariable* stack_trace_param = |
| 3949 top_scope->LookupVariable(Symbols::AsyncOperationStackTraceParam(), | 3955 top_scope->LookupVariable(Symbols::AsyncOperationStackTraceParam(), |
| 3950 false); | 3956 false); |
| 3951 for_true.BuildAwaitJump(old_context, | 3957 for_true.BuildAsyncJump(old_context, |
| 3952 result_param, | 3958 result_param, |
| 3953 error_param, | 3959 error_param, |
| 3954 stack_trace_param, | 3960 stack_trace_param, |
| 3955 (*owner()->await_levels())[i], | 3961 (*owner()->await_levels())[i], |
| 3956 (*owner()->await_joins())[i]); | 3962 (*owner()->await_joins())[i]); |
| 3957 } else { | 3963 } else { |
| 3958 ASSERT(function.IsSyncGenClosure()); | 3964 ASSERT(function.IsSyncGenClosure()); |
| 3959 LocalVariable* iterator_param = | 3965 LocalVariable* iterator_param = |
| 3960 top_scope->LookupVariable(Symbols::IteratorParameter(), false); | 3966 top_scope->LookupVariable(Symbols::IteratorParameter(), false); |
| 3961 for_true.BuildYieldJump(old_context, | 3967 for_true.BuildSyncYieldJump(old_context, |
| 3962 iterator_param, | 3968 iterator_param, |
| 3963 (*owner()->await_levels())[i], | 3969 (*owner()->await_levels())[i], |
| 3964 (*owner()->await_joins())[i]); | 3970 (*owner()->await_joins())[i]); |
| 3965 } | 3971 } |
| 3966 | 3972 |
| 3967 Join(for_test, for_true, for_false); | 3973 Join(for_test, for_true, for_false); |
| 3968 if (i == 0) { | 3974 if (i == 0) { |
| 3969 // Manually link up the preamble start. | 3975 // Manually link up the preamble start. |
| 3970 preamble_start->previous()->set_next(for_test.entry()); | 3976 preamble_start->previous()->set_next(for_test.entry()); |
| 3971 for_test.entry()->set_previous(preamble_start->previous()); | 3977 for_test.entry()->set_previous(preamble_start->previous()); |
| 3972 } | 3978 } |
| 3973 if (i == (num_await_states - 1)) { | 3979 if (i == (num_await_states - 1)) { |
| 3974 // Link up preamble end. | 3980 // Link up preamble end. |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4358 Report::MessageF(Report::kBailout, | 4364 Report::MessageF(Report::kBailout, |
| 4359 Script::Handle(function.script()), | 4365 Script::Handle(function.script()), |
| 4360 function.token_pos(), | 4366 function.token_pos(), |
| 4361 "FlowGraphBuilder Bailout: %s %s", | 4367 "FlowGraphBuilder Bailout: %s %s", |
| 4362 String::Handle(function.name()).ToCString(), | 4368 String::Handle(function.name()).ToCString(), |
| 4363 reason); | 4369 reason); |
| 4364 UNREACHABLE(); | 4370 UNREACHABLE(); |
| 4365 } | 4371 } |
| 4366 | 4372 |
| 4367 } // namespace dart | 4373 } // namespace dart |
| OLD | NEW |