Chromium Code Reviews| Index: runtime/vm/parser.cc |
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
| index 2ec2a489374abba8da7ebbeb7afe77f8a30383d8..e75934499b0ef021efd354d00c865d510b49959f 100644 |
| --- a/runtime/vm/parser.cc |
| +++ b/runtime/vm/parser.cc |
| @@ -7612,6 +7612,7 @@ AstNode* Parser::ParseFunctionStatement(bool is_literal) { |
| // Note that we cannot share the same closure function between the closurized |
| // and non-closurized versions of the same parent function. |
| Function& function = Function::ZoneHandle(Z); |
| + bool found_func = true; |
| // TODO(hausner): There could be two different closures at the given |
| // function_pos, one enclosed in a closurized function and one enclosed in the |
| // non-closurized version of this same function. |
| @@ -7620,6 +7621,7 @@ AstNode* Parser::ParseFunctionStatement(bool is_literal) { |
| // The function will be registered in the lookup table by the |
| // EffectGraphVisitor::VisitClosureNode when the newly allocated closure |
| // function has been properly setup. |
| + found_func = false; |
| function = Function::NewClosureFunction(*function_name, |
| innermost_function(), |
| function_pos); |
| @@ -7669,15 +7671,38 @@ AstNode* Parser::ParseFunctionStatement(bool is_literal) { |
| } |
| } |
| - // Parse the local function. |
| - SequenceNode* statements = Parser::ParseFunc(function, !is_literal); |
| - INC_STAT(thread(), num_functions_parsed, 1); |
| - // Now that the local function has formal parameters, lookup the signature |
| - Type& signature_type = Type::ZoneHandle(Z, function.SignatureType()); |
| - signature_type ^= ClassFinalizer::FinalizeType( |
| - current_class(), signature_type, ClassFinalizer::kCanonicalize); |
| - function.SetSignatureType(signature_type); |
| + Type& signature_type = Type::ZoneHandle(Z); |
| + SequenceNode* statements = NULL; |
| + if (!found_func) { |
| + // Parse the local function. As a side effect of the parsing, the |
| + // variables of this function's scope that are referenced by the local |
| + // function (and its inner nested functions) will be marked as captured. |
| + statements = Parser::ParseFunc(function, !is_literal); |
| + INC_STAT(thread(), num_functions_parsed, 1); |
| + |
| + // Now that the local function has formal parameters, lookup the signature |
| + signature_type = function.SignatureType(); |
| + signature_type ^= ClassFinalizer::FinalizeType( |
| + current_class(), signature_type, ClassFinalizer::kCanonicalize); |
| + function.SetSignatureType(signature_type); |
| + } else { |
| + // The local function was parsed before. The captrued variables are |
|
regis
2016/05/16 22:42:15
captured
|
| + // saved in the function's context scope. Iterate over the context scope |
| + // and mark its variables as captured. |
| + const ContextScope& context_scope = |
| + ContextScope::Handle(Z, function.context_scope()); |
| + ASSERT(!context_scope.IsNull()); |
| + String& var_name = String::Handle(Z); |
| + for (int i = 0; i < context_scope.num_variables(); i++) { |
| + var_name = context_scope.NameAt(i); |
| + LocalVariable* v = LookupLocalScope(var_name); |
| + ASSERT(v != NULL); |
| + current_block_->scope->CaptureVariable(v); |
| + } |
| + SkipFunctionLiteral(); |
| + signature_type = function.SignatureType(); |
| + } |
| // Local functions are registered in the enclosing class, but |
| // ignored during class finalization. The enclosing class has |
| @@ -7732,8 +7757,9 @@ AstNode* Parser::ParseFunctionStatement(bool is_literal) { |
| // variables are not relevant for the compilation of the enclosing function. |
| // This pruning is done by omitting to hook the local scope in its parent |
| // scope in the constructor of LocalScope. |
| - AstNode* closure = new(Z) ClosureNode( |
| - function_pos, function, NULL, statements->scope()); |
| + AstNode* closure = |
| + new(Z) ClosureNode(function_pos, function, NULL, |
| + statements != NULL ? statements->scope() : NULL); |
| if (function_variable == NULL) { |
| ASSERT(is_literal); |