}
+// 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
flusher->EvictCandidate(this);
}
+#ifdef DEBUG
DCHECK(code()->gc_metadata() == NULL && value->gc_metadata() == NULL);
+ Code::VerifyRecompiledCode(code(), value);
+#endif // DEBUG
set_code(value);
#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() {
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.
}
}
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();
}
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.
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;
}
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,
// 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);
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,
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,
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,
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);
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);
}
} 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();