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

Unified Diff: runtime/vm/parser.cc

Issue 1980193002: Fix capturing variables in optimized compilations (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 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 side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698