Commit 912577a3 authored by jochen's avatar jochen Committed by Commit bot

Reland "Hook up compiler dispatcher jobs to lazy parser."

Original issue description:
> The lazy parser actually parses eagerly. It's called lazy because it
> parses functions that were previously lazy parsed. D'uh.
>
> BUG=v8:5215
> R=marja@chromium.org
>
> Review-Url: https://codereview.chromium.org/2220463002
> Cr-Commit-Position: refs/heads/master@{#38375}

BUG=v8:5215
TBR=marja@chromium.org

Review-Url: https://codereview.chromium.org/2218033003
Cr-Commit-Position: refs/heads/master@{#38387}
parent 682a8f71
......@@ -46,6 +46,8 @@ void CompilerDispatcherJob::PrepareToParseOnMainThread() {
zone_.reset(new Zone(isolate_->allocator()));
Handle<SharedFunctionInfo> shared(function_->shared(), isolate_);
Handle<Script> script(Script::cast(shared->script()), isolate_);
DCHECK(script->type() != Script::TYPE_NATIVE);
Handle<String> source(String::cast(script->source()), isolate_);
if (source->IsExternalTwoByteString()) {
character_stream_.reset(new ExternalTwoByteStringUtf16CharacterStream(
......@@ -66,12 +68,24 @@ void CompilerDispatcherJob::PrepareToParseOnMainThread() {
parse_info_.reset(new ParseInfo(zone_.get()));
parse_info_->set_isolate(isolate_);
parse_info_->set_character_stream(character_stream_.get());
parse_info_->set_lazy();
parse_info_->set_hash_seed(isolate_->heap()->HashSeed());
parse_info_->set_is_named_expression(shared->is_named_expression());
parse_info_->set_calls_eval(shared->scope_info()->CallsEval());
parse_info_->set_compiler_hints(shared->compiler_hints());
parse_info_->set_start_position(shared->start_position());
parse_info_->set_end_position(shared->end_position());
parse_info_->set_unicode_cache(unicode_cache_.get());
parse_info_->set_language_mode(shared->language_mode());
parser_.reset(new Parser(parse_info_.get()));
parser_->DeserializeScopeChain(
parse_info_.get(), handle(function_->context(), isolate_),
Scope::DeserializationMode::kDeserializeOffHeap);
Handle<String> name(String::cast(shared->name()));
parse_info_->set_function_name(
parse_info_->ast_value_factory()->GetString(name));
status_ = CompileJobStatus::kReadyToParse;
}
......
......@@ -58,6 +58,7 @@ ParseInfo::ParseInfo(Zone* zone)
isolate_(nullptr),
cached_data_(nullptr),
ast_value_factory_(nullptr),
function_name_(nullptr),
literal_(nullptr),
scope_(nullptr) {}
......@@ -1117,8 +1118,8 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
source, shared_info->start_position(), shared_info->end_position()));
}
Handle<String> name(String::cast(shared_info->name()));
result = DoParseLazy(isolate, info, ast_value_factory()->GetString(name),
stream.get());
result =
DoParseLazy(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);
......@@ -1145,7 +1146,7 @@ static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) {
return FunctionLiteral::kAnonymousExpression;
}
FunctionLiteral* Parser::DoParseLazy(Isolate* isolate, ParseInfo* info,
FunctionLiteral* Parser::DoParseLazy(ParseInfo* info,
const AstRawString* raw_name,
Utf16CharacterStream* source) {
scanner_.Initialize(source);
......@@ -5513,7 +5514,6 @@ void Parser::ParseOnBackground(ParseInfo* info) {
DCHECK(info->literal() == NULL);
FunctionLiteral* result = NULL;
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
CompleteParserRecorder recorder;
if (produce_cached_parse_data()) log_ = &recorder;
......@@ -5529,7 +5529,6 @@ void Parser::ParseOnBackground(ParseInfo* info) {
info->source_stream_encoding()));
stream_ptr = stream.get();
}
scanner_.Initialize(stream_ptr);
DCHECK(info->context().is_null() || info->context()->IsNativeContext());
DCHECK(original_scope_);
......@@ -5540,7 +5539,13 @@ void Parser::ParseOnBackground(ParseInfo* info) {
// don't). We work around this by storing all the scopes which need their end
// position set at the end of the script (the top scope and possible eval
// scopes) and set their end position after we know the script length.
result = DoParseProgram(info);
if (info->is_lazy()) {
result = DoParseLazy(info, info->function_name(), stream_ptr);
} else {
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
scanner_.Initialize(stream_ptr);
result = DoParseProgram(info);
}
info->set_literal(result);
......
......@@ -112,6 +112,11 @@ class ParseInfo {
ast_value_factory_ = ast_value_factory;
}
const AstRawString* function_name() const { return function_name_; }
void set_function_name(const AstRawString* function_name) {
function_name_ = function_name;
}
FunctionLiteral* literal() { return literal_; }
void set_literal(FunctionLiteral* literal) { literal_ = literal; }
......@@ -225,6 +230,7 @@ class ParseInfo {
//----------- Inputs+Outputs of parsing and scope analysis -----------------
ScriptData** cached_data_; // used if available, populated if requested.
AstValueFactory* ast_value_factory_; // used if available, otherwise new.
const AstRawString* function_name_;
//----------- Outputs of parsing and scope analysis ------------------------
FunctionLiteral* literal_; // produced by full parser.
......@@ -776,8 +782,7 @@ class Parser : public ParserBase<ParserTraits> {
FunctionLiteral* ParseProgram(Isolate* isolate, ParseInfo* info);
FunctionLiteral* ParseLazy(Isolate* isolate, ParseInfo* info);
FunctionLiteral* DoParseLazy(Isolate* isolate, ParseInfo* info,
const AstRawString* raw_name,
FunctionLiteral* DoParseLazy(ParseInfo* info, const AstRawString* raw_name,
Utf16CharacterStream* source);
// Called by ParseProgram after setting up the scanner.
......
......@@ -4,9 +4,13 @@
#include <memory>
#include "include/v8.h"
#include "src/api.h"
#include "src/ast/scopes.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/flags.h"
#include "src/isolate-inl.h"
#include "src/parsing/parser.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -17,7 +21,7 @@ typedef TestWithContext CompilerDispatcherJobTest;
namespace {
const char test_script[] = "x*x";
const char test_script[] = "(x) { x*x; }";
class ScriptResource : public v8::String::ExternalOneByteStringResource {
public:
......@@ -108,6 +112,44 @@ TEST_F(CompilerDispatcherJobTest, SyntaxError) {
job->ReportErrorsOnMainThread();
ASSERT_TRUE(job->status() == CompileJobStatus::kDone);
ASSERT_TRUE(i_isolate()->has_pending_exception());
i_isolate()->clear_pending_exception();
}
TEST_F(CompilerDispatcherJobTest, ScopeChain) {
const char script[] =
"function g() { var g = 1; function f(x) { return x * g }; return f; } "
"g();";
Handle<JSFunction> f = Handle<JSFunction>::cast(Utils::OpenHandle(
*v8::Script::Compile(isolate()->GetCurrentContext(),
v8::String::NewFromUtf8(isolate(), script,
v8::NewStringType::kNormal)
.ToLocalChecked())
.ToLocalChecked()
->Run(isolate()->GetCurrentContext())
.ToLocalChecked()));
std::unique_ptr<CompilerDispatcherJob> job(
new CompilerDispatcherJob(i_isolate(), f, FLAG_stack_size));
job->PrepareToParseOnMainThread();
job->Parse();
job->FinalizeParsingOnMainThread();
ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile);
const AstRawString* var_x =
job->parse_info_->ast_value_factory()->GetOneByteString("x");
Variable* var = job->parse_info_->literal()->scope()->Lookup(var_x);
ASSERT_TRUE(var);
ASSERT_TRUE(var->IsUnallocated());
const AstRawString* var_g =
job->parse_info_->ast_value_factory()->GetOneByteString("g");
var = job->parse_info_->literal()->scope()->Lookup(var_g);
ASSERT_TRUE(var);
ASSERT_TRUE(var->IsContextSlot());
job->ResetOnMainThread();
ASSERT_TRUE(job->status() == CompileJobStatus::kInitial);
}
} // namespace internal
......
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