[compiler-dispatcher] Enqueue jobs without SFI.

This a step towards using CompilerDispatcher in parallel
parsing.

BUG=v8:6093

Change-Id: I7c0dc0a5f5b25652a8aa98c94b1e069c1f081a5b
Reviewed-on: https://chromium-review.googlesource.com/473106
Reviewed-by: Jochen Eisinger <jochen@chromium.org>
Commit-Queue: Wiktor Garbacz <wiktorg@google.com>
Cr-Commit-Position: refs/heads/master@{#44570}
This commit is contained in:
Wiktor Garbacz 2017-04-06 15:59:07 +02:00 committed by Commit Bot
parent f956279ed6
commit 7deb682187
9 changed files with 347 additions and 192 deletions

View File

@ -68,7 +68,7 @@ CompilerDispatcherJob::CompilerDispatcherJob(
bool module, bool is_named_expression, bool calls_eval, uint32_t hash_seed, bool module, bool is_named_expression, bool calls_eval, uint32_t hash_seed,
AccountingAllocator* zone_allocator, int compiler_hints, AccountingAllocator* zone_allocator, int compiler_hints,
const AstStringConstants* ast_string_constants, const AstStringConstants* ast_string_constants,
FinishCallback* finish_callback) CompileJobFinishCallback* finish_callback)
: status_(CompileJobStatus::kReadyToParse), : status_(CompileJobStatus::kReadyToParse),
isolate_(nullptr), isolate_(nullptr),
tracer_(tracer), tracer_(tracer),

View File

@ -43,14 +43,14 @@ enum class CompileJobStatus {
kDone, kDone,
}; };
class CompileJobFinishCallback {
public:
virtual ~CompileJobFinishCallback() {}
virtual void ParseFinished(std::unique_ptr<ParseInfo> parse_info) = 0;
};
class V8_EXPORT_PRIVATE CompilerDispatcherJob { class V8_EXPORT_PRIVATE CompilerDispatcherJob {
public: public:
class FinishCallback {
public:
virtual ~FinishCallback() {}
virtual void ParseFinished(std::unique_ptr<ParseInfo> parse_info) = 0;
};
// Creates a CompilerDispatcherJob in the initial state. // Creates a CompilerDispatcherJob in the initial state.
CompilerDispatcherJob(Isolate* isolate, CompilerDispatcherTracer* tracer, CompilerDispatcherJob(Isolate* isolate, CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared, Handle<SharedFunctionInfo> shared,
@ -65,7 +65,7 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
uint32_t hash_seed, AccountingAllocator* zone_allocator, uint32_t hash_seed, AccountingAllocator* zone_allocator,
int compiler_hints, int compiler_hints,
const AstStringConstants* ast_string_constants, const AstStringConstants* ast_string_constants,
FinishCallback* finish_callback); CompileJobFinishCallback* finish_callback);
// Creates a CompilerDispatcherJob in the analyzed state. // Creates a CompilerDispatcherJob in the analyzed state.
CompilerDispatcherJob(Isolate* isolate, CompilerDispatcherTracer* tracer, CompilerDispatcherJob(Isolate* isolate, CompilerDispatcherTracer* tracer,
Handle<Script> script, Handle<Script> script,
@ -79,6 +79,7 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
CompileJobStatus status() const { return status_; } CompileJobStatus status() const { return status_; }
bool has_context() const { return !context_.is_null(); }
Context* context() { return *context_; } Context* context() { return *context_; }
Handle<SharedFunctionInfo> shared() const { return shared_; } Handle<SharedFunctionInfo> shared() const { return shared_; }
@ -135,7 +136,7 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
Handle<String> wrapper_; // Global handle. Handle<String> wrapper_; // Global handle.
std::unique_ptr<v8::String::ExternalStringResourceBase> source_wrapper_; std::unique_ptr<v8::String::ExternalStringResourceBase> source_wrapper_;
size_t max_stack_size_; size_t max_stack_size_;
FinishCallback* finish_callback_ = nullptr; CompileJobFinishCallback* finish_callback_ = nullptr;
// Members required for parsing. // Members required for parsing.
std::unique_ptr<UnicodeCache> unicode_cache_; std::unique_ptr<UnicodeCache> unicode_cache_;

View File

@ -21,6 +21,16 @@ namespace {
enum class ExceptionHandling { kSwallow, kThrow }; enum class ExceptionHandling { kSwallow, kThrow };
bool IsFinished(CompilerDispatcherJob* job) {
return job->status() == CompileJobStatus::kDone ||
job->status() == CompileJobStatus::kFailed;
}
bool CanRunOnAnyThread(CompilerDispatcherJob* job) {
return job->status() == CompileJobStatus::kReadyToParse ||
job->status() == CompileJobStatus::kReadyToCompile;
}
bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job, bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
ExceptionHandling exception_handling) { ExceptionHandling exception_handling) {
DCHECK(ThreadId::Current().Equals(isolate->thread_id())); DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
@ -29,7 +39,11 @@ bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
// Ensure we are in the correct context for the job. // Ensure we are in the correct context for the job.
SaveContext save(isolate); SaveContext save(isolate);
isolate->set_context(job->context()); if (job->has_context()) {
isolate->set_context(job->context());
} else {
DCHECK(CanRunOnAnyThread(job));
}
switch (job->status()) { switch (job->status()) {
case CompileJobStatus::kInitial: case CompileJobStatus::kInitial:
@ -74,16 +88,6 @@ bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
return job->status() != CompileJobStatus::kFailed; return job->status() != CompileJobStatus::kFailed;
} }
bool IsFinished(CompilerDispatcherJob* job) {
return job->status() == CompileJobStatus::kDone ||
job->status() == CompileJobStatus::kFailed;
}
bool CanRunOnAnyThread(CompilerDispatcherJob* job) {
return job->status() == CompileJobStatus::kReadyToParse ||
job->status() == CompileJobStatus::kReadyToCompile;
}
void DoNextStepOnBackgroundThread(CompilerDispatcherJob* job) { void DoNextStepOnBackgroundThread(CompilerDispatcherJob* job) {
DCHECK(CanRunOnAnyThread(job)); DCHECK(CanRunOnAnyThread(job));
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
@ -241,7 +245,7 @@ CompilerDispatcher::~CompilerDispatcher() {
task_manager_->CancelAndWait(); task_manager_->CancelAndWait();
} }
bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) { bool CompilerDispatcher::CanEnqueue() {
if (!IsEnabled()) return false; if (!IsEnabled()) return false;
DCHECK(FLAG_ignition); DCHECK(FLAG_ignition);
@ -255,6 +259,12 @@ bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) {
if (abort_) return false; if (abort_) return false;
} }
return true;
}
bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) {
if (!CanEnqueue()) return false;
// We only handle functions (no eval / top-level code / wasm) that are // We only handle functions (no eval / top-level code / wasm) that are
// attached to a script. // attached to a script.
if (!function->script()->IsScript() || function->is_toplevel() || if (!function->script()->IsScript() || function->is_toplevel() ||
@ -281,6 +291,31 @@ CompilerDispatcher::JobId CompilerDispatcher::Enqueue(
return it->first; return it->first;
} }
CompilerDispatcher::JobId CompilerDispatcher::EnqueueAndStep(
std::unique_ptr<CompilerDispatcherJob> job) {
DCHECK(!IsFinished(job.get()));
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;
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: stepping ");
it->second->ShortPrint();
PrintF("\n");
}
DoNextStepOnMainThread(isolate_, it->second.get(),
ExceptionHandling::kSwallow);
ConsiderJobForBackgroundProcessing(it->second.get());
RemoveIfFinished(it);
ScheduleIdleTaskIfNeeded();
return id;
}
bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) { bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherEnqueue"); "V8.CompilerDispatcherEnqueue");
@ -299,21 +334,49 @@ bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
return true; 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,
bool calls_eval, int compiler_hints,
CompileJobFinishCallback* finish_callback,
JobId* job_id) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherEnqueue");
if (!CanEnqueue()) return false;
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: enqueuing function at %d for initial parse\n",
start_position);
}
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
tracer_.get(), max_stack_size_, source, start_position, end_position,
language_mode, function_literal_id, native, module, is_named_expression,
calls_eval, isolate_->heap()->HashSeed(), isolate_->allocator(),
compiler_hints, isolate_->ast_string_constants(), finish_callback));
JobId id = Enqueue(std::move(job));
if (job_id != nullptr) {
*job_id = id;
}
return true;
}
bool CompilerDispatcher::EnqueueAndStep(Handle<SharedFunctionInfo> function) { bool CompilerDispatcher::EnqueueAndStep(Handle<SharedFunctionInfo> function) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherEnqueueAndStep"); "V8.CompilerDispatcherEnqueueAndStep");
if (!CanEnqueue(function)) return false;
if (IsEnqueued(function)) return true; if (IsEnqueued(function)) return true;
if (!Enqueue(function)) return false;
if (trace_compiler_dispatcher_) { if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: stepping "); PrintF("CompilerDispatcher: enqueuing ");
function->ShortPrint(); function->ShortPrint();
PrintF("\n"); PrintF(" for parse and compile\n");
} }
JobMap::const_iterator job = GetJobFor(function);
DoNextStepOnMainThread(isolate_, job->second.get(), std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
ExceptionHandling::kSwallow); isolate_, tracer_.get(), function, max_stack_size_));
ConsiderJobForBackgroundProcessing(job->second.get()); EnqueueAndStep(std::move(job));
return true; return true;
} }
@ -347,21 +410,19 @@ bool CompilerDispatcher::EnqueueAndStep(
std::shared_ptr<DeferredHandles> compile_handles) { std::shared_ptr<DeferredHandles> compile_handles) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherEnqueueAndStep"); "V8.CompilerDispatcherEnqueueAndStep");
if (!CanEnqueue(function)) return false;
if (IsEnqueued(function)) return true; if (IsEnqueued(function)) return true;
if (!Enqueue(script, function, literal, parse_zone, parse_handles,
compile_handles)) {
return false;
}
if (trace_compiler_dispatcher_) { if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: stepping "); PrintF("CompilerDispatcher: enqueuing ");
function->ShortPrint(); function->ShortPrint();
PrintF("\n"); PrintF(" for compile\n");
} }
JobMap::const_iterator job = GetJobFor(function);
DoNextStepOnMainThread(isolate_, job->second.get(), std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
ExceptionHandling::kSwallow); isolate_, tracer_.get(), script, function, literal, parse_zone,
ConsiderJobForBackgroundProcessing(job->second.get()); parse_handles, compile_handles, max_stack_size_));
EnqueueAndStep(std::move(job));
return true; return true;
} }
@ -411,23 +472,7 @@ bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
ExceptionHandling::kThrow); ExceptionHandling::kThrow);
} }
bool result = job->second->status() != CompileJobStatus::kFailed; bool result = job->second->status() != CompileJobStatus::kFailed;
RemoveIfFinished(job);
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: finished working on ");
function->ShortPrint();
PrintF(": %s\n", result ? "success" : "failure");
tracer_->DumpStatistics();
}
job->second->ResetOnMainThread();
if (!job->second->shared().is_null()) {
shared_to_job_id_.Delete(job->second->shared());
}
jobs_.erase(job);
if (jobs_.empty()) {
base::LockGuard<base::Mutex> lock(&mutex_);
if (num_background_tasks_ == 0) abort_ = false;
}
return result; return result;
} }
@ -475,7 +520,7 @@ void CompilerDispatcher::AbortInactiveJobs() {
// here with nothing left to do. // here with nothing left to do.
if (!abort_) return; if (!abort_) return;
} }
for (auto it = jobs_.begin(); it != jobs_.end();) { for (auto it = jobs_.cbegin(); it != jobs_.cend();) {
auto job = it; auto job = it;
++it; ++it;
{ {
@ -490,11 +535,7 @@ void CompilerDispatcher::AbortInactiveJobs() {
job->second->ShortPrint(); job->second->ShortPrint();
PrintF("\n"); PrintF("\n");
} }
job->second->ResetOnMainThread(); it = RemoveJob(job);
if (!job->second->shared().is_null()) {
shared_to_job_id_.Delete(job->second->shared());
}
jobs_.erase(job);
} }
if (jobs_.empty()) { if (jobs_.empty()) {
base::LockGuard<base::Mutex> lock(&mutex_); base::LockGuard<base::Mutex> lock(&mutex_);
@ -676,8 +717,8 @@ void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) {
idle_time_in_seconds * idle_time_in_seconds *
static_cast<double>(base::Time::kMillisecondsPerSecond)); static_cast<double>(base::Time::kMillisecondsPerSecond));
} }
for (auto job = jobs_.begin(); for (auto job = jobs_.cbegin();
job != jobs_.end() && idle_time_in_seconds > 0.0; job != jobs_.cend() && idle_time_in_seconds > 0.0;
idle_time_in_seconds = idle_time_in_seconds =
deadline_in_seconds - platform_->MonotonicallyIncreasingTime()) { deadline_in_seconds - platform_->MonotonicallyIncreasingTime()) {
// Don't work on jobs that are being worked on by background tasks. // Don't work on jobs that are being worked on by background tasks.
@ -706,19 +747,8 @@ void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) {
++job; ++job;
} else if (IsFinished(job->second.get())) { } else if (IsFinished(job->second.get())) {
DCHECK(it == pending_background_jobs_.end()); DCHECK(it == pending_background_jobs_.end());
if (trace_compiler_dispatcher_) { lock.reset();
PrintF("CompilerDispatcher: finished working on "); job = RemoveJob(job);
job->second->ShortPrint();
PrintF(": %s\n", job->second->status() == CompileJobStatus::kDone
? "success"
: "failure");
tracer_->DumpStatistics();
}
job->second->ResetOnMainThread();
if (!job->second->shared().is_null()) {
shared_to_job_id_.Delete(job->second->shared());
}
job = jobs_.erase(job);
continue; continue;
} else { } else {
// Do one step, and keep processing the job (as we don't advance the // Do one step, and keep processing the job (as we don't advance the
@ -734,5 +764,36 @@ void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) {
if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded(); if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded();
} }
CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::RemoveIfFinished(
JobMap::const_iterator job) {
if (!IsFinished(job->second.get())) {
return job;
}
if (trace_compiler_dispatcher_) {
bool result = job->second->status() != CompileJobStatus::kFailed;
PrintF("CompilerDispatcher: finished working on ");
job->second->ShortPrint();
PrintF(": %s\n", result ? "success" : "failure");
tracer_->DumpStatistics();
}
return RemoveJob(job);
}
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());
}
job = jobs_.erase(job);
if (jobs_.empty()) {
base::LockGuard<base::Mutex> lock(&mutex_);
if (num_background_tasks_ == 0) abort_ = false;
}
return job;
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -28,6 +28,7 @@ enum class MemoryPressureLevel;
namespace internal { namespace internal {
class CancelableTaskManager; class CancelableTaskManager;
class CompileJobFinishCallback;
class CompilerDispatcherJob; class CompilerDispatcherJob;
class CompilerDispatcherTracer; class CompilerDispatcherTracer;
class DeferredHandles; class DeferredHandles;
@ -81,6 +82,13 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
// Enqueue a job for parse and compile. Returns true if a job was enqueued. // Enqueue a job for parse and compile. Returns true if a job was enqueued.
bool Enqueue(Handle<SharedFunctionInfo> function); bool Enqueue(Handle<SharedFunctionInfo> function);
// Enqueue a job for initial parse. Returns true if a job was enqueued.
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, bool calls_eval,
int compiler_hints, CompileJobFinishCallback* finish_callback,
JobId* job_id);
// Like Enqueue, but also advances the job so that it can potentially // Like Enqueue, but also advances the job so that it can potentially
// continue running on a background thread (if at all possible). Returns // continue running on a background thread (if at all possible). Returns
// true if the job was enqueued. // true if the job was enqueued.
@ -122,7 +130,9 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
private: private:
FRIEND_TEST(CompilerDispatcherTest, EnqueueJob); FRIEND_TEST(CompilerDispatcherTest, EnqueueJob);
FRIEND_TEST(CompilerDispatcherTest, EnqueueWithoutSFI);
FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStep); FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStep);
FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStepWithoutSFI);
FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStepTwice); FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStepTwice);
FRIEND_TEST(CompilerDispatcherTest, EnqueueParsed); FRIEND_TEST(CompilerDispatcherTest, EnqueueParsed);
FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStepParsed); FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStepParsed);
@ -142,6 +152,7 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
void WaitForJobIfRunningOnBackground(CompilerDispatcherJob* job); void WaitForJobIfRunningOnBackground(CompilerDispatcherJob* job);
void AbortInactiveJobs(); void AbortInactiveJobs();
bool CanEnqueue();
bool CanEnqueue(Handle<SharedFunctionInfo> function); bool CanEnqueue(Handle<SharedFunctionInfo> function);
JobMap::const_iterator GetJobFor(Handle<SharedFunctionInfo> shared) const; JobMap::const_iterator GetJobFor(Handle<SharedFunctionInfo> shared) const;
void ConsiderJobForBackgroundProcessing(CompilerDispatcherJob* job); void ConsiderJobForBackgroundProcessing(CompilerDispatcherJob* job);
@ -152,6 +163,11 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
void DoBackgroundWork(); void DoBackgroundWork();
void DoIdleWork(double deadline_in_seconds); void DoIdleWork(double deadline_in_seconds);
JobId Enqueue(std::unique_ptr<CompilerDispatcherJob> job); JobId Enqueue(std::unique_ptr<CompilerDispatcherJob> job);
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 following the removed job.
JobMap::const_iterator RemoveJob(JobMap::const_iterator job);
Isolate* isolate_; Isolate* isolate_;
Platform* platform_; Platform* platform_;

View File

@ -4,14 +4,16 @@
#include "test/unittests/compiler-dispatcher/compiler-dispatcher-helper.h" #include "test/unittests/compiler-dispatcher/compiler-dispatcher-helper.h"
#include <memory>
#include "include/v8.h" #include "include/v8.h"
#include "src/api.h" #include "src/api.h"
#include "src/handles.h"
#include "src/isolate.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
#include "src/objects.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace test {
Handle<Object> RunJS(v8::Isolate* isolate, const char* script) { Handle<Object> RunJS(v8::Isolate* isolate, const char* script) {
return Utils::OpenHandle( return Utils::OpenHandle(
@ -24,5 +26,35 @@ Handle<Object> RunJS(v8::Isolate* isolate, const char* script) {
.ToLocalChecked()); .ToLocalChecked());
} }
Handle<String> CreateSource(Isolate* isolate,
ExternalOneByteString::Resource* maybe_resource) {
static const char test_script[] = "(x) { x*x; }";
if (maybe_resource) {
return isolate->factory()
->NewExternalStringFromOneByte(maybe_resource)
.ToHandleChecked();
}
return isolate->factory()->NewStringFromAsciiChecked(test_script);
}
Handle<SharedFunctionInfo> CreateSharedFunctionInfo(
Isolate* isolate,
v8::String::ExternalOneByteStringResource* maybe_resource) {
HandleScope scope(isolate);
Handle<String> source = CreateSource(isolate, maybe_resource);
Handle<Script> script = isolate->factory()->NewScript(source);
Handle<FixedArray> infos = isolate->factory()->NewFixedArray(3);
script->set_shared_function_infos(*infos);
Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
isolate->factory()->NewStringFromAsciiChecked("f"),
isolate->builtins()->CompileLazy(), false);
shared->set_end_position(source->length());
shared->set_outer_scope_info(ScopeInfo::Empty(isolate));
shared->set_function_literal_id(1);
SharedFunctionInfo::SetScript(shared, script);
return scope.CloseAndEscape(shared);
}
} // namespace test
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -5,6 +5,12 @@
#ifndef V8_UNITTESTS_COMPILER_DISPATCHER_COMPILER_DISPATCHER_HELPER_H_ #ifndef V8_UNITTESTS_COMPILER_DISPATCHER_COMPILER_DISPATCHER_HELPER_H_
#define V8_UNITTESTS_COMPILER_DISPATCHER_COMPILER_DISPATCHER_HELPER_H_ #define V8_UNITTESTS_COMPILER_DISPATCHER_COMPILER_DISPATCHER_HELPER_H_
#include <memory>
#include "include/v8.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/parsing/parse-info.h"
namespace v8 { namespace v8 {
class Isolate; class Isolate;
@ -14,9 +20,46 @@ namespace internal {
class Object; class Object;
template <typename T> template <typename T>
class Handle; class Handle;
class Isolate;
namespace test {
class ScriptResource : public v8::String::ExternalOneByteStringResource {
public:
ScriptResource(const char* data, size_t length)
: data_(data), length_(length) {}
~ScriptResource() override = default;
const char* data() const override { return data_; }
size_t length() const override { return length_; }
private:
const char* data_;
size_t length_;
DISALLOW_COPY_AND_ASSIGN(ScriptResource);
};
class FinishCallback : public CompileJobFinishCallback {
public:
void ParseFinished(std::unique_ptr<ParseInfo> result) override {
result_ = std::move(result);
}
ParseInfo* result() const { return result_.get(); }
private:
std::unique_ptr<ParseInfo> result_;
};
Handle<Object> RunJS(v8::Isolate* isolate, const char* script); Handle<Object> RunJS(v8::Isolate* isolate, const char* script);
Handle<String> CreateSource(
Isolate* isolate,
v8::String::ExternalOneByteStringResource* maybe_resource);
Handle<SharedFunctionInfo> CreateSharedFunctionInfo(
Isolate* isolate,
v8::String::ExternalOneByteStringResource* maybe_resource);
} // namespace test
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -56,74 +56,21 @@ namespace {
const char test_script[] = "(x) { x*x; }"; const char test_script[] = "(x) { x*x; }";
class ScriptResource : public v8::String::ExternalOneByteStringResource {
public:
ScriptResource(const char* data, size_t length)
: data_(data), length_(length) {}
~ScriptResource() override = default;
const char* data() const override { return data_; }
size_t length() const override { return length_; }
private:
const char* data_;
size_t length_;
DISALLOW_COPY_AND_ASSIGN(ScriptResource);
};
Handle<String> CreateSource(Isolate* isolate,
ExternalOneByteString::Resource* maybe_resource) {
if (maybe_resource) {
return isolate->factory()
->NewExternalStringFromOneByte(maybe_resource)
.ToHandleChecked();
}
return isolate->factory()->NewStringFromAsciiChecked(test_script);
}
Handle<SharedFunctionInfo> CreateSharedFunctionInfo(
Isolate* isolate, ExternalOneByteString::Resource* maybe_resource) {
HandleScope scope(isolate);
Handle<String> source = CreateSource(isolate, maybe_resource);
Handle<Script> script = isolate->factory()->NewScript(source);
Handle<FixedArray> infos = isolate->factory()->NewFixedArray(3);
script->set_shared_function_infos(*infos);
Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
isolate->factory()->NewStringFromAsciiChecked("f"),
isolate->builtins()->CompileLazy(), false);
shared->set_end_position(source->length());
shared->set_outer_scope_info(ScopeInfo::Empty(isolate));
shared->set_function_literal_id(1);
SharedFunctionInfo::SetScript(shared, script);
return scope.CloseAndEscape(shared);
}
class FinishCallback : public CompilerDispatcherJob::FinishCallback {
public:
void ParseFinished(std::unique_ptr<ParseInfo> result) override {
result_ = std::move(result);
}
ParseInfo* result() const { return result_.get(); }
private:
std::unique_ptr<ParseInfo> result_;
};
} // namespace } // namespace
TEST_F(CompilerDispatcherJobTest, Construct) { TEST_F(CompilerDispatcherJobTest, Construct) {
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), nullptr), i_isolate(), tracer(),
FLAG_stack_size)); test::CreateSharedFunctionInfo(i_isolate(), nullptr), FLAG_stack_size));
} }
TEST_F(CompilerDispatcherJobTest, ConstructWithoutSFI) { TEST_F(CompilerDispatcherJobTest, ConstructWithoutSFI) {
std::unique_ptr<FinishCallback> callback(new FinishCallback()); std::unique_ptr<test::FinishCallback> callback(new test::FinishCallback());
std::unique_ptr<ScriptResource> resource( std::unique_ptr<test::ScriptResource> resource(
new ScriptResource(test_script, strlen(test_script))); new test::ScriptResource(test_script, strlen(test_script)));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
tracer(), FLAG_stack_size, CreateSource(i_isolate(), resource.get()), 0, tracer(), FLAG_stack_size,
test::CreateSource(i_isolate(), resource.get()), 0,
static_cast<int>(resource->length()), SLOPPY, 1, false, false, false, static_cast<int>(resource->length()), SLOPPY, 1, false, false, false,
false, i_isolate()->heap()->HashSeed(), i_isolate()->allocator(), false, i_isolate()->heap()->HashSeed(), i_isolate()->allocator(),
ScriptCompiler::kNoCompileOptions, i_isolate()->ast_string_constants(), ScriptCompiler::kNoCompileOptions, i_isolate()->ast_string_constants(),
@ -132,8 +79,8 @@ TEST_F(CompilerDispatcherJobTest, ConstructWithoutSFI) {
TEST_F(CompilerDispatcherJobTest, StateTransitions) { TEST_F(CompilerDispatcherJobTest, StateTransitions) {
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), nullptr), i_isolate(), tracer(),
FLAG_stack_size)); test::CreateSharedFunctionInfo(i_isolate(), nullptr), FLAG_stack_size));
ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); ASSERT_TRUE(job->status() == CompileJobStatus::kInitial);
job->PrepareToParseOnMainThread(); job->PrepareToParseOnMainThread();
@ -155,11 +102,12 @@ TEST_F(CompilerDispatcherJobTest, StateTransitions) {
} }
TEST_F(CompilerDispatcherJobTest, StateTransitionsParseWithCallback) { TEST_F(CompilerDispatcherJobTest, StateTransitionsParseWithCallback) {
std::unique_ptr<FinishCallback> callback(new FinishCallback()); std::unique_ptr<test::FinishCallback> callback(new test::FinishCallback());
std::unique_ptr<ScriptResource> resource( std::unique_ptr<test::ScriptResource> resource(
new ScriptResource(test_script, strlen(test_script))); new test::ScriptResource(test_script, strlen(test_script)));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
tracer(), FLAG_stack_size, CreateSource(i_isolate(), resource.get()), 0, tracer(), FLAG_stack_size,
test::CreateSource(i_isolate(), resource.get()), 0,
static_cast<int>(resource->length()), SLOPPY, 1, false, false, false, static_cast<int>(resource->length()), SLOPPY, 1, false, false, false,
false, i_isolate()->heap()->HashSeed(), i_isolate()->allocator(), false, i_isolate()->heap()->HashSeed(), i_isolate()->allocator(),
ScriptCompiler::kNoCompileOptions, i_isolate()->ast_string_constants(), ScriptCompiler::kNoCompileOptions, i_isolate()->ast_string_constants(),
@ -173,10 +121,10 @@ TEST_F(CompilerDispatcherJobTest, StateTransitionsParseWithCallback) {
} }
TEST_F(CompilerDispatcherJobTest, SyntaxError) { TEST_F(CompilerDispatcherJobTest, SyntaxError) {
ScriptResource script("^^^", strlen("^^^")); test::ScriptResource script("^^^", strlen("^^^"));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), &script), i_isolate(), tracer(),
FLAG_stack_size)); test::CreateSharedFunctionInfo(i_isolate(), &script), FLAG_stack_size));
job->PrepareToParseOnMainThread(); job->PrepareToParseOnMainThread();
job->Parse(); job->Parse();
@ -194,7 +142,8 @@ TEST_F(CompilerDispatcherJobTest, ScopeChain) {
const char script[] = const char script[] =
"function g() { var y = 1; function f(x) { return x * y }; return f; } " "function g() { var y = 1; function f(x) { return x * y }; return f; } "
"g();"; "g();";
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size)); i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size));
@ -232,7 +181,8 @@ TEST_F(CompilerDispatcherJobTest, CompileAndRun) {
" return f;\n" " return f;\n"
"}\n" "}\n"
"g();"; "g();";
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size)); i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size));
@ -245,7 +195,7 @@ TEST_F(CompilerDispatcherJobTest, CompileAndRun) {
ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); ASSERT_TRUE(job->FinalizeCompilingOnMainThread());
ASSERT_TRUE(job->status() == CompileJobStatus::kDone); ASSERT_TRUE(job->status() == CompileJobStatus::kDone);
Smi* value = Smi::cast(*RunJS(isolate(), "f(100);")); Smi* value = Smi::cast(*test::RunJS(isolate(), "f(100);"));
ASSERT_TRUE(value == Smi::FromInt(160)); ASSERT_TRUE(value == Smi::FromInt(160));
job->ResetOnMainThread(); job->ResetOnMainThread();
@ -258,10 +208,10 @@ TEST_F(CompilerDispatcherJobTest, CompileFailureToAnalyse) {
raw_script += "'x' + "; raw_script += "'x' + ";
} }
raw_script += " 'x'; }"; raw_script += " 'x'; }";
ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str())); test::ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str()));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), &script), i_isolate(), tracer(),
100)); test::CreateSharedFunctionInfo(i_isolate(), &script), 100));
job->PrepareToParseOnMainThread(); job->PrepareToParseOnMainThread();
job->Parse(); job->Parse();
@ -281,10 +231,10 @@ TEST_F(CompilerDispatcherJobTest, CompileFailureToFinalize) {
raw_script += "'x' + "; raw_script += "'x' + ";
} }
raw_script += " 'x'; }"; raw_script += " 'x'; }";
ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str())); test::ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str()));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), &script), i_isolate(), tracer(),
50)); test::CreateSharedFunctionInfo(i_isolate(), &script), 50));
job->PrepareToParseOnMainThread(); job->PrepareToParseOnMainThread();
job->Parse(); job->Parse();
@ -326,10 +276,10 @@ TEST_F(CompilerDispatcherJobTest, CompileOnBackgroundThread) {
" var d = { foo: 100, bar : bar() }\n" " var d = { foo: 100, bar : bar() }\n"
" return bar;" " return bar;"
"}"; "}";
ScriptResource script(raw_script, strlen(raw_script)); test::ScriptResource script(raw_script, strlen(raw_script));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), &script), i_isolate(), tracer(),
100)); test::CreateSharedFunctionInfo(i_isolate(), &script), 100));
job->PrepareToParseOnMainThread(); job->PrepareToParseOnMainThread();
job->Parse(); job->Parse();
@ -359,7 +309,8 @@ TEST_F(CompilerDispatcherJobTest, LazyInnerFunctions) {
" return f;\n" " return f;\n"
"}\n" "}\n"
"g();"; "g();";
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size)); i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size));
@ -373,7 +324,8 @@ TEST_F(CompilerDispatcherJobTest, LazyInnerFunctions) {
ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); ASSERT_TRUE(job->FinalizeCompilingOnMainThread());
ASSERT_TRUE(job->status() == CompileJobStatus::kDone); ASSERT_TRUE(job->status() == CompileJobStatus::kDone);
Handle<JSFunction> e = Handle<JSFunction>::cast(RunJS(isolate(), "f();")); Handle<JSFunction> e =
Handle<JSFunction>::cast(test::RunJS(isolate(), "f();"));
ASSERT_FALSE(e->shared()->HasBaselineCode()); ASSERT_FALSE(e->shared()->HasBaselineCode());

View File

@ -270,6 +270,8 @@ class MockPlatform : public v8::Platform {
DISALLOW_COPY_AND_ASSIGN(MockPlatform); DISALLOW_COPY_AND_ASSIGN(MockPlatform);
}; };
const char test_script[] = "(x) { x*x; }";
} // namespace } // namespace
TEST_F(CompilerDispatcherTest, Construct) { TEST_F(CompilerDispatcherTest, Construct) {
@ -282,7 +284,8 @@ TEST_F(CompilerDispatcherTest, IsEnqueued) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(dispatcher.IsEnqueued(shared)); ASSERT_FALSE(dispatcher.IsEnqueued(shared));
@ -299,7 +302,8 @@ TEST_F(CompilerDispatcherTest, FinishNow) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(shared->is_compiled()); ASSERT_FALSE(shared->is_compiled());
@ -317,7 +321,8 @@ TEST_F(CompilerDispatcherTest, IdleTask) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -337,7 +342,8 @@ TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -381,7 +387,7 @@ TEST_F(CompilerDispatcherTest, IdleTaskException) {
} }
script += " 'x'; }; return " + func_name + "; } g();"; script += " 'x'; }; return " + func_name + "; } g();";
Handle<JSFunction> f = Handle<JSFunction> f =
Handle<JSFunction>::cast(RunJS(isolate(), script.c_str())); Handle<JSFunction>::cast(test::RunJS(isolate(), script.c_str()));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -402,7 +408,8 @@ TEST_F(CompilerDispatcherTest, CompileOnBackgroundThread) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -445,7 +452,8 @@ TEST_F(CompilerDispatcherTest, FinishNowWithBackgroundTask) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -484,11 +492,13 @@ TEST_F(CompilerDispatcherTest, IdleTaskMultipleJobs) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script1[] = TEST_SCRIPT(); const char script1[] = TEST_SCRIPT();
Handle<JSFunction> f1 = Handle<JSFunction>::cast(RunJS(isolate(), script1)); Handle<JSFunction> f1 =
Handle<JSFunction>::cast(test::RunJS(isolate(), script1));
Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate()); Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate());
const char script2[] = TEST_SCRIPT(); const char script2[] = TEST_SCRIPT();
Handle<JSFunction> f2 = Handle<JSFunction>::cast(RunJS(isolate(), script2)); Handle<JSFunction> f2 =
Handle<JSFunction>::cast(test::RunJS(isolate(), script2));
Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate()); Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -517,7 +527,7 @@ TEST_F(CompilerDispatcherTest, FinishNowException) {
} }
script += " 'x'; }; return " + func_name + "; } g();"; script += " 'x'; }; return " + func_name + "; } g();";
Handle<JSFunction> f = Handle<JSFunction> f =
Handle<JSFunction>::cast(RunJS(isolate(), script.c_str())); Handle<JSFunction>::cast(test::RunJS(isolate(), script.c_str()));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -539,7 +549,8 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingBackgroundTask) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -581,11 +592,13 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllRunningBackgroundTask) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script1[] = TEST_SCRIPT(); const char script1[] = TEST_SCRIPT();
Handle<JSFunction> f1 = Handle<JSFunction>::cast(RunJS(isolate(), script1)); Handle<JSFunction> f1 =
Handle<JSFunction>::cast(test::RunJS(isolate(), script1));
Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate()); Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate());
const char script2[] = TEST_SCRIPT(); const char script2[] = TEST_SCRIPT();
Handle<JSFunction> f2 = Handle<JSFunction>::cast(RunJS(isolate(), script2)); Handle<JSFunction> f2 =
Handle<JSFunction>::cast(test::RunJS(isolate(), script2));
Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate()); Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -661,7 +674,8 @@ TEST_F(CompilerDispatcherTest, FinishNowDuringAbortAll) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());
@ -739,7 +753,8 @@ TEST_F(CompilerDispatcherTest, MemoryPressure) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
// Can't enqueue tasks under memory pressure. // Can't enqueue tasks under memory pressure.
@ -786,7 +801,8 @@ TEST_F(CompilerDispatcherTest, MemoryPressureFromBackground) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_TRUE(dispatcher.Enqueue(shared)); ASSERT_TRUE(dispatcher.Enqueue(shared));
@ -817,7 +833,8 @@ TEST_F(CompilerDispatcherTest, EnqueueJob) {
MockPlatform platform; MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
std::unique_ptr<CompilerDispatcherJob> job( std::unique_ptr<CompilerDispatcherJob> job(
new CompilerDispatcherJob(i_isolate(), dispatcher.tracer_.get(), shared, new CompilerDispatcherJob(i_isolate(), dispatcher.tracer_.get(), shared,
@ -831,12 +848,38 @@ TEST_F(CompilerDispatcherTest, EnqueueJob) {
ASSERT_FALSE(platform.BackgroundTasksPending()); ASSERT_FALSE(platform.BackgroundTasksPending());
} }
TEST_F(CompilerDispatcherTest, EnqueueWithoutSFI) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
ASSERT_TRUE(dispatcher.jobs_.empty());
ASSERT_TRUE(dispatcher.shared_to_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)));
ASSERT_TRUE(callback->result() == nullptr);
ASSERT_TRUE(dispatcher.Enqueue(CreateSource(i_isolate(), resource.get()), 0,
static_cast<int>(resource->length()), SLOPPY,
1, false, false, false, false, 0,
callback.get(), nullptr));
ASSERT_TRUE(!dispatcher.jobs_.empty());
ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() ==
CompileJobStatus::kReadyToParse);
ASSERT_TRUE(dispatcher.shared_to_job_id_.empty());
ASSERT_TRUE(callback->result() == nullptr);
ASSERT_TRUE(platform.IdleTaskPending());
platform.ClearIdleTask();
ASSERT_TRUE(platform.BackgroundTasksPending());
platform.ClearBackgroundTasks();
}
TEST_F(CompilerDispatcherTest, EnqueueAndStep) { TEST_F(CompilerDispatcherTest, EnqueueAndStep) {
MockPlatform platform; MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] = TEST_SCRIPT(); const char script[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(dispatcher.IsEnqueued(shared)); ASSERT_FALSE(dispatcher.IsEnqueued(shared));
@ -857,7 +900,8 @@ TEST_F(CompilerDispatcherTest, EnqueueParsed) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char source[] = TEST_SCRIPT(); const char source[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), source));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
Handle<Script> script(Script::cast(shared->script()), i_isolate()); Handle<Script> script(Script::cast(shared->script()), i_isolate());
@ -883,7 +927,8 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStepParsed) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char source[] = TEST_SCRIPT(); const char source[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), source));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
Handle<Script> script(Script::cast(shared->script()), i_isolate()); Handle<Script> script(Script::cast(shared->script()), i_isolate());
@ -911,7 +956,8 @@ TEST_F(CompilerDispatcherTest, CompileParsedOutOfScope) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char source[] = TEST_SCRIPT(); const char source[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), source));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
Handle<Script> script(Script::cast(shared->script()), i_isolate()); Handle<Script> script(Script::cast(shared->script()), i_isolate());
@ -1023,7 +1069,8 @@ TEST_F(CompilerDispatcherTest, CompileLazyFinishesDispatcherJob) {
CompilerDispatcher* dispatcher = i_isolate()->compiler_dispatcher(); CompilerDispatcher* dispatcher = i_isolate()->compiler_dispatcher();
const char source[] = TEST_SCRIPT(); const char source[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), source));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
ASSERT_FALSE(shared->is_compiled()); ASSERT_FALSE(shared->is_compiled());
@ -1033,7 +1080,7 @@ TEST_F(CompilerDispatcherTest, CompileLazyFinishesDispatcherJob) {
// Now force the function to run and ensure CompileLazy finished and dequeues // Now force the function to run and ensure CompileLazy finished and dequeues
// it from the dispatcher. // it from the dispatcher.
RunJS(isolate(), "g()();"); test::RunJS(isolate(), "g()();");
ASSERT_TRUE(shared->is_compiled()); ASSERT_TRUE(shared->is_compiled());
ASSERT_FALSE(dispatcher->IsEnqueued(shared)); ASSERT_FALSE(dispatcher->IsEnqueued(shared));
} }
@ -1045,20 +1092,20 @@ TEST_F(CompilerDispatcherTest, CompileLazy2FinishesDispatcherJob) {
const char source2[] = "function lazy2() { return 42; }; lazy2;"; const char source2[] = "function lazy2() { return 42; }; lazy2;";
Handle<JSFunction> lazy2 = Handle<JSFunction> lazy2 =
Handle<JSFunction>::cast(RunJS(isolate(), source2)); Handle<JSFunction>::cast(test::RunJS(isolate(), source2));
Handle<SharedFunctionInfo> shared2(lazy2->shared(), i_isolate()); Handle<SharedFunctionInfo> shared2(lazy2->shared(), i_isolate());
ASSERT_FALSE(shared2->is_compiled()); ASSERT_FALSE(shared2->is_compiled());
const char source1[] = "function lazy1() { return lazy2(); }; lazy1;"; const char source1[] = "function lazy1() { return lazy2(); }; lazy1;";
Handle<JSFunction> lazy1 = Handle<JSFunction> lazy1 =
Handle<JSFunction>::cast(RunJS(isolate(), source1)); Handle<JSFunction>::cast(test::RunJS(isolate(), source1));
Handle<SharedFunctionInfo> shared1(lazy1->shared(), i_isolate()); Handle<SharedFunctionInfo> shared1(lazy1->shared(), i_isolate());
ASSERT_FALSE(shared1->is_compiled()); ASSERT_FALSE(shared1->is_compiled());
ASSERT_TRUE(dispatcher->Enqueue(shared1)); ASSERT_TRUE(dispatcher->Enqueue(shared1));
ASSERT_TRUE(dispatcher->Enqueue(shared2)); ASSERT_TRUE(dispatcher->Enqueue(shared2));
RunJS(isolate(), "lazy1();"); test::RunJS(isolate(), "lazy1();");
ASSERT_TRUE(shared1->is_compiled()); ASSERT_TRUE(shared1->is_compiled());
ASSERT_TRUE(shared2->is_compiled()); ASSERT_TRUE(shared2->is_compiled());
ASSERT_FALSE(dispatcher->IsEnqueued(shared1)); ASSERT_FALSE(dispatcher->IsEnqueued(shared1));
@ -1070,7 +1117,8 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStepTwice) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char source[] = TEST_SCRIPT(); const char source[] = TEST_SCRIPT();
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); Handle<JSFunction> f =
Handle<JSFunction>::cast(test::RunJS(isolate(), source));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
Handle<Script> script(Script::cast(shared->script()), i_isolate()); Handle<Script> script(Script::cast(shared->script()), i_isolate());
@ -1110,10 +1158,12 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script1[] = TEST_SCRIPT(); const char script1[] = TEST_SCRIPT();
Handle<JSFunction> f1 = Handle<JSFunction>::cast(RunJS(isolate(), script1)); Handle<JSFunction> f1 =
Handle<JSFunction>::cast(test::RunJS(isolate(), script1));
Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate()); Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate());
const char script2[] = TEST_SCRIPT(); const char script2[] = TEST_SCRIPT();
Handle<JSFunction> f2 = Handle<JSFunction>::cast(RunJS(isolate(), script2)); Handle<JSFunction> f2 =
Handle<JSFunction>::cast(test::RunJS(isolate(), script2));
Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate()); Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate());
ASSERT_FALSE(platform.IdleTaskPending()); ASSERT_FALSE(platform.IdleTaskPending());

View File

@ -71,8 +71,8 @@ TEST_F(OptimizingCompileDispatcherTest, Construct) {
} }
TEST_F(OptimizingCompileDispatcherTest, NonBlockingFlush) { TEST_F(OptimizingCompileDispatcherTest, NonBlockingFlush) {
Handle<JSFunction> fun = Handle<JSFunction>::cast( Handle<JSFunction> fun = Handle<JSFunction>::cast(test::RunJS(
RunJS(isolate(), "function f() { function g() {}; return g;}; f();")); isolate(), "function f() { function g() {}; return g;}; f();"));
BlockingCompilationJob* job = new BlockingCompilationJob(i_isolate(), fun); BlockingCompilationJob* job = new BlockingCompilationJob(i_isolate(), fun);
OptimizingCompileDispatcher dispatcher(i_isolate()); OptimizingCompileDispatcher dispatcher(i_isolate());