Don't dereference handles in DoParseLazy

This will allow for using DoParseLazy on a background thread, so we can
also parse inner functions on the background thread.

BUG=v8:5215
R=adamk@chromium.org,marja@chromium.org

Review-Url: https://codereview.chromium.org/2201423002
Cr-Commit-Position: refs/heads/master@{#38332}
This commit is contained in:
jochen 2016-08-04 01:51:29 -07:00 committed by Commit bot
parent 94ad974df8
commit 52cc7ddfba
2 changed files with 85 additions and 33 deletions

View File

@ -52,6 +52,9 @@ ParseInfo::ParseInfo(Zone* zone)
unicode_cache_(nullptr), unicode_cache_(nullptr),
stack_limit_(0), stack_limit_(0),
hash_seed_(0), hash_seed_(0),
compiler_hints_(0),
start_position_(0),
end_position_(0),
isolate_(nullptr), isolate_(nullptr),
cached_data_(nullptr), cached_data_(nullptr),
ast_value_factory_(nullptr), ast_value_factory_(nullptr),
@ -70,6 +73,11 @@ ParseInfo::ParseInfo(Zone* zone, Handle<SharedFunctionInfo> shared)
set_lazy(); set_lazy();
set_hash_seed(isolate_->heap()->HashSeed()); set_hash_seed(isolate_->heap()->HashSeed());
set_is_named_expression(shared->is_named_expression());
set_calls_eval(shared->scope_info()->CallsEval());
set_compiler_hints(shared->compiler_hints());
set_start_position(shared->start_position());
set_end_position(shared->end_position());
set_stack_limit(isolate_->stack_guard()->real_climit()); set_stack_limit(isolate_->stack_guard()->real_climit());
set_unicode_cache(isolate_->unicode_cache()); set_unicode_cache(isolate_->unicode_cache());
set_language_mode(shared->language_mode()); set_language_mode(shared->language_mode());
@ -96,6 +104,26 @@ ParseInfo::ParseInfo(Zone* zone, Handle<Script> script) : ParseInfo(zone) {
} }
} }
bool ParseInfo::is_declaration() const {
return (compiler_hints_ & (1 << SharedFunctionInfo::kIsDeclaration)) != 0;
}
bool ParseInfo::is_arrow() const {
return (compiler_hints_ & (1 << SharedFunctionInfo::kIsArrow)) != 0;
}
bool ParseInfo::is_async() const {
return (compiler_hints_ & (1 << SharedFunctionInfo::kIsAsyncFunction)) != 0;
}
bool ParseInfo::is_default_constructor() const {
return (compiler_hints_ & (1 << SharedFunctionInfo::kIsDefaultConstructor)) !=
0;
}
FunctionKind ParseInfo::function_kind() const {
return SharedFunctionInfo::FunctionKindBits::decode(compiler_hints_);
}
FunctionEntry ParseData::GetFunctionEntry(int start) { FunctionEntry ParseData::GetFunctionEntry(int start) {
// The current pre-data entry must be a FunctionEntry with the given // The current pre-data entry must be a FunctionEntry with the given
@ -1080,7 +1108,13 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
stream.reset(new GenericStringUtf16CharacterStream( stream.reset(new GenericStringUtf16CharacterStream(
source, shared_info->start_position(), shared_info->end_position())); source, shared_info->start_position(), shared_info->end_position()));
} }
result = DoParseLazy(isolate, info, stream.get()); Handle<String> name(String::cast(shared_info->name()));
result = DoParseLazy(isolate, info, ast_value_factory()->GetString(name),
stream.get());
if (result != nullptr) {
Handle<String> inferred_name(shared_info->inferred_name());
result->set_inferred_name(inferred_name);
}
} }
if (FLAG_trace_parse && result != NULL) { if (FLAG_trace_parse && result != NULL) {
@ -1091,30 +1125,27 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
return result; return result;
} }
static FunctionLiteral::FunctionType ComputeFunctionType( static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) {
Handle<SharedFunctionInfo> shared_info) { if (info->is_declaration()) {
if (shared_info->is_declaration()) {
return FunctionLiteral::kDeclaration; return FunctionLiteral::kDeclaration;
} else if (shared_info->is_named_expression()) { } else if (info->is_named_expression()) {
return FunctionLiteral::kNamedExpression; return FunctionLiteral::kNamedExpression;
} else if (IsConciseMethod(shared_info->kind()) || } else if (IsConciseMethod(info->function_kind()) ||
IsAccessorFunction(shared_info->kind())) { IsAccessorFunction(info->function_kind())) {
return FunctionLiteral::kAccessorOrMethod; return FunctionLiteral::kAccessorOrMethod;
} }
return FunctionLiteral::kAnonymousExpression; return FunctionLiteral::kAnonymousExpression;
} }
FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info, FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
const AstRawString* raw_name,
Utf16CharacterStream* source) { Utf16CharacterStream* source) {
Handle<SharedFunctionInfo> shared_info = info->shared_info();
scanner_.Initialize(source); scanner_.Initialize(source);
DCHECK_NULL(scope_state_); DCHECK_NULL(scope_state_);
DCHECK_NULL(target_stack_); DCHECK_NULL(target_stack_);
Handle<String> name(String::cast(shared_info->name()));
DCHECK(ast_value_factory()); DCHECK(ast_value_factory());
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
const AstRawString* raw_name = ast_value_factory()->GetString(name);
fni_->PushEnclosingName(raw_name); fni_->PushEnclosingName(raw_name);
ParsingModeScope parsing_mode(this, PARSE_EAGERLY); ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
@ -1127,16 +1158,14 @@ FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
Scope* scope = original_scope_; Scope* scope = original_scope_;
DCHECK(scope); DCHECK(scope);
FunctionState function_state(&function_state_, &scope_state_, scope, FunctionState function_state(&function_state_, &scope_state_, scope,
shared_info->kind()); info->function_kind());
DCHECK(is_sloppy(scope->language_mode()) || DCHECK(is_sloppy(scope->language_mode()) ||
is_strict(info->language_mode())); is_strict(info->language_mode()));
DCHECK(info->language_mode() == shared_info->language_mode()); FunctionLiteral::FunctionType function_type = ComputeFunctionType(info);
FunctionLiteral::FunctionType function_type =
ComputeFunctionType(shared_info);
bool ok = true; bool ok = true;
if (shared_info->is_arrow()) { if (info->is_arrow()) {
bool is_async = allow_harmony_async_await() && shared_info->is_async(); bool is_async = allow_harmony_async_await() && info->is_async();
if (is_async) { if (is_async) {
DCHECK(!scanner()->HasAnyLineTerminatorAfterNext()); DCHECK(!scanner()->HasAnyLineTerminatorAfterNext());
if (!Check(Token::ASYNC)) { if (!Check(Token::ASYNC)) {
@ -1156,12 +1185,12 @@ FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
// not passing the ScopeInfo to the Scope constructor. // not passing the ScopeInfo to the Scope constructor.
// TODO(adamk): Remove these calls once the above NewScope call // TODO(adamk): Remove these calls once the above NewScope call
// passes the ScopeInfo. // passes the ScopeInfo.
if (shared_info->scope_info()->CallsEval()) { if (info->calls_eval()) {
scope->RecordEvalCall(); scope->RecordEvalCall();
} }
SetLanguageMode(scope, shared_info->language_mode()); SetLanguageMode(scope, info->language_mode());
scope->set_start_position(shared_info->start_position()); scope->set_start_position(info->start_position());
ExpressionClassifier formals_classifier(this); ExpressionClassifier formals_classifier(this);
ParserFormalParameters formals(scope); ParserFormalParameters formals(scope);
Checkpoint checkpoint(this); Checkpoint checkpoint(this);
@ -1197,7 +1226,7 @@ FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
// concise body happens to be a valid expression. This is a problem // concise body happens to be a valid expression. This is a problem
// only for arrow functions with single expression bodies, since there // only for arrow functions with single expression bodies, since there
// is no end token such as "}" for normal functions. // is no end token such as "}" for normal functions.
if (scanner()->location().end_pos == shared_info->end_position()) { if (scanner()->location().end_pos == info->end_position()) {
// The pre-parser saw an arrow function here, so the full parser // The pre-parser saw an arrow function here, so the full parser
// must produce a FunctionLiteral. // must produce a FunctionLiteral.
DCHECK(expression->IsFunctionLiteral()); DCHECK(expression->IsFunctionLiteral());
@ -1207,17 +1236,16 @@ FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
} }
} }
} }
} else if (shared_info->is_default_constructor()) { } else if (info->is_default_constructor()) {
DCHECK_EQ(this->scope(), scope); DCHECK_EQ(this->scope(), scope);
result = DefaultConstructor( result = DefaultConstructor(
raw_name, IsSubclassConstructor(shared_info->kind()), raw_name, IsSubclassConstructor(info->function_kind()),
shared_info->start_position(), shared_info->end_position(), info->start_position(), info->end_position(), info->language_mode());
shared_info->language_mode());
} else { } else {
result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(), result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
kSkipFunctionNameCheck, shared_info->kind(), kSkipFunctionNameCheck,
kNoSourcePosition, function_type, info->function_kind(), kNoSourcePosition,
shared_info->language_mode(), &ok); function_type, info->language_mode(), &ok);
} }
// Make sure the results agree. // Make sure the results agree.
DCHECK(ok == (result != nullptr)); DCHECK(ok == (result != nullptr));
@ -1225,11 +1253,6 @@ FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
// Make sure the target stack is empty. // Make sure the target stack is empty.
DCHECK_NULL(target_stack_); DCHECK_NULL(target_stack_);
if (result != nullptr) {
Handle<String> inferred_name(shared_info->inferred_name());
result->set_inferred_name(inferred_name);
}
return result; return result;
} }

View File

@ -58,6 +58,9 @@ class ParseInfo {
FLAG_ACCESSOR(kAllowLazyParsing, allow_lazy_parsing, set_allow_lazy_parsing) FLAG_ACCESSOR(kAllowLazyParsing, allow_lazy_parsing, set_allow_lazy_parsing)
FLAG_ACCESSOR(kAstValueFactoryOwned, ast_value_factory_owned, FLAG_ACCESSOR(kAstValueFactoryOwned, ast_value_factory_owned,
set_ast_value_factory_owned) set_ast_value_factory_owned)
FLAG_ACCESSOR(kIsNamedExpression, is_named_expression,
set_is_named_expression)
FLAG_ACCESSOR(kCallsEval, calls_eval, set_calls_eval)
#undef FLAG_ACCESSOR #undef FLAG_ACCESSOR
@ -126,6 +129,26 @@ class ParseInfo {
uint32_t hash_seed() { return hash_seed_; } uint32_t hash_seed() { return hash_seed_; }
void set_hash_seed(uint32_t hash_seed) { hash_seed_ = hash_seed; } void set_hash_seed(uint32_t hash_seed) { hash_seed_ = hash_seed; }
int compiler_hints() const { return compiler_hints_; }
void set_compiler_hints(int compiler_hints) {
compiler_hints_ = compiler_hints;
}
int start_position() const { return start_position_; }
void set_start_position(int start_position) {
start_position_ = start_position;
}
int end_position() const { return end_position_; }
void set_end_position(int end_position) { end_position_ = end_position; }
// Getters for individual compiler hints.
bool is_declaration() const;
bool is_arrow() const;
bool is_async() const;
bool is_default_constructor() const;
FunctionKind function_kind() const;
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// TODO(titzer): these should not be part of ParseInfo. // TODO(titzer): these should not be part of ParseInfo.
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -171,8 +194,10 @@ class ParseInfo {
kParseRestriction = 1 << 6, kParseRestriction = 1 << 6,
kModule = 1 << 7, kModule = 1 << 7,
kAllowLazyParsing = 1 << 8, kAllowLazyParsing = 1 << 8,
kIsNamedExpression = 1 << 9,
kCallsEval = 1 << 10,
// ---------- Output flags -------------------------- // ---------- Output flags --------------------------
kAstValueFactoryOwned = 1 << 9 kAstValueFactoryOwned = 1 << 11
}; };
//------------- Inputs to parsing and scope analysis ----------------------- //------------- Inputs to parsing and scope analysis -----------------------
@ -187,6 +212,9 @@ class ParseInfo {
UnicodeCache* unicode_cache_; UnicodeCache* unicode_cache_;
uintptr_t stack_limit_; uintptr_t stack_limit_;
uint32_t hash_seed_; uint32_t hash_seed_;
int compiler_hints_;
int start_position_;
int end_position_;
// TODO(titzer): Move handles and isolate out of ParseInfo. // TODO(titzer): Move handles and isolate out of ParseInfo.
Isolate* isolate_; Isolate* isolate_;
@ -750,6 +778,7 @@ class Parser : public ParserBase<ParserTraits> {
FunctionLiteral* ParseLazy(Isolate* isolate, ParseInfo* info); FunctionLiteral* ParseLazy(Isolate* isolate, ParseInfo* info);
FunctionLiteral* DoParseLazy(Isolate* isolate, ParseInfo* info, FunctionLiteral* DoParseLazy(Isolate* isolate, ParseInfo* info,
const AstRawString* raw_name,
Utf16CharacterStream* source); Utf16CharacterStream* source);
// Called by ParseProgram after setting up the scanner. // Called by ParseProgram after setting up the scanner.