Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: runtime/vm/flow_graph_builder.cc

Issue 888463004: Add support for sync* and yield (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 1068
1069 // Async functions contain two types of return statements: 1069 // Async functions contain two types of return statements:
1070 // 1) Returns that should complete the completer once all finally blocks have 1070 // 1) Returns that should complete the completer once all finally blocks have
1071 // been inlined (call: :async_completer.complete(return_value)). These 1071 // been inlined (call: :async_completer.complete(return_value)). These
1072 // returns end up returning null in the end. 1072 // returns end up returning null in the end.
1073 // 2) "Continuation" returns that should not complete the completer but return 1073 // 2) "Continuation" returns that should not complete the completer but return
1074 // the value. 1074 // the value.
1075 // 1075 //
1076 // We distinguish those kinds of nodes via is_regular_return(). 1076 // We distinguish those kinds of nodes via is_regular_return().
1077 // 1077 //
1078 if (function.is_async_closure() && 1078 if (function.IsAsyncClosure() &&
1079 (node->return_type() == ReturnNode::kRegular)) { 1079 (node->return_type() == ReturnNode::kRegular)) {
1080 // Temporary store the computed return value. 1080 // Temporary store the computed return value.
1081 Do(BuildStoreExprTemp(return_value)); 1081 Do(BuildStoreExprTemp(return_value));
1082 1082
1083 LocalVariable* rcv_var = node->scope()->LookupVariable( 1083 LocalVariable* rcv_var =
1084 Symbols::AsyncCompleter(), false); 1084 node->scope()->LookupVariable(Symbols::AsyncCompleter(), false);
1085 ASSERT(rcv_var != NULL && rcv_var->is_captured()); 1085 ASSERT(rcv_var != NULL && rcv_var->is_captured());
1086 ZoneGrowableArray<PushArgumentInstr*>* arguments = 1086 ZoneGrowableArray<PushArgumentInstr*>* arguments =
1087 new(I) ZoneGrowableArray<PushArgumentInstr*>(2); 1087 new(I) ZoneGrowableArray<PushArgumentInstr*>(2);
1088 Value* rcv_value = Bind(BuildLoadLocal(*rcv_var)); 1088 Value* rcv_value = Bind(BuildLoadLocal(*rcv_var));
1089 arguments->Add(PushArgument(rcv_value)); 1089 arguments->Add(PushArgument(rcv_value));
1090 Value* returned_value = Bind(BuildLoadExprTemp()); 1090 Value* returned_value = Bind(BuildLoadExprTemp());
1091 arguments->Add(PushArgument(returned_value)); 1091 arguments->Add(PushArgument(returned_value));
1092 InstanceCallInstr* call = new(I) InstanceCallInstr( 1092 InstanceCallInstr* call = new(I) InstanceCallInstr(
1093 Scanner::kNoSourcePos, 1093 Scanner::kNoSourcePos,
1094 Symbols::CompleterComplete(), 1094 Symbols::CompleterComplete(),
1095 Token::kILLEGAL, 1095 Token::kILLEGAL,
1096 arguments, 1096 arguments,
1097 Object::null_array(), 1097 Object::null_array(),
1098 1, 1098 1,
1099 owner()->ic_data_array()); 1099 owner()->ic_data_array());
1100 Do(call); 1100 Do(call);
1101 1101
1102 // Rebind the return value for the actual return call to be null. 1102 // Rebind the return value for the actual return call to be null.
1103 return_value = BuildNullValue(); 1103 return_value = BuildNullValue();
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
1113 AddReturnExit(node->token_pos(), return_value); 1112 AddReturnExit(node->token_pos(), return_value);
1114 1113
1115 if (function.is_async_closure() && 1114 if ((function.IsAsyncClosure() || function.IsSyncGenClosure()) &&
1116 (node->return_type() == ReturnNode::kContinuationTarget)) { 1115 (node->return_type() == ReturnNode::kContinuationTarget)) {
1117 JoinEntryInstr* const join = new(I) JoinEntryInstr( 1116 JoinEntryInstr* const join = new(I) JoinEntryInstr(
1118 owner()->AllocateBlockId(), owner()->try_index()); 1117 owner()->AllocateBlockId(), owner()->try_index());
1119 owner()->await_joins()->Add(join); 1118 owner()->await_joins()->Add(join);
1120 exit_ = join; 1119 exit_ = join;
1121 } 1120 }
1122 } 1121 }
1123 1122
1124 1123
1125 // <Expression> ::= Literal { literal: Instance } 1124 // <Expression> ::= Literal { literal: Instance }
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 return new(I) AssertAssignableInstr(token_pos, 1476 return new(I) AssertAssignableInstr(token_pos,
1478 value, 1477 value,
1479 instantiator, 1478 instantiator,
1480 instantiator_type_arguments, 1479 instantiator_type_arguments,
1481 dst_type, 1480 dst_type,
1482 dst_name, 1481 dst_name,
1483 deopt_id); 1482 deopt_id);
1484 } 1483 }
1485 1484
1486 1485
1486 void EffectGraphVisitor::BuildYieldJump(LocalVariable* old_context,
1487 LocalVariable* iterator_param,
1488 const intptr_t old_ctx_level,
1489 JoinEntryInstr* target) {
1490 // Building a jump consists of the following actions:
1491 // * Load the generator body's iterator parameter (:iterator)
1492 // from the current context into a temporary.
1493 // * Restore the old context from :await_cxt_var.
1494 // * Copy the iterator saved above into the restored context.
1495 // * Append a Goto to the target's join.
1496 ASSERT((iterator_param != NULL) && iterator_param->is_captured());
1497 ASSERT((old_context != NULL) && old_context->is_captured());
1498 // Before restoring the context we need to temporarily save the
1499 // iterator parameter.
1500 LocalVariable* temp_iterator_var =
1501 EnterTempLocalScope(Bind(BuildLoadLocal(*iterator_param)));
1502
1503 // Restore the saved continuation context, i.e. the context that was
1504 // saved into :await_ctx_var before the closure suspended.
1505 BuildRestoreContext(*old_context);
1506
1507 // Store the continuation result and continuation error values into
1508 // the restored context.
1509
1510 // FlowGraphBuilder is at top context level, but the continuation
1511 // target has possibly been recorded in a nested context (old_ctx_level).
1512 // We need to unroll manually here.
1513 intptr_t delta =
1514 old_ctx_level - iterator_param->owner()->context_level();
1515 ASSERT(delta >= 0);
1516 Value* context = Bind(BuildCurrentContext());
1517 while (delta-- > 0) {
1518 context = Bind(new(I) LoadFieldInstr(
1519 context, Context::parent_offset(), Type::ZoneHandle(I, Type::null()),
1520 Scanner::kNoSourcePos));
1521 }
1522 LocalVariable* temp_context_var = EnterTempLocalScope(context);
1523
1524 Value* context_val = Bind(new(I) LoadLocalInstr(*temp_context_var));
1525 Value* store_val = Bind(new(I) LoadLocalInstr(*temp_iterator_var));
1526 StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr(
1527 Context::variable_offset(iterator_param->index()),
1528 context_val,
1529 store_val,
1530 kEmitStoreBarrier,
1531 Scanner::kNoSourcePos);
1532 Do(store);
1533
1534 Do(ExitTempLocalScope(temp_context_var));
1535 Do(ExitTempLocalScope(temp_iterator_var));
1536
1537 // Goto saved join.
1538 Goto(target);
1539 }
1540
1541
1487 void EffectGraphVisitor::BuildAwaitJump(LocalVariable* old_context, 1542 void EffectGraphVisitor::BuildAwaitJump(LocalVariable* old_context,
1488 LocalVariable* continuation_result, 1543 LocalVariable* continuation_result,
1489 LocalVariable* continuation_error, 1544 LocalVariable* continuation_error,
1490 LocalVariable* continuation_stack_trace, 1545 LocalVariable* continuation_stack_trace,
1491 const intptr_t old_ctx_level, 1546 const intptr_t old_ctx_level,
1492 JoinEntryInstr* target) { 1547 JoinEntryInstr* target) {
1493 // Building a jump consists of the following actions: 1548 // Building a jump consists of the following actions:
1494 // * Record the current continuation result in a temporary. 1549 // * Load the current continuation result parameter (:async_result)
1495 // * Restore the old context. 1550 // and continuation error parameter (:async_error_param) from
1496 // * Overwrite the old context's continuation result with the temporary. 1551 // the current context into temporaries.
1552 // * Restore the old context from :await_cxt_var.
1553 // * Copy the result and error parameters saved above into the restored
1554 // context.
1497 // * Append a Goto to the target's join. 1555 // * Append a Goto to the target's join.
1498 ASSERT((continuation_result != NULL) && continuation_result->is_captured()); 1556 ASSERT((continuation_result != NULL) && continuation_result->is_captured());
1499 ASSERT((continuation_error != NULL) && continuation_error->is_captured()); 1557 ASSERT((continuation_error != NULL) && continuation_error->is_captured());
1500 ASSERT((old_context != NULL) && old_context->is_captured()); 1558 ASSERT((old_context != NULL) && old_context->is_captured());
1501 // Before restoring the continuation context we need to temporary save the 1559 // Before restoring the continuation context we need to temporary save the
1502 // result and error parameter. 1560 // result and error parameter.
1503 LocalVariable* temp_result_var = EnterTempLocalScope( 1561 LocalVariable* temp_result_var =
1504 Bind(BuildLoadLocal(*continuation_result))); 1562 EnterTempLocalScope(Bind(BuildLoadLocal(*continuation_result)));
1505 LocalVariable* temp_error_var = EnterTempLocalScope( 1563 LocalVariable* temp_error_var =
1506 Bind(BuildLoadLocal(*continuation_error))); 1564 EnterTempLocalScope(Bind(BuildLoadLocal(*continuation_error)));
1507 LocalVariable* temp_stack_trace_var = EnterTempLocalScope( 1565 LocalVariable* temp_stack_trace_var =
1508 Bind(BuildLoadLocal(*continuation_stack_trace))); 1566 EnterTempLocalScope(Bind(BuildLoadLocal(*continuation_stack_trace)));
1509 // Restore the saved continuation context. 1567
1568 // Restore the saved continuation context, i.e. the context that was
1569 // saved into :await_ctx_var before the closure suspended.
1510 BuildRestoreContext(*old_context); 1570 BuildRestoreContext(*old_context);
1511 1571
1512 // Pass over the continuation result. 1572 // Store the continuation result and continuation error values into
1573 // the restored context.
1513 1574
1514 // FlowGraphBuilder is at top context level, but the await target has possibly 1575 // FlowGraphBuilder is at top context level, but the await target has possibly
1515 // been recorded in a nested context (old_ctx_level). We need to unroll 1576 // been recorded in a nested context (old_ctx_level). We need to unroll
1516 // manually here. 1577 // manually here.
1517 intptr_t delta = old_ctx_level - 1578 intptr_t delta =
1518 continuation_result->owner()->context_level(); 1579 old_ctx_level - continuation_result->owner()->context_level();
1519 ASSERT(delta >= 0); 1580 ASSERT(delta >= 0);
1520 Value* context = Bind(BuildCurrentContext()); 1581 Value* context = Bind(BuildCurrentContext());
1521 while (delta-- > 0) { 1582 while (delta-- > 0) {
1522 context = Bind(new(I) LoadFieldInstr( 1583 context = Bind(new(I) LoadFieldInstr(
1523 context, Context::parent_offset(), Type::ZoneHandle(I, Type::null()), 1584 context, Context::parent_offset(), Type::ZoneHandle(I, Type::null()),
1524 Scanner::kNoSourcePos)); 1585 Scanner::kNoSourcePos));
1525 } 1586 }
1526 LocalVariable* temp_context_var = EnterTempLocalScope(context); 1587 LocalVariable* temp_context_var = EnterTempLocalScope(context);
1527 1588
1528 Value* context_val = Bind(new(I) LoadLocalInstr(*temp_context_var)); 1589 Value* context_val = Bind(new(I) LoadLocalInstr(*temp_context_var));
(...skipping 2166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3695 Do(BuildStoreContext(context)); 3756 Do(BuildStoreContext(context));
3696 } 3757 }
3697 } 3758 }
3698 3759
3699 3760
3700 // <Statement> ::= Sequence { scope: LocalScope 3761 // <Statement> ::= Sequence { scope: LocalScope
3701 // nodes: <Statement>* 3762 // nodes: <Statement>*
3702 // label: SourceLabel } 3763 // label: SourceLabel }
3703 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { 3764 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
3704 LocalScope* scope = node->scope(); 3765 LocalScope* scope = node->scope();
3766 const Function& function = owner()->function();
3705 const intptr_t num_context_variables = 3767 const intptr_t num_context_variables =
3706 (scope != NULL) ? scope->num_context_variables() : 0; 3768 (scope != NULL) ? scope->num_context_variables() : 0;
3707 const bool is_top_level_sequence = 3769 const bool is_top_level_sequence =
3708 node == owner()->parsed_function().node_sequence(); 3770 node == owner()->parsed_function().node_sequence();
3709 // The outermost function sequence cannot contain a label. 3771 // The outermost function sequence cannot contain a label.
3710 ASSERT((node->label() == NULL) || !is_top_level_sequence); 3772 ASSERT((node->label() == NULL) || !is_top_level_sequence);
3711 NestedBlock nested_block(owner(), node); 3773 NestedBlock nested_block(owner(), node);
3712 3774
3713 if (num_context_variables > 0) { 3775 if (num_context_variables > 0) {
3714 // The local scope declares variables that are captured. 3776 // The local scope declares variables that are captured.
(...skipping 12 matching lines...) Expand all
3727 kEmitStoreBarrier, 3789 kEmitStoreBarrier,
3728 Scanner::kNoSourcePos)); 3790 Scanner::kNoSourcePos));
3729 } 3791 }
3730 Do(BuildStoreContext(Bind(ExitTempLocalScope(tmp_var)))); 3792 Do(BuildStoreContext(Bind(ExitTempLocalScope(tmp_var))));
3731 } 3793 }
3732 3794
3733 // If this node_sequence is the body of the function being compiled, copy 3795 // If this node_sequence is the body of the function being compiled, copy
3734 // the captured parameters from the frame into the context. 3796 // the captured parameters from the frame into the context.
3735 if (is_top_level_sequence) { 3797 if (is_top_level_sequence) {
3736 ASSERT(scope->context_level() == 1); 3798 ASSERT(scope->context_level() == 1);
3737 const Function& function = owner()->function();
3738 const int num_params = function.NumParameters(); 3799 const int num_params = function.NumParameters();
3739 int param_frame_index = (num_params == function.num_fixed_parameters()) ? 3800 int param_frame_index = (num_params == function.num_fixed_parameters()) ?
3740 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; 3801 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp;
3741 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { 3802 for (int pos = 0; pos < num_params; param_frame_index--, pos++) {
3742 const LocalVariable& parameter = *scope->VariableAt(pos); 3803 const LocalVariable& parameter = *scope->VariableAt(pos);
3743 ASSERT(parameter.owner() == scope); 3804 ASSERT(parameter.owner() == scope);
3744 if (parameter.is_captured()) { 3805 if (parameter.is_captured()) {
3745 // Create a temporary local describing the original position. 3806 // Create a temporary local describing the original position.
3746 const String& temp_name = Symbols::TempParam(); 3807 const String& temp_name = Symbols::TempParam();
3747 LocalVariable* temp_local = new(I) LocalVariable( 3808 LocalVariable* temp_local = new(I) LocalVariable(
(...skipping 17 matching lines...) Expand all
3765 Value* null_constant = Bind(new(I) ConstantInstr( 3826 Value* null_constant = Bind(new(I) ConstantInstr(
3766 Object::ZoneHandle(I, Object::null()))); 3827 Object::ZoneHandle(I, Object::null())));
3767 Do(BuildStoreLocal(*temp_local, null_constant)); 3828 Do(BuildStoreLocal(*temp_local, null_constant));
3768 } 3829 }
3769 } 3830 }
3770 } 3831 }
3771 } 3832 }
3772 3833
3773 // This check may be deleted if the generated code is leaf. 3834 // This check may be deleted if the generated code is leaf.
3774 // Native functions don't need a stack check at entry. 3835 // Native functions don't need a stack check at entry.
3775 const Function& function = owner()->function();
3776 if (is_top_level_sequence && !function.is_native()) { 3836 if (is_top_level_sequence && !function.is_native()) {
3777 // Always allocate CheckOverflowInstr so that deopt-ids match regardless 3837 // Always allocate CheckOverflowInstr so that deopt-ids match regardless
3778 // if we inline or not. 3838 // if we inline or not.
3779 if (!function.IsImplicitGetterFunction() && 3839 if (!function.IsImplicitGetterFunction() &&
3780 !function.IsImplicitSetterFunction()) { 3840 !function.IsImplicitSetterFunction()) {
3781 CheckStackOverflowInstr* check = 3841 CheckStackOverflowInstr* check =
3782 new(I) CheckStackOverflowInstr(function.token_pos(), 0); 3842 new(I) CheckStackOverflowInstr(function.token_pos(), 0);
3783 // If we are inlining don't actually attach the stack check. We must still 3843 // If we are inlining don't actually attach the stack check. We must still
3784 // create the stack check in order to allocate a deopt id. 3844 // create the stack check in order to allocate a deopt id.
3785 if (!owner()->IsInlining()) { 3845 if (!owner()->IsInlining()) {
3786 AddInstruction(check); 3846 AddInstruction(check);
3787 } 3847 }
3788 } 3848 }
3789 } 3849 }
3790 3850
3791 if (Isolate::Current()->TypeChecksEnabled() && is_top_level_sequence) { 3851 if (Isolate::Current()->TypeChecksEnabled() && is_top_level_sequence) {
3792 const Function& function = owner()->function();
3793 const int num_params = function.NumParameters(); 3852 const int num_params = function.NumParameters();
3794 int pos = 0; 3853 int pos = 0;
3795 if (function.IsConstructor()) { 3854 if (function.IsConstructor()) {
3796 // Skip type checking of receiver and phase for constructor functions. 3855 // Skip type checking of receiver and phase for constructor functions.
3797 pos = 2; 3856 pos = 2;
3798 } else if (function.IsFactory() || function.IsDynamicFunction()) { 3857 } else if (function.IsFactory() || function.IsDynamicFunction()) {
3799 // Skip type checking of type arguments for factory functions. 3858 // Skip type checking of type arguments for factory functions.
3800 // Skip type checking of receiver for instance functions. 3859 // Skip type checking of receiver for instance functions.
3801 pos = 1; 3860 pos = 1;
3802 } 3861 }
3803 while (pos < num_params) { 3862 while (pos < num_params) {
3804 const LocalVariable& parameter = *scope->VariableAt(pos); 3863 const LocalVariable& parameter = *scope->VariableAt(pos);
3805 ASSERT(parameter.owner() == scope); 3864 ASSERT(parameter.owner() == scope);
3806 if (!CanSkipTypeCheck(parameter.token_pos(), 3865 if (!CanSkipTypeCheck(parameter.token_pos(),
3807 NULL, 3866 NULL,
3808 parameter.type(), 3867 parameter.type(),
3809 parameter.name())) { 3868 parameter.name())) {
3810 Value* parameter_value = Bind(BuildLoadLocal(parameter)); 3869 Value* parameter_value = Bind(BuildLoadLocal(parameter));
3811 Do(BuildAssertAssignable(parameter.token_pos(), 3870 Do(BuildAssertAssignable(parameter.token_pos(),
3812 parameter_value, 3871 parameter_value,
3813 parameter.type(), 3872 parameter.type(),
3814 parameter.name())); 3873 parameter.name()));
3815 } 3874 }
3816 pos++; 3875 pos++;
3817 } 3876 }
3818 } 3877 }
3819 3878
3820 // Continuation part: 3879 // Continuation part:
3821 // If this node sequence is the body of an async closure leave room for a 3880 // If this node sequence is the body of a function with continuations,
3822 // preamble. The preamble is generated after visiting the body. 3881 // leave room for a preamble.
3882 // The preamble is generated after visiting the body.
3823 GotoInstr* preamble_start = NULL; 3883 GotoInstr* preamble_start = NULL;
3824 if (is_top_level_sequence && (owner()->function().is_async_closure())) { 3884 if (is_top_level_sequence &&
3885 (function.IsAsyncClosure() || function.IsSyncGenClosure())) {
3825 JoinEntryInstr* preamble_end = new(I) JoinEntryInstr( 3886 JoinEntryInstr* preamble_end = new(I) JoinEntryInstr(
3826 owner()->AllocateBlockId(), owner()->try_index()); 3887 owner()->AllocateBlockId(), owner()->try_index());
3827 ASSERT(exit() != NULL); 3888 ASSERT(exit() != NULL);
3828 exit()->Goto(preamble_end); 3889 exit()->Goto(preamble_end);
3829 ASSERT(exit()->next()->IsGoto()); 3890 ASSERT(exit()->next()->IsGoto());
3830 preamble_start = exit()->next()->AsGoto(); 3891 preamble_start = exit()->next()->AsGoto();
3831 ASSERT(preamble_start->IsGoto()); 3892 ASSERT(preamble_start->IsGoto());
3832 exit_ = preamble_end; 3893 exit_ = preamble_end;
3833 } 3894 }
3834 3895
3835 intptr_t i = 0; 3896 intptr_t i = 0;
3836 while (is_open() && (i < node->length())) { 3897 while (is_open() && (i < node->length())) {
3837 EffectGraphVisitor for_effect(owner()); 3898 EffectGraphVisitor for_effect(owner());
3838 node->NodeAt(i++)->Visit(&for_effect); 3899 node->NodeAt(i++)->Visit(&for_effect);
3839 Append(for_effect); 3900 Append(for_effect);
3840 if (!is_open()) { 3901 if (!is_open()) {
3841 // E.g., because of a JumpNode. 3902 // E.g., because of a JumpNode.
3842 break; 3903 break;
3843 } 3904 }
3844 } 3905 }
3845 3906
3846 // Continuation part: 3907 // Continuation part:
3847 // After generating the CFG for the body we can create the preamble because we 3908 // After generating the CFG for the body we can create the preamble
3848 // know exactly how many continuation states we need. 3909 // because we know exactly how many continuation states we need.
3849 if (is_top_level_sequence && (owner()->function().is_async_closure())) { 3910 if (is_top_level_sequence &&
3911 (function.IsAsyncClosure() || function.IsSyncGenClosure())) {
3850 ASSERT(preamble_start != NULL); 3912 ASSERT(preamble_start != NULL);
3851 // We are at the top level. Fetch the corresponding scope. 3913 // We are at the top level. Fetch the corresponding scope.
3852 LocalScope* top_scope = node->scope(); 3914 LocalScope* top_scope = node->scope();
3853 LocalVariable* jump_var = top_scope->LookupVariable( 3915 LocalVariable* jump_var = top_scope->LookupVariable(
3854 Symbols::AwaitJumpVar(), false); 3916 Symbols::AwaitJumpVar(), false);
3855 ASSERT(jump_var != NULL && jump_var->is_captured()); 3917 ASSERT(jump_var != NULL && jump_var->is_captured());
3856
3857 Instruction* saved_entry = entry_; 3918 Instruction* saved_entry = entry_;
3858 Instruction* saved_exit = exit_; 3919 Instruction* saved_exit = exit_;
3859 entry_ = NULL; 3920 entry_ = NULL;
3860 exit_ = NULL; 3921 exit_ = NULL;
3861 3922
3862 LoadLocalNode* load_jump_count = new(I) LoadLocalNode( 3923 LoadLocalNode* load_jump_count =
3863 Scanner::kNoSourcePos, jump_var); 3924 new(I) LoadLocalNode(Scanner::kNoSourcePos, jump_var);
3864 ComparisonNode* check_jump_count; 3925 ComparisonNode* check_jump_count;
3865 const intptr_t num_await_states = owner()->await_joins()->length(); 3926 const intptr_t num_await_states = owner()->await_joins()->length();
3927
3866 LocalVariable* old_context = top_scope->LookupVariable( 3928 LocalVariable* old_context = top_scope->LookupVariable(
3867 Symbols::AwaitContextVar(), false); 3929 Symbols::AwaitContextVar(), false);
3868 LocalVariable* continuation_result = top_scope->LookupVariable(
3869 Symbols::AsyncOperationParam(), false);
3870 LocalVariable* continuation_error = top_scope->LookupVariable(
3871 Symbols::AsyncOperationErrorParam(), false);
3872 LocalVariable* continuation_stack_trace = top_scope->LookupVariable(
3873 Symbols::AsyncOperationStackTraceParam(), false);
3874 for (intptr_t i = 0; i < num_await_states; i++) { 3930 for (intptr_t i = 0; i < num_await_states; i++) {
3875 check_jump_count = new(I) ComparisonNode( 3931 check_jump_count = new(I) ComparisonNode(
3876 Scanner::kNoSourcePos, 3932 Scanner::kNoSourcePos,
3877 Token::kEQ, 3933 Token::kEQ,
3878 load_jump_count, 3934 load_jump_count,
3879 new(I) LiteralNode( 3935 new(I) LiteralNode(
3880 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i)))); 3936 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i))));
3881 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos); 3937 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
3882 check_jump_count->Visit(&for_test); 3938 check_jump_count->Visit(&for_test);
3883 EffectGraphVisitor for_true(owner()); 3939 EffectGraphVisitor for_true(owner());
3884 EffectGraphVisitor for_false(owner()); 3940 EffectGraphVisitor for_false(owner());
3885 3941
3886 for_true.BuildAwaitJump(old_context, 3942 if (function.IsAsyncClosure()) {
3887 continuation_result, 3943 LocalVariable* result_param =
3888 continuation_error, 3944 top_scope->LookupVariable(Symbols::AsyncOperationParam(), false);
3889 continuation_stack_trace, 3945 LocalVariable* error_param =
3890 (*owner()->await_levels())[i], 3946 top_scope->LookupVariable(Symbols::AsyncOperationErrorParam(),
3891 (*owner()->await_joins())[i]); 3947 false);
3948 LocalVariable* stack_trace_param =
3949 top_scope->LookupVariable(Symbols::AsyncOperationStackTraceParam(),
3950 false);
3951 for_true.BuildAwaitJump(old_context,
3952 result_param,
3953 error_param,
3954 stack_trace_param,
3955 (*owner()->await_levels())[i],
3956 (*owner()->await_joins())[i]);
3957 } else {
3958 ASSERT(function.IsSyncGenClosure());
3959 LocalVariable* iterator_param =
3960 top_scope->LookupVariable(Symbols::IteratorParameter(), false);
3961 for_true.BuildYieldJump(old_context,
3962 iterator_param,
3963 (*owner()->await_levels())[i],
3964 (*owner()->await_joins())[i]);
3965 }
3966
3892 Join(for_test, for_true, for_false); 3967 Join(for_test, for_true, for_false);
3893
3894 if (i == 0) { 3968 if (i == 0) {
3895 // Manually link up the preamble start. 3969 // Manually link up the preamble start.
3896 preamble_start->previous()->set_next(for_test.entry()); 3970 preamble_start->previous()->set_next(for_test.entry());
3897 for_test.entry()->set_previous(preamble_start->previous()); 3971 for_test.entry()->set_previous(preamble_start->previous());
3898 } 3972 }
3899 if (i == (num_await_states - 1)) { 3973 if (i == (num_await_states - 1)) {
3900 // Link up preamble end. 3974 // Link up preamble end.
3901 if (exit_ == NULL) { 3975 if (exit_ == NULL) {
3902 exit_ = preamble_start; 3976 exit_ = preamble_start;
3903 } else { 3977 } else {
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
4282 Report::MessageF(Report::kBailout, 4356 Report::MessageF(Report::kBailout,
4283 Script::Handle(function.script()), 4357 Script::Handle(function.script()),
4284 function.token_pos(), 4358 function.token_pos(),
4285 "FlowGraphBuilder Bailout: %s %s", 4359 "FlowGraphBuilder Bailout: %s %s",
4286 String::Handle(function.name()).ToCString(), 4360 String::Handle(function.name()).ToCString(),
4287 reason); 4361 reason);
4288 UNREACHABLE(); 4362 UNREACHABLE();
4289 } 4363 }
4290 4364
4291 } // namespace dart 4365 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698