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),
stack_limit_(0),
hash_seed_(0),
compiler_hints_(0),
start_position_(0),
end_position_(0),
isolate_(nullptr),
cached_data_(nullptr),
ast_value_factory_(nullptr),
@ -70,6 +73,11 @@ ParseInfo::ParseInfo(Zone* zone, Handle<SharedFunctionInfo> shared)
set_lazy();
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_unicode_cache(isolate_->unicode_cache());
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) {
// 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(
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) {
@ -1091,30 +1125,27 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
return result;
}
static FunctionLiteral::FunctionType ComputeFunctionType(
Handle<SharedFunctionInfo> shared_info) {
if (shared_info->is_declaration()) {
static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) {
if (info->is_declaration()) {
return FunctionLiteral::kDeclaration;
} else if (shared_info->is_named_expression()) {
} else if (info->is_named_expression()) {
return FunctionLiteral::kNamedExpression;
} else if (IsConciseMethod(shared_info->kind()) ||
IsAccessorFunction(shared_info->kind())) {
} else if (IsConciseMethod(info->function_kind()) ||
IsAccessorFunction(info->function_kind())) {
return FunctionLiteral::kAccessorOrMethod;
}
return FunctionLiteral::kAnonymousExpression;
}
FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
const AstRawString* raw_name,
Utf16CharacterStream* source) {
Handle<SharedFunctionInfo> shared_info = info->shared_info();
scanner_.Initialize(source);
DCHECK_NULL(scope_state_);
DCHECK_NULL(target_stack_);
Handle<String> name(String::cast(shared_info->name()));
DCHECK(ast_value_factory());
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
const AstRawString* raw_name = ast_value_factory()->GetString(name);
fni_->PushEnclosingName(raw_name);
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
@ -1127,16 +1158,14 @@ FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
Scope* scope = original_scope_;
DCHECK(scope);
FunctionState function_state(&function_state_, &scope_state_, scope,
shared_info->kind());
info->function_kind());
DCHECK(is_sloppy(scope->language_mode()) ||
is_strict(info->language_mode()));
DCHECK(info->language_mode() == shared_info->language_mode());
FunctionLiteral::FunctionType function_type =
ComputeFunctionType(shared_info);
FunctionLiteral::FunctionType function_type = ComputeFunctionType(info);
bool ok = true;
if (shared_info->is_arrow()) {
bool is_async = allow_harmony_async_await() && shared_info->is_async();
if (info->is_arrow()) {
bool is_async = allow_harmony_async_await() && info->is_async();
if (is_async) {
DCHECK(!scanner()->HasAnyLineTerminatorAfterNext());
if (!Check(Token::ASYNC)) {
@ -1156,12 +1185,12 @@ FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
// not passing the ScopeInfo to the Scope constructor.
// TODO(adamk): Remove these calls once the above NewScope call
// passes the ScopeInfo.
if (shared_info->scope_info()->CallsEval()) {
if (info->calls_eval()) {
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);
ParserFormalParameters formals(scope);
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
// only for arrow functions with single expression bodies, since there
// 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
// must produce a FunctionLiteral.
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);
result = DefaultConstructor(
raw_name, IsSubclassConstructor(shared_info->kind()),
shared_info->start_position(), shared_info->end_position(),
shared_info->language_mode());
raw_name, IsSubclassConstructor(info->function_kind()),
info->start_position(), info->end_position(), info->language_mode());
} else {
result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
kSkipFunctionNameCheck, shared_info->kind(),
kNoSourcePosition, function_type,
shared_info->language_mode(), &ok);
kSkipFunctionNameCheck,
info->function_kind(), kNoSourcePosition,
function_type, info->language_mode(), &ok);
}
// Make sure the results agree.
DCHECK(ok == (result != nullptr));
@ -1225,11 +1253,6 @@ FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
// Make sure the target stack is empty.
DCHECK_NULL(target_stack_);
if (result != nullptr) {
Handle<String> inferred_name(shared_info->inferred_name());
result->set_inferred_name(inferred_name);
}
return result;
}

View File

@ -58,6 +58,9 @@ class ParseInfo {
FLAG_ACCESSOR(kAllowLazyParsing, allow_lazy_parsing, set_allow_lazy_parsing)
FLAG_ACCESSOR(kAstValueFactoryOwned, 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
@ -126,6 +129,26 @@ class ParseInfo {
uint32_t hash_seed() { return 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.
//--------------------------------------------------------------------------
@ -171,8 +194,10 @@ class ParseInfo {
kParseRestriction = 1 << 6,
kModule = 1 << 7,
kAllowLazyParsing = 1 << 8,
kIsNamedExpression = 1 << 9,
kCallsEval = 1 << 10,
// ---------- Output flags --------------------------
kAstValueFactoryOwned = 1 << 9
kAstValueFactoryOwned = 1 << 11
};
//------------- Inputs to parsing and scope analysis -----------------------
@ -187,6 +212,9 @@ class ParseInfo {
UnicodeCache* unicode_cache_;
uintptr_t stack_limit_;
uint32_t hash_seed_;
int compiler_hints_;
int start_position_;
int end_position_;
// TODO(titzer): Move handles and isolate out of ParseInfo.
Isolate* isolate_;
@ -750,6 +778,7 @@ class Parser : public ParserBase<ParserTraits> {
FunctionLiteral* ParseLazy(Isolate* isolate, ParseInfo* info);
FunctionLiteral* DoParseLazy(Isolate* isolate, ParseInfo* info,
const AstRawString* raw_name,
Utf16CharacterStream* source);
// Called by ParseProgram after setting up the scanner.