Commit c80ff604 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[compiler-dispatcher] Make compiler jobs abstract (reland)

Reland of https://chromium-review.googlesource.com/c/558290/

Makes compiler dispatcher jobs an abstract interface, with unoptimized
compile jobs as an implementation of this interface.

Bug: v8:6537
Change-Id: Ia85781f72c7aaca497896ca4efa91ada97e43b1c
Reviewed-on: https://chromium-review.googlesource.com/589154
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46940}
parent f3817e9b
......@@ -1246,6 +1246,8 @@ v8_source_set("v8_base") {
"src/compiler-dispatcher/compiler-dispatcher.h",
"src/compiler-dispatcher/optimizing-compile-dispatcher.cc",
"src/compiler-dispatcher/optimizing-compile-dispatcher.h",
"src/compiler-dispatcher/unoptimized-compile-job.cc",
"src/compiler-dispatcher/unoptimized-compile-job.h",
"src/compiler.cc",
"src/compiler.h",
"src/compiler/access-builder.cc",
......
......@@ -4,572 +4,15 @@
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/assert-scope.h"
#include "src/compilation-info.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/compiler.h"
#include "src/flags.h"
#include "src/global-handles.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser.h"
#include "src/parsing/scanner-character-streams.h"
#include "src/unicode-cache.h"
#include "src/utils.h"
#include "src/compiler-dispatcher/unoptimized-compile-job.h"
namespace v8 {
namespace internal {
namespace {
class OneByteWrapper : public v8::String::ExternalOneByteStringResource {
public:
OneByteWrapper(const void* data, int length) : data_(data), length_(length) {}
~OneByteWrapper() override = default;
const char* data() const override {
return reinterpret_cast<const char*>(data_);
}
size_t length() const override { return static_cast<size_t>(length_); }
private:
const void* data_;
int length_;
DISALLOW_COPY_AND_ASSIGN(OneByteWrapper);
};
class TwoByteWrapper : public v8::String::ExternalStringResource {
public:
TwoByteWrapper(const void* data, int length) : data_(data), length_(length) {}
~TwoByteWrapper() override = default;
const uint16_t* data() const override {
return reinterpret_cast<const uint16_t*>(data_);
}
size_t length() const override { return static_cast<size_t>(length_); }
private:
const void* data_;
int length_;
DISALLOW_COPY_AND_ASSIGN(TwoByteWrapper);
};
} // namespace
CompilerDispatcherJob::CompilerDispatcherJob(
CompilerDispatcherTracer* tracer, size_t max_stack_size,
Handle<String> source, int start_position, int end_position,
LanguageMode language_mode, int function_literal_id, bool native,
bool module, bool is_named_expression, uint32_t hash_seed,
AccountingAllocator* zone_allocator, int compiler_hints,
const AstStringConstants* ast_string_constants,
CompileJobFinishCallback* finish_callback)
: status_(CompileJobStatus::kReadyToParse),
isolate_(nullptr),
tracer_(tracer),
max_stack_size_(max_stack_size),
finish_callback_(finish_callback),
trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
parse_info_.reset(new ParseInfo(zone_allocator));
DCHECK(source->IsExternalTwoByteString() ||
source->IsExternalOneByteString());
character_stream_.reset(
ScannerStream::For(source, start_position, end_position));
parse_info_->set_character_stream(character_stream_.get());
parse_info_->set_hash_seed(hash_seed);
parse_info_->set_compiler_hints(compiler_hints);
parse_info_->set_start_position(start_position);
parse_info_->set_end_position(end_position);
unicode_cache_.reset(new UnicodeCache());
parse_info_->set_unicode_cache(unicode_cache_.get());
parse_info_->set_language_mode(language_mode);
parse_info_->set_function_literal_id(function_literal_id);
parse_info_->set_ast_string_constants(ast_string_constants);
if (V8_UNLIKELY(FLAG_runtime_stats)) {
parse_info_->set_runtime_call_stats(new (parse_info_->zone())
RuntimeCallStats());
}
parse_info_->set_native(native);
parse_info_->set_module(module);
parse_info_->set_is_named_expression(is_named_expression);
parser_.reset(new Parser(parse_info_.get()));
parser_->DeserializeScopeChain(parse_info_.get(), MaybeHandle<ScopeInfo>());
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p] created for ", static_cast<void*>(this));
ShortPrint();
PrintF(" in ready to parse state.\n");
}
}
CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate,
CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
size_t max_stack_size)
: status_(CompileJobStatus::kInitial),
isolate_(isolate),
tracer_(tracer),
context_(isolate_->global_handles()->Create(isolate->context())),
shared_(isolate_->global_handles()->Create(*shared)),
max_stack_size_(max_stack_size),
trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
DCHECK(!shared_->is_toplevel());
HandleScope scope(isolate_);
Handle<Script> script(Script::cast(shared_->script()), isolate_);
Handle<String> source(String::cast(script->source()), isolate_);
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p] created for ", static_cast<void*>(this));
ShortPrint();
PrintF(" in initial state.\n");
}
}
CompilerDispatcherJob::CompilerDispatcherJob(
Isolate* isolate, CompilerDispatcherTracer* tracer, Handle<Script> script,
Handle<SharedFunctionInfo> shared, FunctionLiteral* literal,
ParseInfo* outer_parse_info,
std::shared_ptr<DeferredHandles> compile_handles, size_t max_stack_size)
: status_(CompileJobStatus::kAnalyzed),
isolate_(isolate),
tracer_(tracer),
context_(isolate_->global_handles()->Create(isolate->context())),
shared_(isolate_->global_handles()->Create(*shared)),
max_stack_size_(max_stack_size),
parse_info_(new ParseInfo(shared_)),
compile_zone_(new Zone(isolate->allocator(), ZONE_NAME)),
compile_info_(new CompilationInfo(compile_zone_.get(), parse_info_.get(),
isolate_, shared_,
Handle<JSFunction>::null())),
trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
parse_info_->set_literal(literal);
parse_info_->set_script(script);
parse_info_->ShareAstValueFactory(outer_parse_info);
parse_info_->ShareZone(outer_parse_info);
compile_info_->set_deferred_handles(compile_handles);
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p] created for ", static_cast<void*>(this));
ShortPrint();
PrintF(" in Analyzed state.\n");
}
}
CompilerDispatcherJob::~CompilerDispatcherJob() {
DCHECK(status_ == CompileJobStatus::kInitial ||
(status_ == CompileJobStatus::kReadyToParse && finish_callback_) ||
status_ == CompileJobStatus::kDone);
if (!shared_.is_null()) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
i::GlobalHandles::Destroy(Handle<Object>::cast(shared_).location());
}
if (!context_.is_null()) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
i::GlobalHandles::Destroy(Handle<Object>::cast(context_).location());
}
}
bool CompilerDispatcherJob::IsAssociatedWith(
Handle<SharedFunctionInfo> shared) const {
return *shared_ == *shared;
}
void CompilerDispatcherJob::StepNextOnMainThread() {
switch (status()) {
case CompileJobStatus::kInitial:
return PrepareToParseOnMainThread();
case CompileJobStatus::kReadyToParse:
return Parse();
case CompileJobStatus::kParsed:
return FinalizeParsingOnMainThread();
case CompileJobStatus::kReadyToAnalyze:
return AnalyzeOnMainThread();
case CompileJobStatus::kAnalyzed:
return PrepareToCompileOnMainThread();
case CompileJobStatus::kReadyToCompile:
return Compile();
case CompileJobStatus::kCompiled:
return FinalizeCompilingOnMainThread();
case CompileJobStatus::kFailed:
case CompileJobStatus::kDone:
return;
}
UNREACHABLE();
}
void CompilerDispatcherJob::StepNextOnBackgroundThread() {
DCHECK(CanStepNextOnAnyThread());
switch (status()) {
case CompileJobStatus::kReadyToParse:
return Parse();
case CompileJobStatus::kReadyToCompile:
return Compile();
default:
UNREACHABLE();
}
}
void CompilerDispatcherJob::PrepareToParseOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kInitial);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToParse);
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p]: Preparing to parse\n",
static_cast<void*>(this));
}
HandleScope scope(isolate_);
unicode_cache_.reset(new UnicodeCache());
Handle<Script> script(Script::cast(shared_->script()), isolate_);
DCHECK(script->type() != Script::TYPE_NATIVE);
Handle<String> source(String::cast(script->source()), isolate_);
parse_info_.reset(new ParseInfo(isolate_->allocator()));
if (source->IsExternalTwoByteString() || source->IsExternalOneByteString()) {
character_stream_.reset(ScannerStream::For(
source, shared_->start_position(), shared_->end_position()));
} else {
source = String::Flatten(source);
const void* data;
int offset = 0;
int length = source->length();
// Objects in lo_space don't move, so we can just read the contents from
// any thread.
if (isolate_->heap()->lo_space()->Contains(*source)) {
// We need to globalize the handle to the flattened string here, in
// case it's not referenced from anywhere else.
source_ = isolate_->global_handles()->Create(*source);
DisallowHeapAllocation no_allocation;
String::FlatContent content = source->GetFlatContent();
DCHECK(content.IsFlat());
data =
content.IsOneByte()
? reinterpret_cast<const void*>(content.ToOneByteVector().start())
: reinterpret_cast<const void*>(content.ToUC16Vector().start());
} else {
// Otherwise, create a copy of the part of the string we'll parse in the
// zone.
length = (shared_->end_position() - shared_->start_position());
offset = shared_->start_position();
int byte_len = length * (source->IsOneByteRepresentation() ? 1 : 2);
data = parse_info_->zone()->New(byte_len);
DisallowHeapAllocation no_allocation;
String::FlatContent content = source->GetFlatContent();
DCHECK(content.IsFlat());
if (content.IsOneByte()) {
MemCopy(const_cast<void*>(data),
&content.ToOneByteVector().at(shared_->start_position()),
byte_len);
} else {
MemCopy(const_cast<void*>(data),
&content.ToUC16Vector().at(shared_->start_position()),
byte_len);
}
}
Handle<String> wrapper;
if (source->IsOneByteRepresentation()) {
ExternalOneByteString::Resource* resource =
new OneByteWrapper(data, length);
source_wrapper_.reset(resource);
wrapper = isolate_->factory()
->NewExternalStringFromOneByte(resource)
.ToHandleChecked();
} else {
ExternalTwoByteString::Resource* resource =
new TwoByteWrapper(data, length);
source_wrapper_.reset(resource);
wrapper = isolate_->factory()
->NewExternalStringFromTwoByte(resource)
.ToHandleChecked();
}
wrapper_ = isolate_->global_handles()->Create(*wrapper);
character_stream_.reset(
ScannerStream::For(wrapper_, shared_->start_position() - offset,
shared_->end_position() - offset));
}
parse_info_->InitFromIsolate(isolate_);
parse_info_->set_character_stream(character_stream_.get());
parse_info_->set_hash_seed(isolate_->heap()->HashSeed());
parse_info_->set_is_named_expression(shared_->is_named_expression());
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());
parse_info_->set_function_literal_id(shared_->function_literal_id());
if (V8_UNLIKELY(FLAG_runtime_stats)) {
parse_info_->set_runtime_call_stats(new (parse_info_->zone())
RuntimeCallStats());
}
parser_.reset(new Parser(parse_info_.get()));
MaybeHandle<ScopeInfo> outer_scope_info;
if (!shared_->outer_scope_info()->IsTheHole(isolate_) &&
ScopeInfo::cast(shared_->outer_scope_info())->length() > 0) {
outer_scope_info = handle(ScopeInfo::cast(shared_->outer_scope_info()));
}
parser_->DeserializeScopeChain(parse_info_.get(), outer_scope_info);
Handle<String> name(shared_->name());
parse_info_->set_function_name(
parse_info_->ast_value_factory()->GetString(name));
status_ = CompileJobStatus::kReadyToParse;
}
void CompilerDispatcherJob::Parse() {
DCHECK(status() == CompileJobStatus::kReadyToParse);
COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM(
tracer_, kParse,
parse_info_->end_position() - parse_info_->start_position());
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p]: Parsing\n", static_cast<void*>(this));
}
DisallowHeapAllocation no_allocation;
DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref;
uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB;
parser_->set_stack_limit(stack_limit);
parser_->ParseOnBackground(parse_info_.get());
if (finish_callback_) {
finish_callback_->ParseFinished(std::move(parse_info_));
status_ = CompileJobStatus::kDone;
} else {
status_ = CompileJobStatus::kParsed;
}
}
void CompilerDispatcherJob::FinalizeParsingOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kParsed);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeParsing);
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p]: Finalizing parsing\n",
static_cast<void*>(this));
}
if (!source_.is_null()) {
i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location());
source_ = Handle<String>::null();
}
if (!wrapper_.is_null()) {
i::GlobalHandles::Destroy(Handle<Object>::cast(wrapper_).location());
wrapper_ = Handle<String>::null();
}
Handle<Script> script(Script::cast(shared_->script()), isolate_);
parse_info_->set_script(script);
if (parse_info_->literal() == nullptr) {
parser_->ReportErrors(isolate_, script);
status_ = CompileJobStatus::kFailed;
} else {
status_ = CompileJobStatus::kReadyToAnalyze;
}
parser_->UpdateStatistics(isolate_, script);
parse_info_->UpdateStatisticsAfterBackgroundParse(isolate_);
if (!shared_->outer_scope_info()->IsTheHole(isolate_) &&
ScopeInfo::cast(shared_->outer_scope_info())->length() > 0) {
Handle<ScopeInfo> outer_scope_info(
handle(ScopeInfo::cast(shared_->outer_scope_info())));
parse_info_->set_outer_scope_info(outer_scope_info);
}
parser_->HandleSourceURLComments(isolate_, script);
parse_info_->set_character_stream(nullptr);
parse_info_->set_unicode_cache(nullptr);
parser_.reset();
unicode_cache_.reset();
character_stream_.reset();
}
void CompilerDispatcherJob::AnalyzeOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kReadyToAnalyze);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kAnalyze);
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p]: Analyzing\n", static_cast<void*>(this));
}
compile_zone_.reset(new Zone(isolate_->allocator(), ZONE_NAME));
compile_info_.reset(new CompilationInfo(
compile_zone_.get(), parse_info_.get(), isolate_,
Handle<SharedFunctionInfo>::null(), Handle<JSFunction>::null()));
DeferredHandleScope scope(isolate_);
{
if (Compiler::Analyze(compile_info_.get())) {
status_ = CompileJobStatus::kAnalyzed;
} else {
status_ = CompileJobStatus::kFailed;
if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
}
}
compile_info_->set_deferred_handles(scope.Detach());
}
void CompilerDispatcherJob::PrepareToCompileOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kAnalyzed);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile);
compile_job_.reset(
Compiler::PrepareUnoptimizedCompilationJob(compile_info_.get()));
if (!compile_job_.get()) {
if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
status_ = CompileJobStatus::kFailed;
return;
}
CHECK(compile_job_->can_execute_on_background_thread());
status_ = CompileJobStatus::kReadyToCompile;
}
void CompilerDispatcherJob::Compile() {
DCHECK(status() == CompileJobStatus::kReadyToCompile);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kCompile);
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p]: Compiling\n", static_cast<void*>(this));
}
// Disallowing of handle dereference and heap access dealt with in
// CompilationJob::ExecuteJob.
uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB;
compile_job_->set_stack_limit(stack_limit);
CompilationJob::Status status = compile_job_->ExecuteJob();
USE(status);
// Always transition to kCompiled - errors will be reported by
// FinalizeCompilingOnMainThread.
status_ = CompileJobStatus::kCompiled;
}
void CompilerDispatcherJob::FinalizeCompilingOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kCompiled);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeCompiling);
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p]: Finalizing compiling\n",
static_cast<void*>(this));
}
{
HandleScope scope(isolate_);
compile_info_->set_shared_info(shared_);
if (compile_job_->state() == CompilationJob::State::kFailed ||
!Compiler::FinalizeCompilationJob(compile_job_.release())) {
if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
status_ = CompileJobStatus::kFailed;
return;
}
}
compile_job_.reset();
compile_info_.reset();
compile_zone_.reset();
parse_info_.reset();
status_ = CompileJobStatus::kDone;
}
void CompilerDispatcherJob::ResetOnMainThread() {
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p]: Resetting\n", static_cast<void*>(this));
}
compile_job_.reset();
compile_info_.reset();
compile_zone_.reset();
parser_.reset();
unicode_cache_.reset();
character_stream_.reset();
parse_info_.reset();
finish_callback_ = nullptr;
if (!source_.is_null()) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location());
source_ = Handle<String>::null();
}
if (!wrapper_.is_null()) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
i::GlobalHandles::Destroy(Handle<Object>::cast(wrapper_).location());
wrapper_ = Handle<String>::null();
}
status_ = CompileJobStatus::kInitial;
}
double CompilerDispatcherJob::EstimateRuntimeOfNextStepInMs() const {
switch (status_) {
case CompileJobStatus::kInitial:
return tracer_->EstimatePrepareToParseInMs();
case CompileJobStatus::kReadyToParse:
return tracer_->EstimateParseInMs(parse_info_->end_position() -
parse_info_->start_position());
case CompileJobStatus::kParsed:
return tracer_->EstimateFinalizeParsingInMs();
case CompileJobStatus::kReadyToAnalyze:
return tracer_->EstimateAnalyzeInMs();
case CompileJobStatus::kAnalyzed:
return tracer_->EstimatePrepareToCompileInMs();
case CompileJobStatus::kReadyToCompile:
return tracer_->EstimateCompileInMs();
case CompileJobStatus::kCompiled:
return tracer_->EstimateFinalizeCompilingInMs();
case CompileJobStatus::kFailed:
case CompileJobStatus::kDone:
return 0.0;
}
UNREACHABLE();
}
void CompilerDispatcherJob::ShortPrint() {
if (isolate_) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(!shared_.is_null());
shared_->ShortPrint();
} else {
// TODO(wiktorg) more useful info in those cases
if (parse_info_) {
PrintF("function at %d", parse_info_->start_position());
} else {
PrintF("parsed function");
}
}
const UnoptimizedCompileJob* CompilerDispatcherJob::AsUnoptimizedCompileJob()
const {
DCHECK_EQ(type(), kUnoptimizedCompile);
return static_cast<const UnoptimizedCompileJob*>(this);
}
} // namespace internal
......
......@@ -5,168 +5,54 @@
#ifndef V8_COMPILER_DISPATCHER_COMPILER_DISPATCHER_JOB_H_
#define V8_COMPILER_DISPATCHER_COMPILER_DISPATCHER_JOB_H_
#include <memory>
#include "include/v8.h"
#include "src/base/macros.h"
#include "src/globals.h"
#include "src/contexts.h"
#include "src/handles.h"
#include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck
namespace v8 {
namespace internal {
class AstValueFactory;
class AstStringConstants;
class CompilerDispatcherTracer;
class CompilationInfo;
class CompilationJob;
class DeferredHandles;
class FunctionLiteral;
class Isolate;
class ParseInfo;
class Parser;
class SharedFunctionInfo;
class String;
class UnicodeCache;
class Utf16CharacterStream;
enum class CompileJobStatus {
kInitial,
kReadyToParse,
kParsed,
kReadyToAnalyze,
kAnalyzed,
kReadyToCompile,
kCompiled,
kFailed,
kDone,
};
class V8_EXPORT_PRIVATE CompileJobFinishCallback {
public:
virtual ~CompileJobFinishCallback() {}
virtual void ParseFinished(std::unique_ptr<ParseInfo> parse_info) = 0;
};
class UnoptimizedCompileJob;
class V8_EXPORT_PRIVATE CompilerDispatcherJob {
public:
// Creates a CompilerDispatcherJob in the initial state.
CompilerDispatcherJob(Isolate* isolate, CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
size_t max_stack_size);
// TODO(wiktorg) document it better once I know how it relates to whole stuff
// Creates a CompilerDispatcherJob in ready to parse top-level function state.
CompilerDispatcherJob(CompilerDispatcherTracer* tracer, size_t max_stack_size,
Handle<String> source, int start_position,
int end_position, LanguageMode language_mode,
int function_literal_id, bool native, bool module,
bool is_named_expression, uint32_t hash_seed,
AccountingAllocator* zone_allocator, int compiler_hints,
const AstStringConstants* ast_string_constants,
CompileJobFinishCallback* finish_callback);
// Creates a CompilerDispatcherJob in the analyzed state.
CompilerDispatcherJob(Isolate* isolate, CompilerDispatcherTracer* tracer,
Handle<Script> script,
Handle<SharedFunctionInfo> shared,
FunctionLiteral* literal, ParseInfo* outer_parse_info,
std::shared_ptr<DeferredHandles> compile_handles,
size_t max_stack_size);
~CompilerDispatcherJob();
bool has_context() const { return !context_.is_null(); }
Context* context() { return *context_; }
Handle<SharedFunctionInfo> shared() const { return shared_; }
// Returns true if this CompilerDispatcherJob was created for the given
// function.
bool IsAssociatedWith(Handle<SharedFunctionInfo> shared) const;
bool IsFinished() {
return status() == CompileJobStatus::kDone ||
status() == CompileJobStatus::kFailed;
}
bool IsFailed() { return status() == CompileJobStatus::kFailed; }
enum Type { kUnoptimizedCompile };
virtual ~CompilerDispatcherJob() {}
virtual Type type() const = 0;
// Returns true if this CompilerDispatcherJob has finished (either with a
// success or a failure).
virtual bool IsFinished() = 0;
// Returns true if this CompilerDispatcherJob has failed.
virtual bool IsFailed() = 0;
// Return true if the next step can be run on any thread, that is when both
// StepNextOnMainThread and StepNextOnBackgroundThread could be used for the
// next step.
bool CanStepNextOnAnyThread() {
return status() == CompileJobStatus::kReadyToParse ||
status() == CompileJobStatus::kReadyToCompile;
}
virtual bool CanStepNextOnAnyThread() = 0;
// Step the job forward by one state on the main thread.
void StepNextOnMainThread();
virtual void StepNextOnMainThread() = 0;
// Step the job forward by one state on a background thread.
void StepNextOnBackgroundThread();
virtual void StepNextOnBackgroundThread() = 0;
// Transition from any state to kInitial and free all resources.
void ResetOnMainThread();
virtual void ResetOnMainThread() = 0;
// Estimate how long the next step will take using the tracer.
double EstimateRuntimeOfNextStepInMs() const;
virtual double EstimateRuntimeOfNextStepInMs() const = 0;
// Even though the name does not imply this, ShortPrint() must only be invoked
// on the main thread.
void ShortPrint();
private:
friend class CompilerDispatcherTest;
friend class CompilerDispatcherJobTest;
CompileJobStatus status() const { return status_; }
CompileJobStatus status_;
Isolate* isolate_;
CompilerDispatcherTracer* tracer_;
Handle<Context> context_; // Global handle.
Handle<SharedFunctionInfo> shared_; // Global handle.
Handle<String> source_; // Global handle.
Handle<String> wrapper_; // Global handle.
std::unique_ptr<v8::String::ExternalStringResourceBase> source_wrapper_;
size_t max_stack_size_;
CompileJobFinishCallback* finish_callback_ = nullptr;
// Members required for parsing.
std::unique_ptr<UnicodeCache> unicode_cache_;
std::unique_ptr<Utf16CharacterStream> character_stream_;
std::unique_ptr<ParseInfo> parse_info_;
std::unique_ptr<Parser> parser_;
// Members required for compiling.
std::unique_ptr<Zone> compile_zone_;
std::unique_ptr<CompilationInfo> compile_info_;
std::unique_ptr<CompilationJob> compile_job_;
bool trace_compiler_dispatcher_jobs_;
// Transition from kInitial to kReadyToParse.
void PrepareToParseOnMainThread();
// Transition from kReadyToParse to kParsed (or kDone if there is
// finish_callback).
void Parse();
// Transition from kParsed to kReadyToAnalyze (or kFailed).
void FinalizeParsingOnMainThread();
// Transition from kReadyToAnalyze to kAnalyzed (or kFailed).
void AnalyzeOnMainThread();
// Transition from kAnalyzed to kReadyToCompile (or kFailed).
void PrepareToCompileOnMainThread();
// Transition from kReadyToCompile to kCompiled.
void Compile();
// Transition from kCompiled to kDone (or kFailed).
void FinalizeCompilingOnMainThread();
virtual void ShortPrint() = 0;
DISALLOW_COPY_AND_ASSIGN(CompilerDispatcherJob);
// Casts to implementations.
const UnoptimizedCompileJob* AsUnoptimizedCompileJob() const;
};
} // namespace internal
......
......@@ -11,6 +11,7 @@
#include "src/compilation-info.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/compiler-dispatcher/unoptimized-compile-job.h"
#include "src/flags.h"
#include "src/objects-inl.h"
......@@ -26,15 +27,6 @@ bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherForgroundStep");
// Ensure we are in the correct context for the job.
SaveContext save(isolate);
if (job->has_context()) {
isolate->set_context(job->context());
} else {
DCHECK(job->CanStepNextOnAnyThread());
}
job->StepNextOnMainThread();
DCHECK_EQ(job->IsFailed(), isolate->has_pending_exception());
......@@ -170,7 +162,7 @@ CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform,
tracer_(new CompilerDispatcherTracer(isolate_)),
task_manager_(new CancelableTaskManager()),
next_job_id_(0),
shared_to_job_id_(isolate->heap()),
shared_to_unoptimized_job_id_(isolate->heap()),
memory_pressure_level_(MemoryPressureLevel::kNone),
abort_(false),
idle_task_scheduled_(false),
......@@ -222,14 +214,7 @@ bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) {
CompilerDispatcher::JobId CompilerDispatcher::Enqueue(
std::unique_ptr<CompilerDispatcherJob> job) {
DCHECK(!job->IsFinished());
bool added;
JobMap::const_iterator it;
std::tie(it, added) =
jobs_.insert(std::make_pair(next_job_id_++, std::move(job)));
DCHECK(added);
if (!it->second->shared().is_null()) {
shared_to_job_id_.Set(it->second->shared(), it->first);
}
JobMap::const_iterator it = InsertJob(std::move(job));
ConsiderJobForBackgroundProcessing(it->second.get());
ScheduleIdleTaskIfNeeded();
return it->first;
......@@ -238,15 +223,7 @@ CompilerDispatcher::JobId CompilerDispatcher::Enqueue(
CompilerDispatcher::JobId CompilerDispatcher::EnqueueAndStep(
std::unique_ptr<CompilerDispatcherJob> job) {
DCHECK(!job->IsFinished());
bool added;
JobMap::const_iterator it;
std::tie(it, added) =
jobs_.insert(std::make_pair(next_job_id_++, std::move(job)));
DCHECK(added);
if (!it->second->shared().is_null()) {
shared_to_job_id_.Set(it->second->shared(), it->first);
}
JobId id = it->first;
JobMap::const_iterator it = InsertJob(std::move(job));
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: stepping ");
it->second->ShortPrint();
......@@ -257,7 +234,7 @@ CompilerDispatcher::JobId CompilerDispatcher::EnqueueAndStep(
ConsiderJobForBackgroundProcessing(it->second.get());
RemoveIfFinished(it);
ScheduleIdleTaskIfNeeded();
return id;
return it->first;
}
bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
......@@ -272,19 +249,17 @@ bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
PrintF(" for parse and compile\n");
}
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<CompilerDispatcherJob> job(new UnoptimizedCompileJob(
isolate_, tracer_.get(), function, max_stack_size_));
Enqueue(std::move(job));
return true;
}
bool CompilerDispatcher::Enqueue(Handle<String> source, int start_position,
int end_position, LanguageMode language_mode,
int function_literal_id, bool native,
bool module, bool is_named_expression,
int compiler_hints,
CompileJobFinishCallback* finish_callback,
JobId* job_id) {
bool CompilerDispatcher::Enqueue(
Handle<String> source, int start_position, int end_position,
LanguageMode language_mode, int function_literal_id, bool native,
bool module, bool is_named_expression, int compiler_hints,
UnoptimizedCompileJobFinishCallback* finish_callback, JobId* job_id) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherEnqueue");
if (!CanEnqueue()) return false;
......@@ -294,7 +269,7 @@ bool CompilerDispatcher::Enqueue(Handle<String> source, int start_position,
start_position);
}
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<CompilerDispatcherJob> job(new UnoptimizedCompileJob(
tracer_.get(), max_stack_size_, source, start_position, end_position,
language_mode, function_literal_id, native, module, is_named_expression,
isolate_->heap()->HashSeed(), isolate_->allocator(), compiler_hints,
......@@ -318,7 +293,7 @@ bool CompilerDispatcher::EnqueueAndStep(Handle<SharedFunctionInfo> function) {
PrintF(" for parse and compile\n");
}
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<CompilerDispatcherJob> job(new UnoptimizedCompileJob(
isolate_, tracer_.get(), function, max_stack_size_));
EnqueueAndStep(std::move(job));
return true;
......@@ -339,7 +314,7 @@ bool CompilerDispatcher::Enqueue(
PrintF(" for compile\n");
}
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<CompilerDispatcherJob> job(new UnoptimizedCompileJob(
isolate_, tracer_.get(), script, function, literal, outer_parse_info,
compile_handles, max_stack_size_));
Enqueue(std::move(job));
......@@ -361,7 +336,7 @@ bool CompilerDispatcher::EnqueueAndStep(
PrintF(" for compile\n");
}
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<CompilerDispatcherJob> job(new UnoptimizedCompileJob(
isolate_, tracer_.get(), script, function, literal, outer_parse_info,
compile_handles, max_stack_size_));
EnqueueAndStep(std::move(job));
......@@ -460,7 +435,7 @@ void CompilerDispatcher::AbortAll(BlockingBehavior blocking) {
it.second->ResetOnMainThread();
}
jobs_.clear();
shared_to_job_id_.Clear();
shared_to_unoptimized_job_id_.Clear();
{
base::LockGuard<base::Mutex> lock(&mutex_);
DCHECK(pending_background_jobs_.empty());
......@@ -546,11 +521,12 @@ void CompilerDispatcher::MemoryPressureNotification(
CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::GetJobFor(
Handle<SharedFunctionInfo> shared) const {
JobId* job_id_ptr = shared_to_job_id_.Find(shared);
JobId* job_id_ptr = shared_to_unoptimized_job_id_.Find(shared);
JobMap::const_iterator job = jobs_.end();
if (job_id_ptr) {
job = jobs_.find(*job_id_ptr);
DCHECK(job == jobs_.end() || job->second->IsAssociatedWith(shared));
DCHECK(job == jobs_.end() ||
job->second->AsUnoptimizedCompileJob()->IsAssociatedWith(shared));
}
return job;
}
......@@ -751,18 +727,51 @@ CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::RemoveIfFinished(
return RemoveJob(job);
}
CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::InsertJob(
std::unique_ptr<CompilerDispatcherJob> job) {
bool added;
JobMap::const_iterator it;
std::tie(it, added) =
jobs_.insert(std::make_pair(next_job_id_++, std::move(job)));
DCHECK(added);
JobId id = it->first;
CompilerDispatcherJob* inserted_job = it->second.get();
// Maps unoptimized jobs' SFIs to their job id.
if (inserted_job->type() == CompilerDispatcherJob::kUnoptimizedCompile) {
Handle<SharedFunctionInfo> shared =
inserted_job->AsUnoptimizedCompileJob()->shared();
if (!shared.is_null()) {
shared_to_unoptimized_job_id_.Set(shared, id);
}
}
return it;
}
CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::RemoveJob(
CompilerDispatcher::JobMap::const_iterator job) {
job->second->ResetOnMainThread();
if (!job->second->shared().is_null()) {
shared_to_job_id_.Delete(job->second->shared());
CompilerDispatcher::JobMap::const_iterator it) {
CompilerDispatcherJob* job = it->second.get();
job->ResetOnMainThread();
// Unmaps unoptimized jobs' SFIs to their job id.
if (job->type() == CompilerDispatcherJob::kUnoptimizedCompile) {
Handle<SharedFunctionInfo> shared =
job->AsUnoptimizedCompileJob()->shared();
if (!shared.is_null()) {
JobId deleted_id = shared_to_unoptimized_job_id_.Delete(shared);
USE(deleted_id);
DCHECK_EQ(it->first, deleted_id);
}
}
job = jobs_.erase(job);
it = jobs_.erase(it);
if (jobs_.empty()) {
base::LockGuard<base::Mutex> lock(&mutex_);
if (num_background_tasks_ == 0) abort_ = false;
}
return job;
return it;
}
} // namespace internal
......
......@@ -29,8 +29,9 @@ namespace internal {
class AstValueFactory;
class CancelableTaskManager;
class CompileJobFinishCallback;
class CompilerDispatcherJob;
class UnoptimizedCompileJob;
class UnoptimizedCompileJobFinishCallback;
class CompilerDispatcherTracer;
class DeferredHandles;
class FunctionLiteral;
......@@ -88,7 +89,8 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
bool Enqueue(Handle<String> source, int start_pos, int end_position,
LanguageMode language_mode, int function_literal_id, bool native,
bool module, bool is_named_expression, int compiler_hints,
CompileJobFinishCallback* finish_callback, JobId* job_id);
UnoptimizedCompileJobFinishCallback* finish_callback,
JobId* job_id);
// Like Enqueue, but also advances the job so that it can potentially
// continue running on a background thread (if at all possible). Returns
......@@ -167,6 +169,8 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
JobId EnqueueAndStep(std::unique_ptr<CompilerDispatcherJob> job);
// Returns job if not removed otherwise iterator following the removed job.
JobMap::const_iterator RemoveIfFinished(JobMap::const_iterator job);
// Returns iterator to the inserted job.
JobMap::const_iterator InsertJob(std::unique_ptr<CompilerDispatcherJob> job);
// Returns iterator following the removed job.
JobMap::const_iterator RemoveJob(JobMap::const_iterator job);
bool FinishNow(CompilerDispatcherJob* job);
......@@ -188,8 +192,9 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
// Mapping from job_id to job.
JobMap jobs_;
// Mapping from SharedFunctionInfo to corresponding JobId;
SharedToJobIdMap shared_to_job_id_;
// Mapping from SharedFunctionInfo to the corresponding unoptimized
// compilation's JobId;
SharedToJobIdMap shared_to_unoptimized_job_id_;
base::AtomicValue<v8::MemoryPressureLevel> memory_pressure_level_;
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler-dispatcher/unoptimized-compile-job.h"
#include "src/assert-scope.h"
#include "src/base/optional.h"
#include "src/compilation-info.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/compiler.h"
#include "src/flags.h"
#include "src/global-handles.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser.h"
#include "src/parsing/scanner-character-streams.h"
#include "src/unicode-cache.h"
#include "src/utils.h"
namespace v8 {
namespace internal {
namespace {
class OneByteWrapper : public v8::String::ExternalOneByteStringResource {
public:
OneByteWrapper(const void* data, int length) : data_(data), length_(length) {}
~OneByteWrapper() override = default;
const char* data() const override {
return reinterpret_cast<const char*>(data_);
}
size_t length() const override { return static_cast<size_t>(length_); }
private:
const void* data_;
int length_;
DISALLOW_COPY_AND_ASSIGN(OneByteWrapper);
};
class TwoByteWrapper : public v8::String::ExternalStringResource {
public:
TwoByteWrapper(const void* data, int length) : data_(data), length_(length) {}
~TwoByteWrapper() override = default;
const uint16_t* data() const override {
return reinterpret_cast<const uint16_t*>(data_);
}
size_t length() const override { return static_cast<size_t>(length_); }
private:
const void* data_;
int length_;
DISALLOW_COPY_AND_ASSIGN(TwoByteWrapper);
};
} // namespace
UnoptimizedCompileJob::UnoptimizedCompileJob(
CompilerDispatcherTracer* tracer, size_t max_stack_size,
Handle<String> source, int start_position, int end_position,
LanguageMode language_mode, int function_literal_id, bool native,
bool module, bool is_named_expression, uint32_t hash_seed,
AccountingAllocator* zone_allocator, int compiler_hints,
const AstStringConstants* ast_string_constants,
UnoptimizedCompileJobFinishCallback* finish_callback)
: status_(Status::kReadyToParse),
isolate_(nullptr),
tracer_(tracer),
max_stack_size_(max_stack_size),
finish_callback_(finish_callback),
trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
parse_info_.reset(new ParseInfo(zone_allocator));
DCHECK(source->IsExternalTwoByteString() ||
source->IsExternalOneByteString());
character_stream_.reset(
ScannerStream::For(source, start_position, end_position));
parse_info_->set_character_stream(character_stream_.get());
parse_info_->set_hash_seed(hash_seed);
parse_info_->set_compiler_hints(compiler_hints);
parse_info_->set_start_position(start_position);
parse_info_->set_end_position(end_position);
unicode_cache_.reset(new UnicodeCache());
parse_info_->set_unicode_cache(unicode_cache_.get());
parse_info_->set_language_mode(language_mode);
parse_info_->set_function_literal_id(function_literal_id);
parse_info_->set_ast_string_constants(ast_string_constants);
if (V8_UNLIKELY(FLAG_runtime_stats)) {
parse_info_->set_runtime_call_stats(new (parse_info_->zone())
RuntimeCallStats());
}
parse_info_->set_native(native);
parse_info_->set_module(module);
parse_info_->set_is_named_expression(is_named_expression);
parser_.reset(new Parser(parse_info_.get()));
parser_->DeserializeScopeChain(parse_info_.get(), MaybeHandle<ScopeInfo>());
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p] created for ", static_cast<void*>(this));
ShortPrint();
PrintF(" in ready to parse state.\n");
}
}
UnoptimizedCompileJob::UnoptimizedCompileJob(Isolate* isolate,
CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
size_t max_stack_size)
: status_(Status::kInitial),
isolate_(isolate),
tracer_(tracer),
context_(isolate_->global_handles()->Create(isolate->context())),
shared_(isolate_->global_handles()->Create(*shared)),
max_stack_size_(max_stack_size),
trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
DCHECK(!shared_->is_toplevel());
HandleScope scope(isolate_);
Handle<Script> script(Script::cast(shared_->script()), isolate_);
Handle<String> source(String::cast(script->source()), isolate_);
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p] created for ", static_cast<void*>(this));
ShortPrint();
PrintF(" in initial state.\n");
}
}
UnoptimizedCompileJob::UnoptimizedCompileJob(
Isolate* isolate, CompilerDispatcherTracer* tracer, Handle<Script> script,
Handle<SharedFunctionInfo> shared, FunctionLiteral* literal,
ParseInfo* outer_parse_info,
std::shared_ptr<DeferredHandles> compile_handles, size_t max_stack_size)
: status_(Status::kAnalyzed),
isolate_(isolate),
tracer_(tracer),
context_(isolate_->global_handles()->Create(isolate->context())),
shared_(isolate_->global_handles()->Create(*shared)),
max_stack_size_(max_stack_size),
parse_info_(new ParseInfo(shared_)),
compile_zone_(new Zone(isolate->allocator(), ZONE_NAME)),
compile_info_(new CompilationInfo(compile_zone_.get(), parse_info_.get(),
isolate_, shared_,
Handle<JSFunction>::null())),
trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
parse_info_->set_literal(literal);
parse_info_->set_script(script);
parse_info_->ShareAstValueFactory(outer_parse_info);
parse_info_->ShareZone(outer_parse_info);
compile_info_->set_deferred_handles(compile_handles);
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p] created for ", static_cast<void*>(this));
ShortPrint();
PrintF(" in Analyzed state.\n");
}
}
UnoptimizedCompileJob::~UnoptimizedCompileJob() {
DCHECK(status_ == Status::kInitial ||
(status_ == Status::kReadyToParse && finish_callback_) ||
status_ == Status::kDone);
if (!shared_.is_null()) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
i::GlobalHandles::Destroy(Handle<Object>::cast(shared_).location());
}
if (!context_.is_null()) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
i::GlobalHandles::Destroy(Handle<Object>::cast(context_).location());
}
}
bool UnoptimizedCompileJob::IsAssociatedWith(
Handle<SharedFunctionInfo> shared) const {
return *shared_ == *shared;
}
void UnoptimizedCompileJob::StepNextOnMainThread() {
// Ensure we are in the correct context for the job.
base::Optional<SaveContext> save;
if (has_context()) {
DCHECK_NOT_NULL(isolate_);
save.emplace(isolate_);
isolate_->set_context(context());
} else {
// Phases which can run off the main thread by definition can't execute any
// JS code, and so we don't need to enter their context.
DCHECK(CanStepNextOnAnyThread());
}
switch (status()) {
case Status::kInitial:
return PrepareToParseOnMainThread();
case Status::kReadyToParse:
return Parse();
case Status::kParsed:
return FinalizeParsingOnMainThread();
case Status::kReadyToAnalyze:
return AnalyzeOnMainThread();
case Status::kAnalyzed:
return PrepareToCompileOnMainThread();
case Status::kReadyToCompile:
return Compile();
case Status::kCompiled:
return FinalizeCompilingOnMainThread();
case Status::kFailed:
case Status::kDone:
return;
}
UNREACHABLE();
}
void UnoptimizedCompileJob::StepNextOnBackgroundThread() {
DCHECK(CanStepNextOnAnyThread());
switch (status()) {
case Status::kReadyToParse:
return Parse();
case Status::kReadyToCompile:
return Compile();
default:
UNREACHABLE();
}
}
void UnoptimizedCompileJob::PrepareToParseOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == Status::kInitial);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToParse);
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p]: Preparing to parse\n",
static_cast<void*>(this));
}
HandleScope scope(isolate_);
unicode_cache_.reset(new UnicodeCache());
Handle<Script> script(Script::cast(shared_->script()), isolate_);
DCHECK(script->type() != Script::TYPE_NATIVE);
Handle<String> source(String::cast(script->source()), isolate_);
parse_info_.reset(new ParseInfo(isolate_->allocator()));
if (source->IsExternalTwoByteString() || source->IsExternalOneByteString()) {
character_stream_.reset(ScannerStream::For(
source, shared_->start_position(), shared_->end_position()));
} else {
source = String::Flatten(source);
const void* data;
int offset = 0;
int length = source->length();
// Objects in lo_space don't move, so we can just read the contents from
// any thread.
if (isolate_->heap()->lo_space()->Contains(*source)) {
// We need to globalize the handle to the flattened string here, in
// case it's not referenced from anywhere else.
source_ = isolate_->global_handles()->Create(*source);
DisallowHeapAllocation no_allocation;
String::FlatContent content = source->GetFlatContent();
DCHECK(content.IsFlat());
data =
content.IsOneByte()
? reinterpret_cast<const void*>(content.ToOneByteVector().start())
: reinterpret_cast<const void*>(content.ToUC16Vector().start());
} else {
// Otherwise, create a copy of the part of the string we'll parse in the
// zone.
length = (shared_->end_position() - shared_->start_position());
offset = shared_->start_position();
int byte_len = length * (source->IsOneByteRepresentation() ? 1 : 2);
data = parse_info_->zone()->New(byte_len);
DisallowHeapAllocation no_allocation;
String::FlatContent content = source->GetFlatContent();
DCHECK(content.IsFlat());
if (content.IsOneByte()) {
MemCopy(const_cast<void*>(data),
&content.ToOneByteVector().at(shared_->start_position()),
byte_len);
} else {
MemCopy(const_cast<void*>(data),
&content.ToUC16Vector().at(shared_->start_position()),
byte_len);
}
}
Handle<String> wrapper;
if (source->IsOneByteRepresentation()) {
ExternalOneByteString::Resource* resource =
new OneByteWrapper(data, length);
source_wrapper_.reset(resource);
wrapper = isolate_->factory()
->NewExternalStringFromOneByte(resource)
.ToHandleChecked();
} else {
ExternalTwoByteString::Resource* resource =
new TwoByteWrapper(data, length);
source_wrapper_.reset(resource);
wrapper = isolate_->factory()
->NewExternalStringFromTwoByte(resource)
.ToHandleChecked();
}
wrapper_ = isolate_->global_handles()->Create(*wrapper);
character_stream_.reset(
ScannerStream::For(wrapper_, shared_->start_position() - offset,
shared_->end_position() - offset));
}
parse_info_->InitFromIsolate(isolate_);
parse_info_->set_character_stream(character_stream_.get());
parse_info_->set_hash_seed(isolate_->heap()->HashSeed());
parse_info_->set_is_named_expression(shared_->is_named_expression());
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());
parse_info_->set_function_literal_id(shared_->function_literal_id());
if (V8_UNLIKELY(FLAG_runtime_stats)) {
parse_info_->set_runtime_call_stats(new (parse_info_->zone())
RuntimeCallStats());
}
parser_.reset(new Parser(parse_info_.get()));
MaybeHandle<ScopeInfo> outer_scope_info;
if (!shared_->outer_scope_info()->IsTheHole(isolate_) &&
ScopeInfo::cast(shared_->outer_scope_info())->length() > 0) {
outer_scope_info = handle(ScopeInfo::cast(shared_->outer_scope_info()));
}
parser_->DeserializeScopeChain(parse_info_.get(), outer_scope_info);
Handle<String> name(shared_->name());
parse_info_->set_function_name(
parse_info_->ast_value_factory()->GetString(name));
status_ = Status::kReadyToParse;
}
void UnoptimizedCompileJob::Parse() {
DCHECK(status() == Status::kReadyToParse);
COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM(
tracer_, kParse,
parse_info_->end_position() - parse_info_->start_position());
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p]: Parsing\n", static_cast<void*>(this));
}
DisallowHeapAllocation no_allocation;
DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref;
uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB;
parser_->set_stack_limit(stack_limit);
parser_->ParseOnBackground(parse_info_.get());
if (finish_callback_) {
finish_callback_->ParseFinished(std::move(parse_info_));
status_ = Status::kDone;
} else {
status_ = Status::kParsed;
}
}
void UnoptimizedCompileJob::FinalizeParsingOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == Status::kParsed);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeParsing);
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p]: Finalizing parsing\n",
static_cast<void*>(this));
}
if (!source_.is_null()) {
i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location());
source_ = Handle<String>::null();
}
if (!wrapper_.is_null()) {
i::GlobalHandles::Destroy(Handle<Object>::cast(wrapper_).location());
wrapper_ = Handle<String>::null();
}
Handle<Script> script(Script::cast(shared_->script()), isolate_);
parse_info_->set_script(script);
if (parse_info_->literal() == nullptr) {
parser_->ReportErrors(isolate_, script);
status_ = Status::kFailed;
} else {
status_ = Status::kReadyToAnalyze;
}
parser_->UpdateStatistics(isolate_, script);
parse_info_->UpdateStatisticsAfterBackgroundParse(isolate_);
if (!shared_->outer_scope_info()->IsTheHole(isolate_) &&
ScopeInfo::cast(shared_->outer_scope_info())->length() > 0) {
Handle<ScopeInfo> outer_scope_info(
handle(ScopeInfo::cast(shared_->outer_scope_info())));
parse_info_->set_outer_scope_info(outer_scope_info);
}
parser_->HandleSourceURLComments(isolate_, script);
parse_info_->set_character_stream(nullptr);
parse_info_->set_unicode_cache(nullptr);
parser_.reset();
unicode_cache_.reset();
character_stream_.reset();
}
void UnoptimizedCompileJob::AnalyzeOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == Status::kReadyToAnalyze);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kAnalyze);
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p]: Analyzing\n", static_cast<void*>(this));
}
compile_zone_.reset(new Zone(isolate_->allocator(), ZONE_NAME));
compile_info_.reset(new CompilationInfo(
compile_zone_.get(), parse_info_.get(), isolate_,
Handle<SharedFunctionInfo>::null(), Handle<JSFunction>::null()));
DeferredHandleScope scope(isolate_);
{
if (Compiler::Analyze(compile_info_.get())) {
status_ = Status::kAnalyzed;
} else {
status_ = Status::kFailed;
if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
}
}
compile_info_->set_deferred_handles(scope.Detach());
}
void UnoptimizedCompileJob::PrepareToCompileOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == Status::kAnalyzed);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile);
compile_job_.reset(
Compiler::PrepareUnoptimizedCompilationJob(compile_info_.get()));
if (!compile_job_.get()) {
if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
status_ = Status::kFailed;
return;
}
CHECK(compile_job_->can_execute_on_background_thread());
status_ = Status::kReadyToCompile;
}
void UnoptimizedCompileJob::Compile() {
DCHECK(status() == Status::kReadyToCompile);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kCompile);
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p]: Compiling\n", static_cast<void*>(this));
}
// Disallowing of handle dereference and heap access dealt with in
// CompilationJob::ExecuteJob.
uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB;
compile_job_->set_stack_limit(stack_limit);
CompilationJob::Status status = compile_job_->ExecuteJob();
USE(status);
// Always transition to kCompiled - errors will be reported by
// FinalizeCompilingOnMainThread.
status_ = Status::kCompiled;
}
void UnoptimizedCompileJob::FinalizeCompilingOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == Status::kCompiled);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeCompiling);
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p]: Finalizing compiling\n",
static_cast<void*>(this));
}
{
HandleScope scope(isolate_);
compile_info_->set_shared_info(shared_);
if (compile_job_->state() == CompilationJob::State::kFailed ||
!Compiler::FinalizeCompilationJob(compile_job_.release())) {
if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
status_ = Status::kFailed;
return;
}
}
compile_job_.reset();
compile_info_.reset();
compile_zone_.reset();
parse_info_.reset();
status_ = Status::kDone;
}
void UnoptimizedCompileJob::ResetOnMainThread() {
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p]: Resetting\n", static_cast<void*>(this));
}
compile_job_.reset();
compile_info_.reset();
compile_zone_.reset();
parser_.reset();
unicode_cache_.reset();
character_stream_.reset();
parse_info_.reset();
finish_callback_ = nullptr;
if (!source_.is_null()) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location());
source_ = Handle<String>::null();
}
if (!wrapper_.is_null()) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
i::GlobalHandles::Destroy(Handle<Object>::cast(wrapper_).location());
wrapper_ = Handle<String>::null();
}
status_ = Status::kInitial;
}
double UnoptimizedCompileJob::EstimateRuntimeOfNextStepInMs() const {
switch (status()) {
case Status::kInitial:
return tracer_->EstimatePrepareToParseInMs();
case Status::kReadyToParse:
return tracer_->EstimateParseInMs(parse_info_->end_position() -
parse_info_->start_position());
case Status::kParsed:
return tracer_->EstimateFinalizeParsingInMs();
case Status::kReadyToAnalyze:
return tracer_->EstimateAnalyzeInMs();
case Status::kAnalyzed:
return tracer_->EstimatePrepareToCompileInMs();
case Status::kReadyToCompile:
return tracer_->EstimateCompileInMs();
case Status::kCompiled:
return tracer_->EstimateFinalizeCompilingInMs();
case Status::kFailed:
case Status::kDone:
return 0.0;
}
UNREACHABLE();
}
void UnoptimizedCompileJob::ShortPrint() {
if (isolate_) {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(!shared_.is_null());
shared_->ShortPrint();
} else {
// TODO(wiktorg) more useful info in those cases
if (parse_info_) {
PrintF("function at %d", parse_info_->start_position());
} else {
PrintF("parsed function");
}
}
}
} // namespace internal
} // namespace v8
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_DISPATCHER_UNOPTIMIZED_COMPILE_JOB_H_
#define V8_COMPILER_DISPATCHER_UNOPTIMIZED_COMPILE_JOB_H_
#include <memory>
#include "include/v8.h"
#include "src/base/macros.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/globals.h"
namespace v8 {
namespace internal {
class AstValueFactory;
class AstStringConstants;
class CompilerDispatcherTracer;
class CompilationInfo;
class CompilationJob;
class DeferredHandles;
class FunctionLiteral;
class Isolate;
class ParseInfo;
class Parser;
class SharedFunctionInfo;
class String;
class UnicodeCache;
class Utf16CharacterStream;
class V8_EXPORT_PRIVATE UnoptimizedCompileJobFinishCallback {
public:
virtual ~UnoptimizedCompileJobFinishCallback() {}
virtual void ParseFinished(std::unique_ptr<ParseInfo> parse_info) = 0;
};
class V8_EXPORT_PRIVATE UnoptimizedCompileJob : public CompilerDispatcherJob {
public:
enum class Status {
kInitial,
kReadyToParse,
kParsed,
kReadyToAnalyze,
kAnalyzed,
kReadyToCompile,
kCompiled,
kDone,
kFailed,
};
// Creates a UnoptimizedCompileJob in the initial state.
UnoptimizedCompileJob(Isolate* isolate, CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
size_t max_stack_size);
// TODO(wiktorg) document it better once I know how it relates to whole stuff
// Creates a UnoptimizedCompileJob in ready to parse top-level function state.
UnoptimizedCompileJob(CompilerDispatcherTracer* tracer, size_t max_stack_size,
Handle<String> source, int start_position,
int end_position, LanguageMode language_mode,
int function_literal_id, bool native, bool module,
bool is_named_expression, uint32_t hash_seed,
AccountingAllocator* zone_allocator, int compiler_hints,
const AstStringConstants* ast_string_constants,
UnoptimizedCompileJobFinishCallback* finish_callback);
// Creates a UnoptimizedCompileJob in the analyzed state.
UnoptimizedCompileJob(Isolate* isolate, CompilerDispatcherTracer* tracer,
Handle<Script> script,
Handle<SharedFunctionInfo> shared,
FunctionLiteral* literal, ParseInfo* outer_parse_info,
std::shared_ptr<DeferredHandles> compile_handles,
size_t max_stack_size);
~UnoptimizedCompileJob() override;
Type type() const override { return kUnoptimizedCompile; }
Handle<SharedFunctionInfo> shared() const { return shared_; }
// Returns true if this UnoptimizedCompileJob was created for the given
// function.
bool IsAssociatedWith(Handle<SharedFunctionInfo> shared) const;
bool IsFinished() override {
return status() == Status::kDone || status() == Status::kFailed;
}
bool IsFailed() override { return status() == Status::kFailed; }
// Return true if the next step can be run on any thread, that is when both
// StepNextOnMainThread and StepNextOnBackgroundThread could be used for the
// next step.
bool CanStepNextOnAnyThread() override {
return status() == Status::kReadyToParse ||
status() == Status::kReadyToCompile;
}
// Step the job forward by one state on the main thread.
void StepNextOnMainThread() override;
// Step the job forward by one state on a background thread.
void StepNextOnBackgroundThread() override;
// Transition from any state to kInitial and free all resources.
void ResetOnMainThread() override;
// Estimate how long the next step will take using the tracer.
double EstimateRuntimeOfNextStepInMs() const override;
// Even though the name does not imply this, ShortPrint() must only be invoked
// on the main thread.
void ShortPrint() override;
private:
friend class CompilerDispatcherTest;
friend class UnoptimizedCompileJobTest;
bool has_context() const { return !context_.is_null(); }
Context* context() { return *context_; }
Status status() const { return status_; }
Status status_;
Isolate* isolate_;
CompilerDispatcherTracer* tracer_;
Handle<Context> context_; // Global handle.
Handle<SharedFunctionInfo> shared_; // Global handle.
Handle<String> source_; // Global handle.
Handle<String> wrapper_; // Global handle.
std::unique_ptr<v8::String::ExternalStringResourceBase> source_wrapper_;
size_t max_stack_size_;
UnoptimizedCompileJobFinishCallback* finish_callback_ = nullptr;
// Members required for parsing.
std::unique_ptr<UnicodeCache> unicode_cache_;
std::unique_ptr<Utf16CharacterStream> character_stream_;
std::unique_ptr<ParseInfo> parse_info_;
std::unique_ptr<Parser> parser_;
// Members required for compiling.
std::shared_ptr<Zone> compile_zone_;
std::unique_ptr<CompilationInfo> compile_info_;
std::unique_ptr<CompilationJob> compile_job_;
bool trace_compiler_dispatcher_jobs_;
// Transition from kInitial to kReadyToParse.
void PrepareToParseOnMainThread();
// Transition from kReadyToParse to kParsed (or kDone if there is
// finish_callback).
void Parse();
// Transition from kParsed to kReadyToAnalyze (or kFailed).
void FinalizeParsingOnMainThread();
// Transition from kReadyToAnalyze to kAnalyzed (or kFailed).
void AnalyzeOnMainThread();
// Transition from kAnalyzed to kReadyToCompile (or kFailed).
void PrepareToCompileOnMainThread();
// Transition from kReadyToCompile to kCompiled.
void Compile();
// Transition from kCompiled to kDone (or kFailed).
void FinalizeCompilingOnMainThread();
DISALLOW_COPY_AND_ASSIGN(UnoptimizedCompileJob);
};
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_DISPATCHER_UNOPTIMIZED_COMPILE_JOB_H_
......@@ -10,7 +10,7 @@
#include <vector>
#include "include/v8.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/compiler-dispatcher/unoptimized-compile-job.h"
#include "src/globals.h"
#include "src/handles.h"
#include "src/parsing/preparsed-scope-data.h"
......@@ -35,7 +35,7 @@ class Utf16CharacterStream;
class Zone;
// A container for the inputs, configuration options, and outputs of parsing.
class V8_EXPORT_PRIVATE ParseInfo : public CompileJobFinishCallback {
class V8_EXPORT_PRIVATE ParseInfo : public UnoptimizedCompileJobFinishCallback {
public:
explicit ParseInfo(AccountingAllocator* zone_allocator);
ParseInfo(Handle<Script> script);
......
......@@ -894,6 +894,8 @@
'compiler-dispatcher/compiler-dispatcher-tracer.h',
'compiler-dispatcher/optimizing-compile-dispatcher.cc',
'compiler-dispatcher/optimizing-compile-dispatcher.h',
'compiler-dispatcher/unoptimized-compile-job.cc',
'compiler-dispatcher/unoptimized-compile-job.h',
'compiler.cc',
'compiler.h',
'contexts-inl.h',
......
......@@ -40,10 +40,10 @@ v8_executable("unittests") {
"base/utils/random-number-generator-unittest.cc",
"cancelable-tasks-unittest.cc",
"char-predicates-unittest.cc",
"compiler-dispatcher/compiler-dispatcher-job-unittest.cc",
"compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc",
"compiler-dispatcher/compiler-dispatcher-unittest.cc",
"compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc",
"compiler-dispatcher/unoptimized-compile-job-unittest.cc",
"compiler/branch-elimination-unittest.cc",
"compiler/bytecode-analysis-unittest.cc",
"compiler/checkpoint-elimination-unittest.cc",
......
......@@ -77,13 +77,15 @@ class CompilerDispatcherTest : public TestWithContext {
CompilerDispatcherTestFlags::RestoreFlags();
}
static CompileJobStatus GetJobStatus(const CompilerDispatcherJob* job) {
return job->status();
static UnoptimizedCompileJob::Status GetUnoptimizedJobStatus(
const CompilerDispatcherJob* job) {
CHECK_EQ(CompilerDispatcherJob::kUnoptimizedCompile, job->type());
return job->AsUnoptimizedCompileJob()->status();
}
static CompileJobStatus GetJobStatus(
static UnoptimizedCompileJob::Status GetUnoptimizedJobStatus(
const std::unique_ptr<CompilerDispatcherJob>& job) {
return GetJobStatus(job.get());
return GetUnoptimizedJobStatus(job.get());
}
private:
......@@ -405,8 +407,8 @@ TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
// The job should be scheduled for the main thread.
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(CompileJobStatus::kInitial,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
// Only grant a little idle time and have time advance beyond it in one step.
platform.RunIdleTask(2.0, 1.0);
......@@ -418,8 +420,8 @@ TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
// The job should be still scheduled for the main thread, but ready for
// parsing.
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(CompileJobStatus::kReadyToParse,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToParse,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
......@@ -470,15 +472,15 @@ TEST_F(CompilerDispatcherTest, CompileOnBackgroundThread) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(CompileJobStatus::kInitial,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
......@@ -489,8 +491,8 @@ TEST_F(CompilerDispatcherTest, CompileOnBackgroundThread) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_EQ(CompileJobStatus::kCompiled,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kCompiled,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
......@@ -514,15 +516,15 @@ TEST_F(CompilerDispatcherTest, FinishNowWithBackgroundTask) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(CompileJobStatus::kInitial,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
......@@ -611,15 +613,15 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingBackgroundTask) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(CompileJobStatus::kInitial,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
......@@ -659,15 +661,15 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllRunningBackgroundTask) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(CompileJobStatus::kInitial,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(dispatcher.IsEnqueued(shared1));
ASSERT_FALSE(shared1->is_compiled());
......@@ -736,15 +738,15 @@ TEST_F(CompilerDispatcherTest, FinishNowDuringAbortAll) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(CompileJobStatus::kInitial,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
......@@ -890,7 +892,7 @@ TEST_F(CompilerDispatcherTest, EnqueueJob) {
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
std::unique_ptr<CompilerDispatcherJob> job(
new CompilerDispatcherJob(i_isolate(), dispatcher.tracer_.get(), shared,
new UnoptimizedCompileJob(i_isolate(), dispatcher.tracer_.get(), shared,
dispatcher.max_stack_size_));
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
dispatcher.Enqueue(std::move(job));
......@@ -905,7 +907,7 @@ TEST_F(CompilerDispatcherTest, EnqueueWithoutSFI) {
MockPlatform platform(V8::GetCurrentPlatform()->GetTracingController());
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
ASSERT_TRUE(dispatcher.jobs_.empty());
ASSERT_TRUE(dispatcher.shared_to_job_id_.empty());
ASSERT_TRUE(dispatcher.shared_to_unoptimized_job_id_.empty());
std::unique_ptr<test::FinishCallback> callback(new test::FinishCallback());
std::unique_ptr<test::ScriptResource> resource(
new test::ScriptResource(test_script, strlen(test_script)));
......@@ -915,9 +917,9 @@ TEST_F(CompilerDispatcherTest, EnqueueWithoutSFI) {
1, false, false, false, 0, callback.get(),
nullptr));
ASSERT_TRUE(!dispatcher.jobs_.empty());
ASSERT_EQ(CompileJobStatus::kReadyToParse,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(dispatcher.shared_to_job_id_.empty());
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToParse,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(dispatcher.shared_to_unoptimized_job_id_.empty());
ASSERT_TRUE(callback->result() == nullptr);
ASSERT_TRUE(platform.IdleTaskPending());
......@@ -939,8 +941,8 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStep) {
ASSERT_TRUE(dispatcher.EnqueueAndStep(shared));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_EQ(CompileJobStatus::kReadyToParse,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToParse,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(platform.IdleTaskPending());
platform.ClearIdleTask();
......@@ -967,8 +969,8 @@ TEST_F(CompilerDispatcherTest, EnqueueParsed) {
&parse_info, handles));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_EQ(CompileJobStatus::kAnalyzed,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kAnalyzed,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(platform.IdleTaskPending());
platform.ClearIdleTask();
......@@ -994,8 +996,8 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStepParsed) {
&parse_info, handles));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
......@@ -1180,19 +1182,19 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStepTwice) {
&parse_info, handles));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
// EnqueueAndStep of the same function again (either already parsed or for
// compile and parse) shouldn't step the job.
ASSERT_TRUE(dispatcher.EnqueueAndStep(script, shared, parse_info.literal(),
&parse_info, handles));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(dispatcher.EnqueueAndStep(shared));
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
......@@ -1219,20 +1221,20 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
ASSERT_EQ(CompileJobStatus::kInitial,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(CompileJobStatus::kInitial,
GetJobStatus((++dispatcher.jobs_.begin())->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus((++dispatcher.jobs_.begin())->second));
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(CompileJobStatus::kReadyToCompile,
GetJobStatus((++dispatcher.jobs_.begin())->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus((++dispatcher.jobs_.begin())->second));
ASSERT_TRUE(dispatcher.IsEnqueued(shared1));
ASSERT_TRUE(dispatcher.IsEnqueued(shared2));
......@@ -1246,10 +1248,10 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
ASSERT_EQ(CompileJobStatus::kCompiled,
GetJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(CompileJobStatus::kCompiled,
GetJobStatus((++dispatcher.jobs_.begin())->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kCompiled,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kCompiled,
GetUnoptimizedJobStatus((++dispatcher.jobs_.begin())->second));
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
......
......@@ -22,10 +22,10 @@
namespace v8 {
namespace internal {
class CompilerDispatcherJobTest : public TestWithContext {
class UnoptimizedCompileJobTest : public TestWithContext {
public:
CompilerDispatcherJobTest() : tracer_(i_isolate()) {}
~CompilerDispatcherJobTest() override {}
UnoptimizedCompileJobTest() : tracer_(i_isolate()) {}
~UnoptimizedCompileJobTest() override {}
CompilerDispatcherTracer* tracer() { return &tracer_; }
......@@ -43,16 +43,16 @@ class CompilerDispatcherJobTest : public TestWithContext {
save_flags_ = nullptr;
}
static CompileJobStatus GetStatus(CompilerDispatcherJob* job) {
static UnoptimizedCompileJob::Status GetStatus(UnoptimizedCompileJob* job) {
return job->status();
}
static CompileJobStatus GetStatus(
const std::unique_ptr<CompilerDispatcherJob>& job) {
static UnoptimizedCompileJob::Status GetStatus(
const std::unique_ptr<UnoptimizedCompileJob>& job) {
return GetStatus(job.get());
}
static Variable* LookupVariableByName(CompilerDispatcherJob* job,
static Variable* LookupVariableByName(UnoptimizedCompileJob* job,
const char* name) {
const AstRawString* name_raw_string =
job->parse_info_->ast_value_factory()->GetOneByteString(name);
......@@ -63,10 +63,10 @@ class CompilerDispatcherJobTest : public TestWithContext {
CompilerDispatcherTracer tracer_;
static SaveFlags* save_flags_;
DISALLOW_COPY_AND_ASSIGN(CompilerDispatcherJobTest);
DISALLOW_COPY_AND_ASSIGN(UnoptimizedCompileJobTest);
};
SaveFlags* CompilerDispatcherJobTest::save_flags_ = nullptr;
SaveFlags* UnoptimizedCompileJobTest::save_flags_ = nullptr;
namespace {
......@@ -76,17 +76,17 @@ const char test_script[] = "(x) { x*x; }";
#define ASSERT_JOB_STATUS(STATUS, JOB) ASSERT_EQ(STATUS, GetStatus(JOB))
TEST_F(CompilerDispatcherJobTest, Construct) {
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
TEST_F(UnoptimizedCompileJobTest, Construct) {
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
i_isolate(), tracer(),
test::CreateSharedFunctionInfo(i_isolate(), nullptr), FLAG_stack_size));
}
TEST_F(CompilerDispatcherJobTest, ConstructWithoutSFI) {
TEST_F(UnoptimizedCompileJobTest, ConstructWithoutSFI) {
std::unique_ptr<test::FinishCallback> callback(new test::FinishCallback());
std::unique_ptr<test::ScriptResource> resource(
new test::ScriptResource(test_script, strlen(test_script)));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
tracer(), FLAG_stack_size,
test::CreateSource(i_isolate(), resource.get()), 0,
static_cast<int>(resource->length()), SLOPPY, 1, false, false, false,
......@@ -95,60 +95,60 @@ TEST_F(CompilerDispatcherJobTest, ConstructWithoutSFI) {
callback.get()));
}
TEST_F(CompilerDispatcherJobTest, StateTransitions) {
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
TEST_F(UnoptimizedCompileJobTest, StateTransitions) {
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
i_isolate(), tracer(),
test::CreateSharedFunctionInfo(i_isolate(), nullptr), FLAG_stack_size));
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kReadyToParse, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kReadyToParse, job);
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kParsed, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kParsed, job);
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kReadyToAnalyze, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kReadyToAnalyze, job);
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kAnalyzed, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kAnalyzed, job);
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kReadyToCompile, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kReadyToCompile, job);
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kCompiled, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kCompiled, job);
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kDone, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kDone, job);
job->ResetOnMainThread();
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
}
TEST_F(CompilerDispatcherJobTest, StateTransitionsParseWithCallback) {
TEST_F(UnoptimizedCompileJobTest, StateTransitionsParseWithCallback) {
std::unique_ptr<test::FinishCallback> callback(new test::FinishCallback());
std::unique_ptr<test::ScriptResource> resource(
new test::ScriptResource(test_script, strlen(test_script)));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
tracer(), FLAG_stack_size,
test::CreateSource(i_isolate(), resource.get()), 0,
static_cast<int>(resource->length()), SLOPPY, 1, false, false, false,
i_isolate()->heap()->HashSeed(), i_isolate()->allocator(),
ScriptCompiler::kNoCompileOptions, i_isolate()->ast_string_constants(),
callback.get()));
ASSERT_JOB_STATUS(CompileJobStatus::kReadyToParse, job);
job->StepNextOnMainThread();
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kReadyToParse, job);
job->StepNextOnBackgroundThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kDone, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kDone, job);
job->ResetOnMainThread();
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
ASSERT_TRUE(callback->result() != nullptr);
}
TEST_F(CompilerDispatcherJobTest, SyntaxError) {
TEST_F(UnoptimizedCompileJobTest, SyntaxError) {
test::ScriptResource script("^^^", strlen("^^^"));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
i_isolate(), tracer(),
test::CreateSharedFunctionInfo(i_isolate(), &script), FLAG_stack_size));
......@@ -158,23 +158,23 @@ TEST_F(CompilerDispatcherJobTest, SyntaxError) {
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread();
ASSERT_TRUE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kFailed, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kFailed, job);
ASSERT_TRUE(i_isolate()->has_pending_exception());
i_isolate()->clear_pending_exception();
job->ResetOnMainThread();
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
}
TEST_F(CompilerDispatcherJobTest, ScopeChain) {
TEST_F(UnoptimizedCompileJobTest, ScopeChain) {
const char script[] =
"function g() { var y = 1; function f(x) { return x * y }; return f; } "
"g();";
Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size));
job->StepNextOnMainThread();
......@@ -187,7 +187,7 @@ TEST_F(CompilerDispatcherJobTest, ScopeChain) {
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kReadyToCompile, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kReadyToCompile, job);
Variable* var = LookupVariableByName(job.get(), "x");
ASSERT_TRUE(var);
......@@ -198,10 +198,10 @@ TEST_F(CompilerDispatcherJobTest, ScopeChain) {
ASSERT_TRUE(var->IsContextSlot());
job->ResetOnMainThread();
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
}
TEST_F(CompilerDispatcherJobTest, CompileAndRun) {
TEST_F(UnoptimizedCompileJobTest, CompileAndRun) {
const char script[] =
"function g() {\n"
" f = function(a) {\n"
......@@ -213,7 +213,7 @@ TEST_F(CompilerDispatcherJobTest, CompileAndRun) {
"g();";
Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size));
job->StepNextOnMainThread();
......@@ -230,23 +230,23 @@ TEST_F(CompilerDispatcherJobTest, CompileAndRun) {
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kDone, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kDone, job);
Smi* value = Smi::cast(*test::RunJS(isolate(), "f(100);"));
ASSERT_TRUE(value == Smi::FromInt(160));
job->ResetOnMainThread();
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
}
TEST_F(CompilerDispatcherJobTest, CompileFailureToAnalyse) {
TEST_F(UnoptimizedCompileJobTest, CompileFailureToAnalyse) {
std::string raw_script("() { var a = ");
for (int i = 0; i < 100000; i++) {
raw_script += "'x' + ";
}
raw_script += " 'x'; }";
test::ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str()));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
i_isolate(), tracer(),
test::CreateSharedFunctionInfo(i_isolate(), &script), 100));
......@@ -258,22 +258,22 @@ TEST_F(CompilerDispatcherJobTest, CompileFailureToAnalyse) {
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread();
ASSERT_TRUE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kFailed, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kFailed, job);
ASSERT_TRUE(i_isolate()->has_pending_exception());
i_isolate()->clear_pending_exception();
job->ResetOnMainThread();
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
}
TEST_F(CompilerDispatcherJobTest, CompileFailureToFinalize) {
TEST_F(UnoptimizedCompileJobTest, CompileFailureToFinalize) {
std::string raw_script("() { var a = ");
for (int i = 0; i < 1000; i++) {
raw_script += "'x' + ";
}
raw_script += " 'x'; }";
test::ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str()));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
i_isolate(), tracer(),
test::CreateSharedFunctionInfo(i_isolate(), &script), 50));
......@@ -291,17 +291,17 @@ TEST_F(CompilerDispatcherJobTest, CompileFailureToFinalize) {
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread();
ASSERT_TRUE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kFailed, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kFailed, job);
ASSERT_TRUE(i_isolate()->has_pending_exception());
i_isolate()->clear_pending_exception();
job->ResetOnMainThread();
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
}
class CompileTask : public Task {
public:
CompileTask(CompilerDispatcherJob* job, base::Semaphore* semaphore)
CompileTask(UnoptimizedCompileJob* job, base::Semaphore* semaphore)
: job_(job), semaphore_(semaphore) {}
~CompileTask() override {}
......@@ -312,12 +312,12 @@ class CompileTask : public Task {
}
private:
CompilerDispatcherJob* job_;
UnoptimizedCompileJob* job_;
base::Semaphore* semaphore_;
DISALLOW_COPY_AND_ASSIGN(CompileTask);
};
TEST_F(CompilerDispatcherJobTest, CompileOnBackgroundThread) {
TEST_F(UnoptimizedCompileJobTest, CompileOnBackgroundThread) {
const char* raw_script =
"(a, b) {\n"
" var c = a + b;\n"
......@@ -326,7 +326,7 @@ TEST_F(CompilerDispatcherJobTest, CompileOnBackgroundThread) {
" return bar;"
"}";
test::ScriptResource script(raw_script, strlen(raw_script));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
i_isolate(), tracer(),
test::CreateSharedFunctionInfo(i_isolate(), &script), 100));
......@@ -343,19 +343,19 @@ TEST_F(CompilerDispatcherJobTest, CompileOnBackgroundThread) {
base::Semaphore semaphore(0);
CompileTask* background_task = new CompileTask(job.get(), &semaphore);
ASSERT_JOB_STATUS(CompileJobStatus::kReadyToCompile, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kReadyToCompile, job);
V8::GetCurrentPlatform()->CallOnBackgroundThread(background_task,
Platform::kShortRunningTask);
semaphore.Wait();
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kDone, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kDone, job);
job->ResetOnMainThread();
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
}
TEST_F(CompilerDispatcherJobTest, LazyInnerFunctions) {
TEST_F(UnoptimizedCompileJobTest, LazyInnerFunctions) {
const char script[] =
"function g() {\n"
" f = function() {\n"
......@@ -368,7 +368,7 @@ TEST_F(CompilerDispatcherJobTest, LazyInnerFunctions) {
Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size));
job->StepNextOnMainThread();
......@@ -385,7 +385,7 @@ TEST_F(CompilerDispatcherJobTest, LazyInnerFunctions) {
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread();
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(CompileJobStatus::kDone, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kDone, job);
Handle<JSFunction> e =
Handle<JSFunction>::cast(test::RunJS(isolate(), "f();"));
......@@ -393,7 +393,7 @@ TEST_F(CompilerDispatcherJobTest, LazyInnerFunctions) {
ASSERT_FALSE(e->shared()->HasBaselineCode());
job->ResetOnMainThread();
ASSERT_JOB_STATUS(CompileJobStatus::kInitial, job);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
}
} // namespace internal
......
......@@ -40,7 +40,7 @@ class ScriptResource : public v8::String::ExternalOneByteStringResource {
DISALLOW_COPY_AND_ASSIGN(ScriptResource);
};
class FinishCallback : public CompileJobFinishCallback {
class FinishCallback : public UnoptimizedCompileJobFinishCallback {
public:
void ParseFinished(std::unique_ptr<ParseInfo> result) override {
result_ = std::move(result);
......
......@@ -91,10 +91,10 @@
'compiler/typer-unittest.cc',
'compiler/value-numbering-reducer-unittest.cc',
'compiler/zone-stats-unittest.cc',
'compiler-dispatcher/compiler-dispatcher-job-unittest.cc',
'compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc',
'compiler-dispatcher/compiler-dispatcher-unittest.cc',
'compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc',
'compiler-dispatcher/unoptimized-compile-job-unittest.cc',
'counters-unittest.cc',
'eh-frame-iterator-unittest.cc',
'eh-frame-writer-unittest.cc',
......
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