Commit 65bae443 authored by verwaest's avatar verwaest Committed by Commit bot

Add function-var to variables_ so LookupRecursive doesn't need to special-case it

After parsing a function, if there's no masking declaration in the function scope, DeclareFunctionVar will also bind the function name to a variable. It will either bind it to the const/const-legacy function_ variable, or to a dynamic non-local if the function calls sloppy eval.

Even if the variable is masked or sloppy eval is called, we still declare the function-var. The client immediately sets up the variable by assigning the resulting function to it.

BUG=v8:5209

Review-Url: https://codereview.chromium.org/2274133002
Cr-Commit-Position: refs/heads/master@{#39581}
parent 15b4b218
......@@ -624,10 +624,16 @@ void DeclarationScope::DeclareDefaultFunctionVariables(
Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) {
DCHECK(is_function_scope());
DCHECK_NULL(function_);
DCHECK_NULL(variables_.Lookup(name));
VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
: NORMAL_VARIABLE;
function_ =
new (zone()) Variable(this, name, CONST, kind, kCreatedInitialized);
if (calls_sloppy_eval()) {
NonLocal(name, DYNAMIC);
} else {
variables_.Add(function_);
}
return function_;
}
......@@ -766,7 +772,15 @@ Variable* Scope::LookupInScopeInfo(const AstRawString* name) {
index = scope_info_->ModuleIndex(name_handle, &mode, &init_flag,
&maybe_assigned_flag);
}
if (index < 0) return nullptr; // Nowhere found.
if (index < 0) {
index = scope_info_->FunctionContextSlotIndex(*name_handle);
if (index < 0) return nullptr; // Nowhere found.
Variable* var = AsDeclarationScope()->DeclareFunctionVar(name);
DCHECK_EQ(CONST, var->mode());
var->AllocateTo(VariableLocation::CONTEXT, index);
return variables_.Lookup(name);
}
VariableKind kind = NORMAL_VARIABLE;
if (location == VariableLocation::CONTEXT &&
......@@ -782,22 +796,6 @@ Variable* Scope::LookupInScopeInfo(const AstRawString* name) {
return var;
}
Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) {
if (function_ != nullptr && function_->raw_name() == name) {
return function_;
} else if (!scope_info_.is_null()) {
// If we are backed by a scope info, try to lookup the variable there.
int index = scope_info_->FunctionContextSlotIndex(*(name->string()));
if (index < 0) return nullptr;
Variable* var = DeclareFunctionVar(name);
var->AllocateTo(VariableLocation::CONTEXT, index);
return var;
} else {
return nullptr;
}
}
Variable* Scope::Lookup(const AstRawString* name) {
for (Scope* scope = this;
scope != NULL;
......@@ -1455,16 +1453,6 @@ Variable* Scope::LookupRecursive(VariableProxy* proxy, Scope* outer_scope_end) {
// remains the same.)
if (var != nullptr) return var;
// We did not find a variable locally. Check against the function variable, if
// any.
if (is_function_scope()) {
var = AsDeclarationScope()->LookupFunctionVar(proxy->raw_name());
if (var != nullptr) {
if (calls_sloppy_eval()) return NonLocal(proxy->raw_name(), DYNAMIC);
return var;
}
}
if (outer_scope_ == outer_scope_end) {
// We may just be trying to find all free variables. In that case, don't
// declare them in the outer scope.
......
......@@ -638,15 +638,14 @@ class DeclarationScope : public Scope {
void DeclareArguments(AstValueFactory* ast_value_factory);
void DeclareDefaultFunctionVariables(AstValueFactory* ast_value_factory);
// This lookup corresponds to a lookup in the "intermediate" scope sitting
// between this scope and the outer scope. (ECMA-262, 3rd., requires that
// the name of named function literal is kept in an intermediate scope
// in between this scope and the next outer scope.)
Variable* LookupFunctionVar(const AstRawString* name);
// Declare the function variable for a function literal. This variable
// is in an intermediate scope between this function scope and the the
// outer scope. Only possible for function scopes; at most one variable.
//
// This function needs to be called after all other variables have been
// declared in the scope. It will add a variable for {name} to {variables_};
// either the function variable itself, or a non-local in case the function
// calls sloppy eval.
Variable* DeclareFunctionVar(const AstRawString* name);
// Declare a parameter in this scope. When there are duplicated
......
......@@ -3662,17 +3662,22 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
}
if (function_type == FunctionLiteral::kNamedExpression) {
// Now that we know the language mode, we can create the const assignment
// in the previously reserved spot.
DCHECK_EQ(function_scope, scope());
Variable* fvar = function_scope->DeclareFunctionVar(function_name);
VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
result->Set(kFunctionNameAssignmentIndex,
factory()->NewExpressionStatement(
factory()->NewAssignment(Token::INIT, fproxy,
factory()->NewThisFunction(pos),
kNoSourcePosition),
kNoSourcePosition));
Statement* statement;
if (function_scope->LookupLocal(function_name) == nullptr) {
// Now that we know the language mode, we can create the const assignment
// in the previously reserved spot.
DCHECK_EQ(function_scope, scope());
Variable* fvar = function_scope->DeclareFunctionVar(function_name);
VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
statement = factory()->NewExpressionStatement(
factory()->NewAssignment(Token::INIT, fproxy,
factory()->NewThisFunction(pos),
kNoSourcePosition),
kNoSourcePosition);
} else {
statement = factory()->NewEmptyStatement(kNoSourcePosition);
}
result->Set(kFunctionNameAssignmentIndex, statement);
}
MarkCollectedTailCallExpressions();
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function() {
function f() {
{
function f() { return 42 }
}
function g() { return f }
return g;
}
var g = f();
var inner_f = g();
assertEquals(42, inner_f());
})();
(function() {
var y = 100;
var z = (function y() { return y; });
assertEquals(z, z());
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment