Commit 10e628eb authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Compiler] Ensure we enter the correct context for compiler-dispatcher jobs.

When running main-thread compiler-dispatcher jobs, ensure that we enter the
correct Context. Also adds a test for compiling an extension in the compiler
dispatcher to ensure that idle tasks enter the correct context before
finalizing the compilation.

BUG=v8:5203

Review-Url: https://codereview.chromium.org/2679193004
Cr-Commit-Position: refs/heads/master@{#43111}
parent 13042c9a
...@@ -69,6 +69,8 @@ CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate, ...@@ -69,6 +69,8 @@ CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate,
: status_(CompileJobStatus::kInitial), : status_(CompileJobStatus::kInitial),
isolate_(isolate), isolate_(isolate),
tracer_(tracer), tracer_(tracer),
context_(Handle<Context>::cast(
isolate_->global_handles()->Create(isolate->context()))),
shared_(Handle<SharedFunctionInfo>::cast( shared_(Handle<SharedFunctionInfo>::cast(
isolate_->global_handles()->Create(*shared))), isolate_->global_handles()->Create(*shared))),
max_stack_size_(max_stack_size), max_stack_size_(max_stack_size),
...@@ -93,6 +95,8 @@ CompilerDispatcherJob::CompilerDispatcherJob( ...@@ -93,6 +95,8 @@ CompilerDispatcherJob::CompilerDispatcherJob(
: status_(CompileJobStatus::kAnalyzed), : status_(CompileJobStatus::kAnalyzed),
isolate_(isolate), isolate_(isolate),
tracer_(tracer), tracer_(tracer),
context_(Handle<Context>::cast(
isolate_->global_handles()->Create(isolate->context()))),
shared_(Handle<SharedFunctionInfo>::cast( shared_(Handle<SharedFunctionInfo>::cast(
isolate_->global_handles()->Create(*shared))), isolate_->global_handles()->Create(*shared))),
max_stack_size_(max_stack_size), max_stack_size_(max_stack_size),
...@@ -117,6 +121,7 @@ CompilerDispatcherJob::~CompilerDispatcherJob() { ...@@ -117,6 +121,7 @@ CompilerDispatcherJob::~CompilerDispatcherJob() {
DCHECK(status_ == CompileJobStatus::kInitial || DCHECK(status_ == CompileJobStatus::kInitial ||
status_ == CompileJobStatus::kDone); status_ == CompileJobStatus::kDone);
i::GlobalHandles::Destroy(Handle<Object>::cast(shared_).location()); i::GlobalHandles::Destroy(Handle<Object>::cast(shared_).location());
i::GlobalHandles::Destroy(Handle<Object>::cast(context_).location());
} }
bool CompilerDispatcherJob::IsAssociatedWith( bool CompilerDispatcherJob::IsAssociatedWith(
...@@ -386,11 +391,14 @@ bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() { ...@@ -386,11 +391,14 @@ bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() {
static_cast<void*>(this)); static_cast<void*>(this));
} }
if (compile_job_->state() == CompilationJob::State::kFailed || {
!Compiler::FinalizeCompilationJob(compile_job_.release())) { HandleScope scope(isolate_);
if (!isolate_->has_pending_exception()) isolate_->StackOverflow(); if (compile_job_->state() == CompilationJob::State::kFailed ||
status_ = CompileJobStatus::kFailed; !Compiler::FinalizeCompilationJob(compile_job_.release())) {
return false; if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
status_ = CompileJobStatus::kFailed;
return false;
}
} }
compile_job_.reset(); compile_job_.reset();
......
...@@ -60,6 +60,8 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob { ...@@ -60,6 +60,8 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
CompileJobStatus status() const { return status_; } CompileJobStatus status() const { return status_; }
Context* context() { return *context_; }
// Returns true if this CompilerDispatcherJob was created for the given // Returns true if this CompilerDispatcherJob was created for the given
// function. // function.
bool IsAssociatedWith(Handle<SharedFunctionInfo> shared) const; bool IsAssociatedWith(Handle<SharedFunctionInfo> shared) const;
...@@ -105,6 +107,7 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob { ...@@ -105,6 +107,7 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
CompileJobStatus status_; CompileJobStatus status_;
Isolate* isolate_; Isolate* isolate_;
CompilerDispatcherTracer* tracer_; CompilerDispatcherTracer* tracer_;
Handle<Context> context_; // Global handle.
Handle<SharedFunctionInfo> shared_; // Global handle. Handle<SharedFunctionInfo> shared_; // Global handle.
Handle<String> source_; // Global handle. Handle<String> source_; // Global handle.
Handle<String> wrapper_; // Global handle. Handle<String> wrapper_; // Global handle.
......
...@@ -24,6 +24,11 @@ enum class ExceptionHandling { kSwallow, kThrow }; ...@@ -24,6 +24,11 @@ enum class ExceptionHandling { kSwallow, kThrow };
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()));
// Ensure we are in the correct context for the job.
SaveContext save(isolate);
isolate->set_context(job->context());
switch (job->status()) { switch (job->status()) {
case CompileJobStatus::kInitial: case CompileJobStatus::kInitial:
job->PrepareToParseOnMainThread(); job->PrepareToParseOnMainThread();
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "src/compiler-dispatcher/compiler-dispatcher.h" #include "src/compiler-dispatcher/compiler-dispatcher.h"
#include "include/v8-platform.h" #include "include/v8-platform.h"
#include "src/api.h"
#include "src/base/platform/semaphore.h" #include "src/base/platform/semaphore.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h" #include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
...@@ -22,34 +23,67 @@ ...@@ -22,34 +23,67 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class CompilerDispatcherTestFlags {
public:
static void SetFlagsForTest() {
old_compiler_dispatcher_flag_ = i::FLAG_compiler_dispatcher;
i::FLAG_compiler_dispatcher = true;
old_ignition_flag_ = i::FLAG_ignition;
i::FLAG_ignition = true;
}
static void RestoreFlags() {
i::FLAG_compiler_dispatcher = old_compiler_dispatcher_flag_;
i::FLAG_ignition = old_ignition_flag_;
}
private:
static bool old_compiler_dispatcher_flag_;
static bool old_ignition_flag_;
DISALLOW_IMPLICIT_CONSTRUCTORS(CompilerDispatcherTestFlags);
};
bool CompilerDispatcherTestFlags::old_compiler_dispatcher_flag_;
bool CompilerDispatcherTestFlags::old_ignition_flag_;
class CompilerDispatcherTest : public TestWithContext { class CompilerDispatcherTest : public TestWithContext {
public: public:
CompilerDispatcherTest() = default; CompilerDispatcherTest() = default;
~CompilerDispatcherTest() override = default; ~CompilerDispatcherTest() override = default;
static void SetUpTestCase() { static void SetUpTestCase() {
old_flag_ = i::FLAG_ignition; CompilerDispatcherTestFlags::SetFlagsForTest();
i::FLAG_compiler_dispatcher = true;
old_ignition_flag_ = i::FLAG_ignition;
i::FLAG_ignition = true;
TestWithContext::SetUpTestCase(); TestWithContext::SetUpTestCase();
} }
static void TearDownTestCase() { static void TearDownTestCase() {
TestWithContext::TearDownTestCase(); TestWithContext::TearDownTestCase();
i::FLAG_compiler_dispatcher = old_flag_; CompilerDispatcherTestFlags::RestoreFlags();
i::FLAG_ignition = old_ignition_flag_;
} }
private: private:
static bool old_flag_;
static bool old_ignition_flag_;
DISALLOW_COPY_AND_ASSIGN(CompilerDispatcherTest); DISALLOW_COPY_AND_ASSIGN(CompilerDispatcherTest);
}; };
bool CompilerDispatcherTest::old_flag_; class CompilerDispatcherTestWithoutContext : public v8::TestWithIsolate {
bool CompilerDispatcherTest::old_ignition_flag_; public:
CompilerDispatcherTestWithoutContext() = default;
~CompilerDispatcherTestWithoutContext() override = default;
static void SetUpTestCase() {
CompilerDispatcherTestFlags::SetFlagsForTest();
TestWithContext::SetUpTestCase();
}
static void TearDownTestCase() {
TestWithContext::TearDownTestCase();
CompilerDispatcherTestFlags::RestoreFlags();
}
private:
DISALLOW_COPY_AND_ASSIGN(CompilerDispatcherTestWithoutContext);
};
namespace { namespace {
...@@ -939,5 +973,79 @@ TEST_F(CompilerDispatcherTest, CompileParsedOutOfScope) { ...@@ -939,5 +973,79 @@ TEST_F(CompilerDispatcherTest, CompileParsedOutOfScope) {
ASSERT_TRUE(shared->is_compiled()); ASSERT_TRUE(shared->is_compiled());
} }
namespace {
const char kExtensionSource[] = "native function Dummy();";
class MockNativeFunctionExtension : public Extension {
public:
MockNativeFunctionExtension()
: Extension("mock-extension", kExtensionSource), function_(&Dummy) {}
virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local<v8::String> name) {
return v8::FunctionTemplate::New(isolate, function_);
}
static void Dummy(const v8::FunctionCallbackInfo<v8::Value>& args) { return; }
private:
v8::FunctionCallback function_;
DISALLOW_COPY_AND_ASSIGN(MockNativeFunctionExtension);
};
} // namespace
TEST_F(CompilerDispatcherTestWithoutContext, CompileExtensionWithoutContext) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
Local<v8::Context> context = v8::Context::New(isolate());
MockNativeFunctionExtension extension;
Handle<String> script_str =
i_isolate()
->factory()
->NewStringFromUtf8(CStrVector(kExtensionSource))
.ToHandleChecked();
Handle<Script> script = i_isolate()->factory()->NewScript(script_str);
script->set_type(Script::TYPE_EXTENSION);
Handle<SharedFunctionInfo> shared;
{
v8::Context::Scope scope(context);
ParseInfo parse_info(script);
parse_info.set_extension(&extension);
ASSERT_TRUE(parsing::ParseAny(&parse_info));
Handle<FixedArray> shared_infos_array(i_isolate()->factory()->NewFixedArray(
parse_info.max_function_literal_id() + 1));
parse_info.script()->set_shared_function_infos(*shared_infos_array);
DeferredHandleScope handles_scope(i_isolate());
{ ASSERT_TRUE(Compiler::Analyze(&parse_info)); }
std::shared_ptr<DeferredHandles> compilation_handles(
handles_scope.Detach());
shared = i_isolate()->factory()->NewSharedFunctionInfoForLiteral(
parse_info.literal(), script);
parse_info.set_shared_info(shared);
ASSERT_FALSE(platform.IdleTaskPending());
ASSERT_TRUE(dispatcher.Enqueue(
shared, parse_info.literal(), parse_info.zone_shared(),
parse_info.deferred_handles(), compilation_handles));
ASSERT_TRUE(platform.IdleTaskPending());
}
// Exit the context scope before running the idle task.
// Since time doesn't progress on the MockPlatform, this is enough idle time
// to finish compiling the function.
platform.RunIdleTask(1000.0, 0.0);
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(shared->is_compiled());
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -24,6 +24,10 @@ class TestWithIsolate : public virtual ::testing::Test { ...@@ -24,6 +24,10 @@ class TestWithIsolate : public virtual ::testing::Test {
Isolate* isolate() const { return isolate_; } Isolate* isolate() const { return isolate_; }
v8::internal::Isolate* i_isolate() const {
return reinterpret_cast<v8::internal::Isolate*>(isolate());
}
static void SetUpTestCase(); static void SetUpTestCase();
static void TearDownTestCase(); static void TearDownTestCase();
...@@ -44,10 +48,6 @@ class TestWithContext : public virtual TestWithIsolate { ...@@ -44,10 +48,6 @@ class TestWithContext : public virtual TestWithIsolate {
const Local<Context>& context() const { return context_; } const Local<Context>& context() const { return context_; }
v8::internal::Isolate* i_isolate() const {
return reinterpret_cast<v8::internal::Isolate*>(isolate());
}
private: private:
Local<Context> context_; Local<Context> context_;
Context::Scope context_scope_; Context::Scope context_scope_;
......
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