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

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
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 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 1067
1068 // Async functions contain two types of return statements: 1068 // Async functions contain two types of return statements:
1069 // 1) Returns that should complete the completer once all finally blocks have 1069 // 1) Returns that should complete the completer once all finally blocks have
1070 // been inlined (call: :async_completer.complete(return_value)). These 1070 // been inlined (call: :async_completer.complete(return_value)). These
1071 // returns end up returning null in the end. 1071 // returns end up returning null in the end.
1072 // 2) "Continuation" returns that should not complete the completer but return 1072 // 2) "Continuation" returns that should not complete the completer but return
1073 // the value. 1073 // the value.
1074 // 1074 //
1075 // We distinguish those kinds of nodes via is_regular_return(). 1075 // We distinguish those kinds of nodes via is_regular_return().
1076 // 1076 //
1077 if (function.is_async_closure() && 1077 if (function.IsAsyncClosure() &&
1078 (node->return_type() == ReturnNode::kRegular)) { 1078 (node->return_type() == ReturnNode::kRegular)) {
1079 // Temporary store the computed return value. 1079 // Temporary store the computed return value.
1080 Do(BuildStoreExprTemp(return_value)); 1080 Do(BuildStoreExprTemp(return_value));
1081 1081
1082 LocalVariable* rcv_var = node->scope()->LookupVariable( 1082 LocalVariable* rcv_var =
1083 Symbols::AsyncCompleter(), false); 1083 node->scope()->LookupVariable(Symbols::AsyncCompleter(), false);
1084 ASSERT(rcv_var != NULL && rcv_var->is_captured()); 1084 ASSERT(rcv_var != NULL && rcv_var->is_captured());
1085 ZoneGrowableArray<PushArgumentInstr*>* arguments = 1085 ZoneGrowableArray<PushArgumentInstr*>* arguments =
1086 new(I) ZoneGrowableArray<PushArgumentInstr*>(2); 1086 new(I) ZoneGrowableArray<PushArgumentInstr*>(2);
1087 Value* rcv_value = Bind(BuildLoadLocal(*rcv_var)); 1087 Value* rcv_value = Bind(BuildLoadLocal(*rcv_var));
1088 arguments->Add(PushArgument(rcv_value)); 1088 arguments->Add(PushArgument(rcv_value));
1089 Value* returned_value = Bind(BuildLoadExprTemp()); 1089 Value* returned_value = Bind(BuildLoadExprTemp());
1090 arguments->Add(PushArgument(returned_value)); 1090 arguments->Add(PushArgument(returned_value));
1091 InstanceCallInstr* call = new(I) InstanceCallInstr( 1091 InstanceCallInstr* call = new(I) InstanceCallInstr(
1092 Scanner::kNoSourcePos, 1092 Scanner::kNoSourcePos,
1093 Symbols::CompleterComplete(), 1093 Symbols::CompleterComplete(),
1094 Token::kILLEGAL, 1094 Token::kILLEGAL,
1095 arguments, 1095 arguments,
1096 Object::null_array(), 1096 Object::null_array(),
1097 1, 1097 1,
1098 owner()->ic_data_array()); 1098 owner()->ic_data_array());
1099 Do(call); 1099 Do(call);
1100 1100
1101 // Rebind the return value for the actual return call to be null. 1101 // Rebind the return value for the actual return call to be null.
1102 return_value = BuildNullValue(); 1102 return_value = BuildNullValue();
1103 } 1103 }
1104 1104
1105 intptr_t current_context_level = owner()->context_level(); 1105 intptr_t current_context_level = owner()->context_level();
1106 ASSERT(current_context_level >= 0); 1106 ASSERT(current_context_level >= 0);
1107 if (HasContextScope()) { 1107 if (HasContextScope()) {
1108 UnchainContexts(current_context_level); 1108 UnchainContexts(current_context_level);
1109 } 1109 }
1110 1110
1111
1112 AddReturnExit(node->token_pos(), return_value); 1111 AddReturnExit(node->token_pos(), return_value);
1113 1112
1114 if (function.is_async_closure() && 1113 if ((function.IsAsyncClosure() || function.IsSyncGenClosure()) &&
1115 (node->return_type() == ReturnNode::kContinuationTarget)) { 1114 (node->return_type() == ReturnNode::kContinuationTarget)) {
1116 JoinEntryInstr* const join = new(I) JoinEntryInstr( 1115 JoinEntryInstr* const join = new(I) JoinEntryInstr(
1117 owner()->AllocateBlockId(), owner()->try_index()); 1116 owner()->AllocateBlockId(), owner()->try_index());
1118 owner()->await_joins()->Add(join); 1117 owner()->await_joins()->Add(join);
1119 exit_ = join; 1118 exit_ = join;
1120 } 1119 }
1121 } 1120 }
1122 1121
1123 1122
1124 // <Expression> ::= Literal { literal: Instance } 1123 // <Expression> ::= Literal { literal: Instance }
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 return new(I) AssertAssignableInstr(token_pos, 1473 return new(I) AssertAssignableInstr(token_pos,
1475 value, 1474 value,
1476 instantiator, 1475 instantiator,
1477 instantiator_type_arguments, 1476 instantiator_type_arguments,
1478 dst_type, 1477 dst_type,
1479 dst_name, 1478 dst_name,
1480 deopt_id); 1479 deopt_id);
1481 } 1480 }
1482 1481
1483 1482
1483 void EffectGraphVisitor::BuildYieldJump(LocalVariable* old_context,
1484 LocalVariable* iterator_param,
1485 const intptr_t old_ctx_level,
1486 JoinEntryInstr* target) {
1487 // Building a jump consists of the following actions:
1488 // * Load the generator body's iterator parameter (:iterator)
1489 // from the current context into a temporary.
1490 // * Restore the old context from :await_cxt_var.
1491 // * Copy the iterator saved above into the restored context.
1492 // * Append a Goto to the target's join.
1493 ASSERT((iterator_param != NULL) && iterator_param->is_captured());
1494 ASSERT((old_context != NULL) && old_context->is_captured());
1495 // Before restoring the context we need to temporarily save the
1496 // iterator parameter.
1497 LocalVariable* temp_iterator_var =
1498 EnterTempLocalScope(Bind(BuildLoadLocal(*iterator_param)));
1499
1500 // Restore the saved continuation context, i.e. the context that was
1501 // saved into :await_ctx_var before the closure suspended.
1502 BuildRestoreContext(*old_context);
1503
1504 // Store the continuation result and continuation error values into
1505 // the restored context.
1506
1507 // FlowGraphBuilder is at top context level, but the continuation
1508 // target has possibly been recorded in a nested context (old_ctx_level).
1509 // We need to unroll manually here.
1510 intptr_t delta =
1511 old_ctx_level - iterator_param->owner()->context_level();
1512 ASSERT(delta >= 0);
1513 Value* context = Bind(BuildCurrentContext());
1514 while (delta-- > 0) {
1515 context = Bind(new(I) LoadFieldInstr(
1516 context, Context::parent_offset(), Type::ZoneHandle(I, Type::null()),
1517 Scanner::kNoSourcePos));
1518 }
1519 LocalVariable* temp_context_var = EnterTempLocalScope(context);
1520
1521 Value* context_val = Bind(new(I) LoadLocalInstr(*temp_context_var));
1522 Value* store_val = Bind(new(I) LoadLocalInstr(*temp_iterator_var));
1523 StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr(
1524 Context::variable_offset(iterator_param->index()),
1525 context_val,
1526 store_val,
1527 kEmitStoreBarrier,
1528 Scanner::kNoSourcePos);
1529 Do(store);
1530
1531 Do(ExitTempLocalScope(temp_context_var));
1532 Do(ExitTempLocalScope(temp_iterator_var));
1533
1534 // Goto saved join.
1535 Goto(target);
1536 }
1537
1538
1484 void EffectGraphVisitor::BuildAwaitJump(LocalVariable* old_context, 1539 void EffectGraphVisitor::BuildAwaitJump(LocalVariable* old_context,
1485 LocalVariable* continuation_result, 1540 LocalVariable* continuation_result,
1486 LocalVariable* continuation_error, 1541 LocalVariable* continuation_error,
1487 const intptr_t old_ctx_level, 1542 const intptr_t old_ctx_level,
1488 JoinEntryInstr* target) { 1543 JoinEntryInstr* target) {
1489 // Building a jump consists of the following actions: 1544 // Building a jump consists of the following actions:
1490 // * Record the current continuation result in a temporary. 1545 // * Load the current continuation result parameter (:async_result)
1491 // * Restore the old context. 1546 // and continuation error parameter (:async_error_param) from
1492 // * Overwrite the old context's continuation result with the temporary. 1547 // the current context into temporaries.
1548 // * Restore the old context from :await_cxt_var.
1549 // * Copy the result and error parameters saved above into the restored
1550 // context.
1493 // * Append a Goto to the target's join. 1551 // * Append a Goto to the target's join.
1494 ASSERT((continuation_result != NULL) && continuation_result->is_captured()); 1552 ASSERT((continuation_result != NULL) && continuation_result->is_captured());
1495 ASSERT((continuation_error != NULL) && continuation_error->is_captured()); 1553 ASSERT((continuation_error != NULL) && continuation_error->is_captured());
1496 ASSERT((old_context != NULL) && old_context->is_captured()); 1554 ASSERT((old_context != NULL) && old_context->is_captured());
1497 // Before restoring the continuation context we need to temporary save the 1555 // Before restoring the continuation context we need to temporary save the
1498 // result and error parameter. 1556 // result and error parameter.
1499 LocalVariable* temp_result_var = EnterTempLocalScope( 1557 LocalVariable* temp_result_var =
1500 Bind(BuildLoadLocal(*continuation_result))); 1558 EnterTempLocalScope(Bind(BuildLoadLocal(*continuation_result)));
1501 LocalVariable* temp_error_var = EnterTempLocalScope( 1559 LocalVariable* temp_error_var =
1502 Bind(BuildLoadLocal(*continuation_error))); 1560 EnterTempLocalScope(Bind(BuildLoadLocal(*continuation_error)));
1503 // Restore the saved continuation context. 1561
1562 // Restore the saved continuation context, i.e. the context that was
1563 // saved into :await_ctx_var before the closure suspended.
1504 BuildRestoreContext(*old_context); 1564 BuildRestoreContext(*old_context);
1505 1565
1506 // Pass over the continuation result. 1566 // Store the continuation result and continuation error values into
1567 // the restored context.
1507 1568
1508 // FlowGraphBuilder is at top context level, but the await target has possibly 1569 // FlowGraphBuilder is at top context level, but the await target has possibly
1509 // been recorded in a nested context (old_ctx_level). We need to unroll 1570 // been recorded in a nested context (old_ctx_level). We need to unroll
1510 // manually here. 1571 // manually here.
1511 intptr_t delta = old_ctx_level - 1572 intptr_t delta =
1512 continuation_result->owner()->context_level(); 1573 old_ctx_level - continuation_result->owner()->context_level();
1513 ASSERT(delta >= 0); 1574 ASSERT(delta >= 0);
1514 Value* context = Bind(BuildCurrentContext()); 1575 Value* context = Bind(BuildCurrentContext());
1515 while (delta-- > 0) { 1576 while (delta-- > 0) {
1516 context = Bind(new(I) LoadFieldInstr( 1577 context = Bind(new(I) LoadFieldInstr(
1517 context, Context::parent_offset(), Type::ZoneHandle(I, Type::null()), 1578 context, Context::parent_offset(), Type::ZoneHandle(I, Type::null()),
1518 Scanner::kNoSourcePos)); 1579 Scanner::kNoSourcePos));
1519 } 1580 }
1520 LocalVariable* temp_context_var = EnterTempLocalScope(context); 1581 LocalVariable* temp_context_var = EnterTempLocalScope(context);
1521 1582
1522 Value* context_val = Bind(new(I) LoadLocalInstr(*temp_context_var)); 1583 Value* context_val = Bind(new(I) LoadLocalInstr(*temp_context_var));
(...skipping 2204 matching lines...) Expand 10 before | Expand all | Expand 10 after
3727 Do(BuildStoreContext(context)); 3788 Do(BuildStoreContext(context));
3728 } 3789 }
3729 } 3790 }
3730 3791
3731 3792
3732 // <Statement> ::= Sequence { scope: LocalScope 3793 // <Statement> ::= Sequence { scope: LocalScope
3733 // nodes: <Statement>* 3794 // nodes: <Statement>*
3734 // label: SourceLabel } 3795 // label: SourceLabel }
3735 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { 3796 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
3736 LocalScope* scope = node->scope(); 3797 LocalScope* scope = node->scope();
3798 const Function& function = owner()->parsed_function().function();
srdjan 2015/02/04 19:29:12 owner()->function();
hausner 2015/02/04 22:09:24 Done.
3737 const intptr_t num_context_variables = 3799 const intptr_t num_context_variables =
3738 (scope != NULL) ? scope->num_context_variables() : 0; 3800 (scope != NULL) ? scope->num_context_variables() : 0;
3739 const bool is_top_level_sequence = 3801 const bool is_top_level_sequence =
3740 node == owner()->parsed_function().node_sequence(); 3802 node == owner()->parsed_function().node_sequence();
3741 // The outermost function sequence cannot contain a label. 3803 // The outermost function sequence cannot contain a label.
3742 ASSERT((node->label() == NULL) || !is_top_level_sequence); 3804 ASSERT((node->label() == NULL) || !is_top_level_sequence);
3743 NestedBlock nested_block(owner(), node); 3805 NestedBlock nested_block(owner(), node);
3744 3806
3745 if (num_context_variables > 0) { 3807 if (num_context_variables > 0) {
3746 // The local scope declares variables that are captured. 3808 // The local scope declares variables that are captured.
(...skipping 12 matching lines...) Expand all
3759 kEmitStoreBarrier, 3821 kEmitStoreBarrier,
3760 Scanner::kNoSourcePos)); 3822 Scanner::kNoSourcePos));
3761 } 3823 }
3762 Do(BuildStoreContext(Bind(ExitTempLocalScope(tmp_var)))); 3824 Do(BuildStoreContext(Bind(ExitTempLocalScope(tmp_var))));
3763 } 3825 }
3764 3826
3765 // If this node_sequence is the body of the function being compiled, copy 3827 // If this node_sequence is the body of the function being compiled, copy
3766 // the captured parameters from the frame into the context. 3828 // the captured parameters from the frame into the context.
3767 if (is_top_level_sequence) { 3829 if (is_top_level_sequence) {
3768 ASSERT(scope->context_level() == 1); 3830 ASSERT(scope->context_level() == 1);
3769 const Function& function = owner()->function();
3770 const int num_params = function.NumParameters(); 3831 const int num_params = function.NumParameters();
3771 int param_frame_index = (num_params == function.num_fixed_parameters()) ? 3832 int param_frame_index = (num_params == function.num_fixed_parameters()) ?
3772 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; 3833 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp;
3773 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { 3834 for (int pos = 0; pos < num_params; param_frame_index--, pos++) {
3774 const LocalVariable& parameter = *scope->VariableAt(pos); 3835 const LocalVariable& parameter = *scope->VariableAt(pos);
3775 ASSERT(parameter.owner() == scope); 3836 ASSERT(parameter.owner() == scope);
3776 if (parameter.is_captured()) { 3837 if (parameter.is_captured()) {
3777 // Create a temporary local describing the original position. 3838 // Create a temporary local describing the original position.
3778 const String& temp_name = Symbols::TempParam(); 3839 const String& temp_name = Symbols::TempParam();
3779 LocalVariable* temp_local = new(I) LocalVariable( 3840 LocalVariable* temp_local = new(I) LocalVariable(
(...skipping 17 matching lines...) Expand all
3797 Value* null_constant = Bind(new(I) ConstantInstr( 3858 Value* null_constant = Bind(new(I) ConstantInstr(
3798 Object::ZoneHandle(I, Object::null()))); 3859 Object::ZoneHandle(I, Object::null())));
3799 Do(BuildStoreLocal(*temp_local, null_constant)); 3860 Do(BuildStoreLocal(*temp_local, null_constant));
3800 } 3861 }
3801 } 3862 }
3802 } 3863 }
3803 } 3864 }
3804 3865
3805 // This check may be deleted if the generated code is leaf. 3866 // This check may be deleted if the generated code is leaf.
3806 // Native functions don't need a stack check at entry. 3867 // Native functions don't need a stack check at entry.
3807 const Function& function = owner()->function();
3808 if (is_top_level_sequence && !function.is_native()) { 3868 if (is_top_level_sequence && !function.is_native()) {
3809 // Always allocate CheckOverflowInstr so that deopt-ids match regardless 3869 // Always allocate CheckOverflowInstr so that deopt-ids match regardless
3810 // if we inline or not. 3870 // if we inline or not.
3811 if (!function.IsImplicitGetterFunction() && 3871 if (!function.IsImplicitGetterFunction() &&
3812 !function.IsImplicitSetterFunction()) { 3872 !function.IsImplicitSetterFunction()) {
3813 CheckStackOverflowInstr* check = 3873 CheckStackOverflowInstr* check =
3814 new(I) CheckStackOverflowInstr(function.token_pos(), 0); 3874 new(I) CheckStackOverflowInstr(function.token_pos(), 0);
3815 // If we are inlining don't actually attach the stack check. We must still 3875 // If we are inlining don't actually attach the stack check. We must still
3816 // create the stack check in order to allocate a deopt id. 3876 // create the stack check in order to allocate a deopt id.
3817 if (!owner()->IsInlining()) { 3877 if (!owner()->IsInlining()) {
3818 AddInstruction(check); 3878 AddInstruction(check);
3819 } 3879 }
3820 } 3880 }
3821 } 3881 }
3822 3882
3823 if (FLAG_enable_type_checks && is_top_level_sequence) { 3883 if (FLAG_enable_type_checks && is_top_level_sequence) {
3824 const Function& function = owner()->function();
3825 const int num_params = function.NumParameters(); 3884 const int num_params = function.NumParameters();
3826 int pos = 0; 3885 int pos = 0;
3827 if (function.IsConstructor()) { 3886 if (function.IsConstructor()) {
3828 // Skip type checking of receiver and phase for constructor functions. 3887 // Skip type checking of receiver and phase for constructor functions.
3829 pos = 2; 3888 pos = 2;
3830 } else if (function.IsFactory() || function.IsDynamicFunction()) { 3889 } else if (function.IsFactory() || function.IsDynamicFunction()) {
3831 // Skip type checking of type arguments for factory functions. 3890 // Skip type checking of type arguments for factory functions.
3832 // Skip type checking of receiver for instance functions. 3891 // Skip type checking of receiver for instance functions.
3833 pos = 1; 3892 pos = 1;
3834 } 3893 }
3835 while (pos < num_params) { 3894 while (pos < num_params) {
3836 const LocalVariable& parameter = *scope->VariableAt(pos); 3895 const LocalVariable& parameter = *scope->VariableAt(pos);
3837 ASSERT(parameter.owner() == scope); 3896 ASSERT(parameter.owner() == scope);
3838 if (!CanSkipTypeCheck(parameter.token_pos(), 3897 if (!CanSkipTypeCheck(parameter.token_pos(),
3839 NULL, 3898 NULL,
3840 parameter.type(), 3899 parameter.type(),
3841 parameter.name())) { 3900 parameter.name())) {
3842 Value* parameter_value = Bind(BuildLoadLocal(parameter)); 3901 Value* parameter_value = Bind(BuildLoadLocal(parameter));
3843 Do(BuildAssertAssignable(parameter.token_pos(), 3902 Do(BuildAssertAssignable(parameter.token_pos(),
3844 parameter_value, 3903 parameter_value,
3845 parameter.type(), 3904 parameter.type(),
3846 parameter.name())); 3905 parameter.name()));
3847 } 3906 }
3848 pos++; 3907 pos++;
3849 } 3908 }
3850 } 3909 }
3851 3910
3852 // Continuation part: 3911 // Continuation part:
3853 // If this node sequence is the body of an async closure leave room for a 3912 // If this node sequence is the body of a function with continuations,
3854 // preamble. The preamble is generated after visiting the body. 3913 // leave room for a preamble.
3914 // The preamble is generated after visiting the body.
3855 GotoInstr* preamble_start = NULL; 3915 GotoInstr* preamble_start = NULL;
3856 if (is_top_level_sequence && (owner()->function().is_async_closure())) { 3916 if (is_top_level_sequence &&
3917 (function.IsAsyncClosure() || function.IsSyncGenClosure())) {
3857 JoinEntryInstr* preamble_end = new(I) JoinEntryInstr( 3918 JoinEntryInstr* preamble_end = new(I) JoinEntryInstr(
3858 owner()->AllocateBlockId(), owner()->try_index()); 3919 owner()->AllocateBlockId(), owner()->try_index());
3859 ASSERT(exit() != NULL); 3920 ASSERT(exit() != NULL);
3860 exit()->Goto(preamble_end); 3921 exit()->Goto(preamble_end);
3861 ASSERT(exit()->next()->IsGoto()); 3922 ASSERT(exit()->next()->IsGoto());
3862 preamble_start = exit()->next()->AsGoto(); 3923 preamble_start = exit()->next()->AsGoto();
3863 ASSERT(preamble_start->IsGoto()); 3924 ASSERT(preamble_start->IsGoto());
3864 exit_ = preamble_end; 3925 exit_ = preamble_end;
3865 } 3926 }
3866 3927
3867 intptr_t i = 0; 3928 intptr_t i = 0;
3868 while (is_open() && (i < node->length())) { 3929 while (is_open() && (i < node->length())) {
3869 EffectGraphVisitor for_effect(owner()); 3930 EffectGraphVisitor for_effect(owner());
3870 node->NodeAt(i++)->Visit(&for_effect); 3931 node->NodeAt(i++)->Visit(&for_effect);
3871 Append(for_effect); 3932 Append(for_effect);
3872 if (!is_open()) { 3933 if (!is_open()) {
3873 // E.g., because of a JumpNode. 3934 // E.g., because of a JumpNode.
3874 break; 3935 break;
3875 } 3936 }
3876 } 3937 }
3877 3938
3878 // Continuation part: 3939 // Continuation part:
3879 // After generating the CFG for the body we can create the preamble because we 3940 // After generating the CFG for the body we can create the preamble
3880 // know exactly how many continuation states we need. 3941 // because we know exactly how many continuation states we need.
3881 if (is_top_level_sequence && (owner()->function().is_async_closure())) { 3942 if (is_top_level_sequence &&
3943 (function.IsAsyncClosure() || function.IsSyncGenClosure())) {
3882 ASSERT(preamble_start != NULL); 3944 ASSERT(preamble_start != NULL);
3883 // We are at the top level. Fetch the corresponding scope. 3945 // We are at the top level. Fetch the corresponding scope.
3884 LocalScope* top_scope = node->scope(); 3946 LocalScope* top_scope = node->scope();
3885 LocalVariable* jump_var = top_scope->LookupVariable( 3947 LocalVariable* jump_var = top_scope->LookupVariable(
3886 Symbols::AwaitJumpVar(), false); 3948 Symbols::AwaitJumpVar(), false);
3887 ASSERT(jump_var != NULL && jump_var->is_captured()); 3949 ASSERT(jump_var != NULL && jump_var->is_captured());
3888
3889 Instruction* saved_entry = entry_; 3950 Instruction* saved_entry = entry_;
3890 Instruction* saved_exit = exit_; 3951 Instruction* saved_exit = exit_;
3891 entry_ = NULL; 3952 entry_ = NULL;
3892 exit_ = NULL; 3953 exit_ = NULL;
3893 3954
3894 LoadLocalNode* load_jump_count = new(I) LoadLocalNode( 3955 LoadLocalNode* load_jump_count =
3895 Scanner::kNoSourcePos, jump_var); 3956 new(I) LoadLocalNode(Scanner::kNoSourcePos, jump_var);
3896 ComparisonNode* check_jump_count; 3957 ComparisonNode* check_jump_count;
3897 const intptr_t num_await_states = owner()->await_joins()->length(); 3958 const intptr_t num_await_states = owner()->await_joins()->length();
3959
3898 LocalVariable* old_context = top_scope->LookupVariable( 3960 LocalVariable* old_context = top_scope->LookupVariable(
3899 Symbols::AwaitContextVar(), false); 3961 Symbols::AwaitContextVar(), false);
3900 LocalVariable* continuation_result = top_scope->LookupVariable(
3901 Symbols::AsyncOperationParam(), false);
3902 LocalVariable* continuation_error = top_scope->LookupVariable(
3903 Symbols::AsyncOperationErrorParam(), false);
3904 for (intptr_t i = 0; i < num_await_states; i++) { 3962 for (intptr_t i = 0; i < num_await_states; i++) {
3905 check_jump_count = new(I) ComparisonNode( 3963 check_jump_count = new(I) ComparisonNode(
3906 Scanner::kNoSourcePos, 3964 Scanner::kNoSourcePos,
3907 Token::kEQ, 3965 Token::kEQ,
3908 load_jump_count, 3966 load_jump_count,
3909 new(I) LiteralNode( 3967 new(I) LiteralNode(
3910 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i)))); 3968 Scanner::kNoSourcePos, Smi::ZoneHandle(I, Smi::New(i))));
3911 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos); 3969 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
3912 check_jump_count->Visit(&for_test); 3970 check_jump_count->Visit(&for_test);
3913 EffectGraphVisitor for_true(owner()); 3971 EffectGraphVisitor for_true(owner());
3914 EffectGraphVisitor for_false(owner()); 3972 EffectGraphVisitor for_false(owner());
3915 3973
3916 for_true.BuildAwaitJump(old_context, 3974 if (function.IsAsyncClosure()) {
3917 continuation_result, 3975 LocalVariable* result_param =
3918 continuation_error, 3976 top_scope->LookupVariable(Symbols::AsyncOperationParam(), false);
3919 (*owner()->await_levels())[i], 3977 LocalVariable* error_param =
3920 (*owner()->await_joins())[i]); 3978 top_scope->LookupVariable(Symbols::AsyncOperationErrorParam(),
3979 false);
3980 for_true.BuildAwaitJump(old_context,
3981 result_param,
3982 error_param,
3983 (*owner()->await_levels())[i],
3984 (*owner()->await_joins())[i]);
3985 } else {
3986 ASSERT(function.IsSyncGenClosure());
3987 LocalVariable* iterator_param =
3988 top_scope->LookupVariable(Symbols::IteratorParameter(), false);
3989 for_true.BuildYieldJump(old_context,
3990 iterator_param,
3991 (*owner()->await_levels())[i],
3992 (*owner()->await_joins())[i]);
3993 }
3921 Join(for_test, for_true, for_false); 3994 Join(for_test, for_true, for_false);
3922 3995
3923 if (i == 0) { 3996 if (i == 0) {
3924 // Manually link up the preamble start. 3997 // Manually link up the preamble start.
3925 preamble_start->previous()->set_next(for_test.entry()); 3998 preamble_start->previous()->set_next(for_test.entry());
3926 for_test.entry()->set_previous(preamble_start->previous()); 3999 for_test.entry()->set_previous(preamble_start->previous());
3927 } 4000 }
3928 if (i == (num_await_states - 1)) { 4001 if (i == (num_await_states - 1)) {
3929 // Link up preamble end. 4002 // Link up preamble end.
3930 if (exit_ == NULL) { 4003 if (exit_ == NULL) {
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
4311 Report::MessageF(Report::kBailout, 4384 Report::MessageF(Report::kBailout,
4312 Script::Handle(function.script()), 4385 Script::Handle(function.script()),
4313 function.token_pos(), 4386 function.token_pos(),
4314 "FlowGraphBuilder Bailout: %s %s", 4387 "FlowGraphBuilder Bailout: %s %s",
4315 String::Handle(function.name()).ToCString(), 4388 String::Handle(function.name()).ToCString(),
4316 reason); 4389 reason);
4317 UNREACHABLE(); 4390 UNREACHABLE();
4318 } 4391 }
4319 4392
4320 } // namespace dart 4393 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698