Commit f7d80884 authored by yangguo's avatar yangguo Committed by Commit bot

Create function name const assignment after parsing language mode.

Otherwise we may choose sloppy const or strict const depending on
whether the function is parsed the first time.

R=mvstanton@chromium.org
BUG=v8:4336
LOG=N

Review URL: https://codereview.chromium.org/1260053004

Cr-Commit-Position: refs/heads/master@{#29966}
parent 99a53f73
......@@ -1277,6 +1277,57 @@ void Code::VerifyEmbeddedObjects(VerifyMode mode) {
}
// Verify that the debugger can redirect old code to the new code.
void Code::VerifyRecompiledCode(Code* old_code, Code* new_code) {
if (old_code->kind() != FUNCTION) return;
if (new_code->kind() != FUNCTION) return;
static const int mask = RelocInfo::kCodeTargetMask;
Isolate* isolate = old_code->GetIsolate();
RelocIterator old_it(old_code, mask);
RelocIterator new_it(new_code, mask);
Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck);
while (!old_it.done()) {
RelocInfo* rinfo = old_it.rinfo();
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
CHECK(!target->is_handler() && !target->is_inline_cache_stub());
if (target == stack_check) break;
old_it.next();
}
while (!new_it.done()) {
RelocInfo* rinfo = new_it.rinfo();
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
CHECK(!target->is_handler() && !target->is_inline_cache_stub());
if (target == stack_check) break;
new_it.next();
}
// Either both are done because there is no stack check.
// Or we are past the prologue for both.
CHECK_EQ(new_it.done(), old_it.done());
// After the prologue, each call in the old code has a corresponding call
// in the new code.
while (!old_it.done() && !new_it.done()) {
Code* old_target =
Code::GetCodeFromTargetAddress(old_it.rinfo()->target_address());
Code* new_target =
Code::GetCodeFromTargetAddress(new_it.rinfo()->target_address());
CHECK_EQ(old_target->kind(), new_target->kind());
if (!old_target->is_handler() && !old_target->is_inline_cache_stub()) {
CHECK_EQ(old_target, new_target);
}
old_it.next();
new_it.next();
}
// Both are done at the same time.
CHECK_EQ(new_it.done(), old_it.done());
}
#endif // DEBUG
} // namespace internal
......
......@@ -5228,7 +5228,10 @@ void SharedFunctionInfo::ReplaceCode(Code* value) {
flusher->EvictCandidate(this);
}
#ifdef DEBUG
DCHECK(code()->gc_metadata() == NULL && value->gc_metadata() == NULL);
Code::VerifyRecompiledCode(code(), value);
#endif // DEBUG
set_code(value);
......
......@@ -4992,6 +4992,7 @@ class Code: public HeapObject {
#ifdef DEBUG
enum VerifyMode { kNoContextSpecificPointers, kNoContextRetainingPointers };
void VerifyEmbeddedObjects(VerifyMode mode = kNoContextRetainingPointers);
static void VerifyRecompiledCode(Code* old_code, Code* new_code);
#endif // DEBUG
inline bool CanContainWeakObjects() {
......
......@@ -4039,31 +4039,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
formals_end_position, CHECK_OK);
Expect(Token::LBRACE, CHECK_OK);
// 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).
// NOTE: We create a proxy and resolve it here so that in the
// future we can change the AST to only refer to VariableProxies
// instead of Variables and Proxis as is the case now.
Variable* fvar = NULL;
Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
bool use_strict_const = is_strict(language_mode) ||
(!allow_legacy_const() && allow_harmony_sloppy());
if (use_strict_const) {
fvar_init_op = Token::INIT_CONST;
}
VariableMode fvar_mode = use_strict_const ? CONST : CONST_LEGACY;
DCHECK(function_name != NULL);
fvar = new (zone())
Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
kCreatedInitialized, kNotAssigned);
VariableProxy* proxy = factory()->NewVariableProxy(fvar);
VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
scope_->DeclareFunctionVar(fvar_declaration);
}
// Determine if the function can be parsed lazily. Lazy parsing is different
// from lazy compilation; we need to parse more eagerly than we compile.
......@@ -4127,8 +4102,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
}
}
if (!is_lazily_parsed) {
body = ParseEagerFunctionBody(function_name, pos, formals, fvar,
fvar_init_op, kind, CHECK_OK);
body = ParseEagerFunctionBody(function_name, pos, formals, kind,
function_type, CHECK_OK);
materialized_literal_count = function_state.materialized_literal_count();
expected_property_count = function_state.expected_property_count();
}
......@@ -4344,23 +4319,24 @@ Block* Parser::BuildParameterInitializationBlock(
ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
const AstRawString* function_name, int pos,
const ParserFormalParameters& parameters, Variable* fvar,
Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
const ParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) {
// Everything inside an eagerly parsed function will be parsed eagerly
// (see comment above).
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
if (fvar != NULL) {
VariableProxy* fproxy = scope_->NewUnresolved(factory(), function_name);
fproxy->BindTo(fvar);
result->Add(factory()->NewExpressionStatement(
factory()->NewAssignment(fvar_init_op,
fproxy,
factory()->NewThisFunction(pos),
RelocInfo::kNoPosition),
RelocInfo::kNoPosition), zone());
}
static const int kFunctionNameAssignmentIndex = 0;
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
DCHECK(function_name != NULL);
// 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(NULL, zone());
}
// For concise constructors, check that they are constructed,
// not called.
......@@ -4445,6 +4421,37 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
result->Add(inner_block, zone());
}
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
// Now that we know the language mode, we can create the const assignment
// in the previously reserved spot.
// NOTE: We create a proxy and resolve it here so that in the
// future we can change the AST to only refer to VariableProxies
// instead of Variables and Proxies as is the case now.
Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
bool use_strict_const = is_strict(scope_->language_mode()) ||
(!allow_legacy_const() && allow_harmony_sloppy());
if (use_strict_const) {
fvar_init_op = Token::INIT_CONST;
}
VariableMode fvar_mode = use_strict_const ? CONST : CONST_LEGACY;
Variable* fvar = new (zone())
Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
kCreatedInitialized, kNotAssigned);
VariableProxy* proxy = factory()->NewVariableProxy(fvar);
VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
scope_->DeclareFunctionVar(fvar_declaration);
VariableProxy* fproxy = scope_->NewUnresolved(factory(), function_name);
fproxy->BindTo(fvar);
result->Set(kFunctionNameAssignmentIndex,
factory()->NewExpressionStatement(
factory()->NewAssignment(fvar_init_op, fproxy,
factory()->NewThisFunction(pos),
RelocInfo::kNoPosition),
RelocInfo::kNoPosition));
}
return result;
}
......
......@@ -802,8 +802,8 @@ class ParserTraits {
Scanner::BookmarkScope* bookmark = nullptr);
V8_INLINE ZoneList<Statement*>* ParseEagerFunctionBody(
const AstRawString* name, int pos,
const ParserFormalParameters& parameters,
Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok);
const ParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok);
ClassLiteral* ParseClassLiteral(const AstRawString* name,
Scanner::Location class_name_location,
......@@ -1160,8 +1160,8 @@ class Parser : public ParserBase<ParserTraits> {
// Consumes the ending }.
ZoneList<Statement*>* ParseEagerFunctionBody(
const AstRawString* function_name, int pos,
const ParserFormalParameters& parameters,
Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok);
const ParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok);
void ThrowPendingError(Isolate* isolate, Handle<Script> script);
......@@ -1225,11 +1225,10 @@ void ParserTraits::SkipLazyFunctionBody(int* materialized_literal_count,
ZoneList<Statement*>* ParserTraits::ParseEagerFunctionBody(
const AstRawString* name, int pos,
const ParserFormalParameters& parameters, Variable* fvar,
Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
return parser_->ParseEagerFunctionBody(name, pos, parameters, fvar,
fvar_init_op, kind, ok);
const AstRawString* name, int pos, const ParserFormalParameters& parameters,
FunctionKind kind, FunctionLiteral::FunctionType function_type, bool* ok) {
return parser_->ParseEagerFunctionBody(name, pos, parameters, kind,
function_type, ok);
}
void ParserTraits::CheckConflictingVarDeclarations(v8::internal::Scope* scope,
......
......@@ -1601,8 +1601,8 @@ class PreParserTraits {
V8_INLINE PreParserStatementList ParseEagerFunctionBody(
PreParserIdentifier function_name, int pos,
const PreParserFormalParameters& parameters,
Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok);
const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok);
V8_INLINE void ParseArrowFunctionFormalParameters(
PreParserFormalParameters* parameters,
......@@ -1786,11 +1786,10 @@ class PreParser : public ParserBase<PreParserTraits> {
V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count,
int* expected_property_count, bool* ok);
V8_INLINE PreParserStatementList
ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
const PreParserFormalParameters& parameters,
Variable* fvar, Token::Value fvar_init_op,
FunctionKind kind, bool* ok);
V8_INLINE PreParserStatementList ParseEagerFunctionBody(
PreParserIdentifier function_name, int pos,
const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok);
Expression ParseFunctionLiteral(
Identifier name, Scanner::Location function_name_location,
......@@ -1845,8 +1844,8 @@ void PreParserTraits::ParseArrowFunctionFormalParameters(
PreParserStatementList PreParser::ParseEagerFunctionBody(
PreParserIdentifier function_name, int pos,
const PreParserFormalParameters& parameters,
Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) {
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
ParseStatementList(Token::RBRACE, ok);
......@@ -1859,10 +1858,10 @@ PreParserStatementList PreParser::ParseEagerFunctionBody(
PreParserStatementList PreParserTraits::ParseEagerFunctionBody(
PreParserIdentifier function_name, int pos,
const PreParserFormalParameters& parameters,
Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
return pre_parser_->ParseEagerFunctionBody(
function_name, pos, parameters, fvar, fvar_init_op, kind, ok);
const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) {
return pre_parser_->ParseEagerFunctionBody(function_name, pos, parameters,
kind, function_type, ok);
}
......@@ -3768,7 +3767,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(
} else {
body = this->ParseEagerFunctionBody(
this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters,
NULL, Token::INIT_VAR, kArrowFunction, CHECK_OK);
kArrowFunction, FunctionLiteral::ANONYMOUS_EXPRESSION, CHECK_OK);
materialized_literal_count =
function_state.materialized_literal_count();
expected_property_count = function_state.expected_property_count();
......
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