Commit 255cc15f authored by jochen's avatar jochen Committed by Commit bot

Hook up compiler dispatcher jobs to lazy parser.

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}
parent e866b969
......@@ -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) {}
ParseInfo::ParseInfo(Zone* zone, Handle<JSFunction> function)
......@@ -1120,8 +1121,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);
......@@ -1148,7 +1149,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);
......@@ -5520,7 +5521,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;
......@@ -5536,7 +5536,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_);
......@@ -5547,7 +5546,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);
......
......@@ -116,6 +116,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() const { return literal_; }
void set_literal(FunctionLiteral* literal) { literal_ = literal; }
......@@ -230,6 +235,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_;
//----------- Output of parsing and scope analysis ------------------------
FunctionLiteral* literal_;
......@@ -781,8 +787,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