Commit bfa90f7e authored by Adam Klein's avatar Adam Klein Committed by Commit Bot

Move function name var initialization to BytecodeGenerator

Besides avoiding the weird hack of inserting a statement at the 0th
index of the function body, we also avoid allocating (and initializing)
the variable if it's unreferenced (which I'd wager is the common case).

Bug: v8:6092
Change-Id: If917d422bb4818cf21e8272aa786ca84d4472802
Reviewed-on: https://chromium-review.googlesource.com/784092Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Commit-Queue: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49646}
parent 87e7fc94
...@@ -2235,8 +2235,10 @@ void DeclarationScope::AllocateLocals() { ...@@ -2235,8 +2235,10 @@ void DeclarationScope::AllocateLocals() {
// allocated in the context, it must be the last slot in the context, // allocated in the context, it must be the last slot in the context,
// because of the current ScopeInfo implementation (see // because of the current ScopeInfo implementation (see
// ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
if (function_ != nullptr) { if (function_ != nullptr && MustAllocate(function_)) {
AllocateNonParameterLocal(function_); AllocateNonParameterLocal(function_);
} else {
function_ = nullptr;
} }
DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) || DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) ||
......
...@@ -762,10 +762,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope { ...@@ -762,10 +762,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
// The variable holding the function literal for named function // The variable holding the function literal for named function
// literals, or nullptr. Only valid for function scopes. // literals, or nullptr. Only valid for function scopes.
Variable* function_var() const { Variable* function_var() const { return function_; }
DCHECK(is_function_scope());
return function_;
}
Variable* generator_object_var() const { Variable* generator_object_var() const {
DCHECK(is_function_scope() || is_module_scope()); DCHECK(is_function_scope() || is_module_scope());
......
...@@ -1016,7 +1016,9 @@ void BytecodeGenerator::GenerateBytecodeBody() { ...@@ -1016,7 +1016,9 @@ void BytecodeGenerator::GenerateBytecodeBody() {
Variable* rest_parameter = closure_scope()->rest_parameter(); Variable* rest_parameter = closure_scope()->rest_parameter();
VisitRestArgumentsArray(rest_parameter); VisitRestArgumentsArray(rest_parameter);
// Build assignment to {.this_function} variable if it is used. // Build assignment to the function name or {.this_function}
// variables if used.
VisitThisFunctionVariable(closure_scope()->function_var());
VisitThisFunctionVariable(closure_scope()->this_function_var()); VisitThisFunctionVariable(closure_scope()->this_function_var());
// Build assignment to {new.target} variable if it is used. // Build assignment to {new.target} variable if it is used.
......
...@@ -4141,18 +4141,6 @@ void ParserBase<Impl>::ParseFunctionBody( ...@@ -4141,18 +4141,6 @@ void ParserBase<Impl>::ParseFunctionBody(
typename ParserBase<Impl>::StatementListT result, IdentifierT function_name, typename ParserBase<Impl>::StatementListT result, IdentifierT function_name,
int pos, const FormalParametersT& parameters, FunctionKind kind, int pos, const FormalParametersT& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) { FunctionLiteral::FunctionType function_type, bool* ok) {
static const int kFunctionNameAssignmentIndex = 0;
if (function_type == FunctionLiteral::kNamedExpression) {
DCHECK(!impl()->IsNull(function_name));
// If we have a named function expression, we add a local variable
// declaration to the body of the function with the name of the
// function and let it refer to the function itself (closure).
// Not having parsed the function body, the language mode may still change,
// so we reserve a spot and create the actual const assignment later.
DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
result->Add(impl()->NullStatement(), zone());
}
DeclarationScope* function_scope = scope()->AsDeclarationScope(); DeclarationScope* function_scope = scope()->AsDeclarationScope();
DeclarationScope* inner_scope = function_scope; DeclarationScope* inner_scope = function_scope;
BlockT inner_block = impl()->NullStatement(); BlockT inner_block = impl()->NullStatement();
...@@ -4233,9 +4221,7 @@ void ParserBase<Impl>::ParseFunctionBody( ...@@ -4233,9 +4221,7 @@ void ParserBase<Impl>::ParseFunctionBody(
function_scope->DeclareArguments(ast_value_factory()); function_scope->DeclareArguments(ast_value_factory());
} }
impl()->CreateFunctionNameAssignment(function_name, pos, function_type, impl()->DeclareFunctionNameVar(function_name, function_type, function_scope);
function_scope, result,
kFunctionNameAssignmentIndex);
} }
template <typename Impl> template <typename Impl>
......
...@@ -1828,25 +1828,13 @@ void Parser::ParseAndRewriteAsyncGeneratorFunctionBody( ...@@ -1828,25 +1828,13 @@ void Parser::ParseAndRewriteAsyncGeneratorFunctionBody(
zone()); zone());
} }
void Parser::CreateFunctionNameAssignment( void Parser::DeclareFunctionNameVar(const AstRawString* function_name,
const AstRawString* function_name, int pos, FunctionLiteral::FunctionType function_type,
FunctionLiteral::FunctionType function_type, DeclarationScope* function_scope) {
DeclarationScope* function_scope, ZoneList<Statement*>* result, int index) { if (function_type == FunctionLiteral::kNamedExpression &&
if (function_type == FunctionLiteral::kNamedExpression) { function_scope->LookupLocal(function_name) == nullptr) {
StatementT statement = factory()->NewEmptyStatement(kNoSourcePosition); DCHECK_EQ(function_scope, scope());
if (function_scope->LookupLocal(function_name) == nullptr) { function_scope->DeclareFunctionVar(function_name);
// 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);
}
result->Set(index, statement);
} }
} }
......
...@@ -346,10 +346,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ...@@ -346,10 +346,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
void ParseAndRewriteAsyncGeneratorFunctionBody(int pos, FunctionKind kind, void ParseAndRewriteAsyncGeneratorFunctionBody(int pos, FunctionKind kind,
ZoneList<Statement*>* body, ZoneList<Statement*>* body,
bool* ok); bool* ok);
void CreateFunctionNameAssignment(const AstRawString* function_name, int pos, void DeclareFunctionNameVar(const AstRawString* function_name,
FunctionLiteral::FunctionType function_type, FunctionLiteral::FunctionType function_type,
DeclarationScope* function_scope, DeclarationScope* function_scope);
ZoneList<Statement*>* result, int index);
Statement* DeclareFunction(const AstRawString* variable_name, Statement* DeclareFunction(const AstRawString* variable_name,
FunctionLiteral* function, VariableMode mode, FunctionLiteral* function, VariableMode mode,
......
...@@ -207,7 +207,7 @@ PreParser::PreParseResult PreParser::PreParseFunction( ...@@ -207,7 +207,7 @@ PreParser::PreParseResult PreParser::PreParseFunction(
if (!IsArrowFunction(kind) && track_unresolved_variables_ && if (!IsArrowFunction(kind) && track_unresolved_variables_ &&
result == kLazyParsingComplete) { result == kLazyParsingComplete) {
CreateFunctionNameAssignment(function_name, function_type, function_scope); DeclareFunctionNameVar(function_name, function_type, function_scope);
// Declare arguments after parsing the function since lexical 'arguments' // Declare arguments after parsing the function since lexical 'arguments'
// masks the arguments object. Declare arguments before declaring the // masks the arguments object. Declare arguments before declaring the
......
...@@ -1073,27 +1073,24 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1073,27 +1073,24 @@ class PreParser : public ParserBase<PreParser> {
int pos, FunctionKind kind, PreParserStatementList body, bool* ok) { int pos, FunctionKind kind, PreParserStatementList body, bool* ok) {
ParseStatementList(body, Token::RBRACE, ok); ParseStatementList(body, Token::RBRACE, ok);
} }
V8_INLINE void CreateFunctionNameAssignment( V8_INLINE void DeclareFunctionNameVar(
const AstRawString* function_name, const AstRawString* function_name,
FunctionLiteral::FunctionType function_type, FunctionLiteral::FunctionType function_type,
DeclarationScope* function_scope) { DeclarationScope* function_scope) {
if (track_unresolved_variables_ && if (track_unresolved_variables_ &&
function_type == FunctionLiteral::kNamedExpression) { function_type == FunctionLiteral::kNamedExpression &&
if (function_scope->LookupLocal(function_name) == nullptr) { function_scope->LookupLocal(function_name) == nullptr) {
DCHECK_EQ(function_scope, scope()); DCHECK_EQ(function_scope, scope());
Variable* fvar = function_scope->DeclareFunctionVar(function_name); function_scope->DeclareFunctionVar(function_name);
fvar->set_is_used();
}
} }
} }
V8_INLINE void CreateFunctionNameAssignment( V8_INLINE void DeclareFunctionNameVar(
const PreParserIdentifier& function_name, int pos, const PreParserIdentifier& function_name,
FunctionLiteral::FunctionType function_type, FunctionLiteral::FunctionType function_type,
DeclarationScope* function_scope, PreParserStatementList result, DeclarationScope* function_scope) {
int index) { DeclareFunctionNameVar(function_name.string_, function_type,
CreateFunctionNameAssignment(function_name.string_, function_type, function_scope);
function_scope);
} }
V8_INLINE PreParserExpression RewriteDoExpression(PreParserStatement body, V8_INLINE PreParserExpression RewriteDoExpression(PreParserStatement body,
......
...@@ -12,12 +12,11 @@ snippet: " ...@@ -12,12 +12,11 @@ snippet: "
f = function f() {}; f = function f() {};
f(); f();
" "
frame size: 1 frame size: 0
parameter count: 1 parameter count: 1
bytecode array length: 6 bytecode array length: 3
bytecodes: [ bytecodes: [
/* 21 E> */ B(StackCheck), /* 21 E> */ B(StackCheck),
B(Mov), R(closure), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 25 S> */ B(Return), /* 25 S> */ B(Return),
] ]
...@@ -36,8 +35,8 @@ frame size: 1 ...@@ -36,8 +35,8 @@ frame size: 1
parameter count: 1 parameter count: 1
bytecode array length: 7 bytecode array length: 7
bytecodes: [ bytecodes: [
/* 21 E> */ B(StackCheck),
B(Mov), R(closure), R(0), B(Mov), R(closure), R(0),
/* 21 E> */ B(StackCheck),
/* 26 S> */ B(Ldar), R(0), /* 26 S> */ B(Ldar), R(0),
/* 35 S> */ B(Return), /* 35 S> */ B(Return),
] ]
......
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