Commit edd65cc4 authored by jochen's avatar jochen Committed by Commit bot

Teach compiler jobs how to actually parse

BUG=v8:5215
R=marja@chromium.org,vogelheim@chromium.org

Review-Url: https://codereview.chromium.org/2190333002
Cr-Commit-Position: refs/heads/master@{#38170}
parent 6215644c
...@@ -52,7 +52,7 @@ class AtomicValue { ...@@ -52,7 +52,7 @@ class AtomicValue {
explicit AtomicValue(T initial) explicit AtomicValue(T initial)
: value_(cast_helper<T>::to_storage_type(initial)) {} : value_(cast_helper<T>::to_storage_type(initial)) {}
V8_INLINE T Value() { V8_INLINE T Value() const {
return cast_helper<T>::to_return_type(base::Acquire_Load(&value_)); return cast_helper<T>::to_return_type(base::Acquire_Load(&value_));
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/compiler-dispatcher/compiler-dispatcher-job.h" #include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/assert-scope.h"
#include "src/global-handles.h" #include "src/global-handles.h"
#include "src/isolate.h" #include "src/isolate.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
...@@ -16,11 +17,24 @@ namespace v8 { ...@@ -16,11 +17,24 @@ namespace v8 {
namespace internal { namespace internal {
CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate, CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate,
Handle<JSFunction> function) Handle<JSFunction> function,
size_t max_stack_size)
: isolate_(isolate), : isolate_(isolate),
function_(Handle<JSFunction>::cast( function_(Handle<JSFunction>::cast(
isolate_->global_handles()->Create(*function))), isolate_->global_handles()->Create(*function))),
can_parse_on_background_thread_(false) {} max_stack_size_(max_stack_size) {
HandleScope scope(isolate_);
Handle<SharedFunctionInfo> shared(function_->shared(), isolate_);
Handle<Script> script(Script::cast(shared->script()), isolate_);
Handle<String> source(String::cast(script->source()), isolate_);
if (source->IsExternalTwoByteString()) {
can_parse_on_background_thread_ = true;
} else if (source->IsExternalOneByteString()) {
can_parse_on_background_thread_ = true;
} else {
can_parse_on_background_thread_ = false;
}
}
CompilerDispatcherJob::~CompilerDispatcherJob() { CompilerDispatcherJob::~CompilerDispatcherJob() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
...@@ -29,7 +43,7 @@ CompilerDispatcherJob::~CompilerDispatcherJob() { ...@@ -29,7 +43,7 @@ CompilerDispatcherJob::~CompilerDispatcherJob() {
void CompilerDispatcherJob::PrepareToParseOnMainThread() { void CompilerDispatcherJob::PrepareToParseOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status_ == CompileJobStatus::kInitial); DCHECK(status() == CompileJobStatus::kInitial);
HandleScope scope(isolate_); HandleScope scope(isolate_);
unicode_cache_.reset(new UnicodeCache()); unicode_cache_.reset(new UnicodeCache());
zone_.reset(new Zone(isolate_->allocator())); zone_.reset(new Zone(isolate_->allocator()));
...@@ -56,7 +70,32 @@ void CompilerDispatcherJob::PrepareToParseOnMainThread() { ...@@ -56,7 +70,32 @@ void CompilerDispatcherJob::PrepareToParseOnMainThread() {
parse_info_->set_character_stream(character_stream_.get()); parse_info_->set_character_stream(character_stream_.get());
parse_info_->set_hash_seed(isolate_->heap()->HashSeed()); parse_info_->set_hash_seed(isolate_->heap()->HashSeed());
parse_info_->set_unicode_cache(unicode_cache_.get()); parse_info_->set_unicode_cache(unicode_cache_.get());
status_ = CompileJobStatus::kReadyToParse; parser_.reset(new Parser(parse_info_.get()));
status_.SetValue(CompileJobStatus::kReadyToParse);
}
void CompilerDispatcherJob::Parse() {
DCHECK(can_parse_on_background_thread_ ||
ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kReadyToParse);
DisallowHeapAllocation no_allocation;
DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref;
// Nullify the Isolate temporarily so that the parser doesn't accidentally
// use it.
parse_info_->set_isolate(nullptr);
uintptr_t stack_limit =
reinterpret_cast<uintptr_t>(&stack_limit) - max_stack_size_ * KB;
parser_->set_stack_limit(stack_limit);
parser_->ParseOnBackground(parse_info_.get());
parse_info_->set_isolate(isolate_);
status_.SetValue(CompileJobStatus::kParsed);
} }
} // namespace internal } // namespace internal
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "src/base/atomic-utils.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/handles.h" #include "src/handles.h"
...@@ -17,6 +18,7 @@ class CompilationInfo; ...@@ -17,6 +18,7 @@ class CompilationInfo;
class Isolate; class Isolate;
class JSFunction; class JSFunction;
class ParseInfo; class ParseInfo;
class Parser;
class UnicodeCache; class UnicodeCache;
class Utf16CharacterStream; class Utf16CharacterStream;
class Zone; class Zone;
...@@ -24,28 +26,39 @@ class Zone; ...@@ -24,28 +26,39 @@ class Zone;
enum class CompileJobStatus { enum class CompileJobStatus {
kInitial, kInitial,
kReadyToParse, kReadyToParse,
kParsed,
}; };
class CompilerDispatcherJob { class CompilerDispatcherJob {
public: public:
CompilerDispatcherJob(Isolate* isolate, Handle<JSFunction> function); CompilerDispatcherJob(Isolate* isolate, Handle<JSFunction> function,
size_t max_stack_size);
~CompilerDispatcherJob(); ~CompilerDispatcherJob();
CompileJobStatus status() const { return status_; } CompileJobStatus status() const { return status_.Value(); }
bool can_parse_on_background_thread() const {
return can_parse_on_background_thread_;
}
// Transition from kInitial to kReadyToParse. // Transition from kInitial to kReadyToParse.
void PrepareToParseOnMainThread(); void PrepareToParseOnMainThread();
// Transition from kReadyToParse to kParsed.
void Parse();
private: private:
CompileJobStatus status_ = CompileJobStatus::kInitial; base::AtomicValue<CompileJobStatus> status_ =
base::AtomicValue<CompileJobStatus>(CompileJobStatus::kInitial);
Isolate* isolate_; Isolate* isolate_;
Handle<JSFunction> function_; // Global handle. Handle<JSFunction> function_; // Global handle.
size_t max_stack_size_;
// Members required for parsing. // Members required for parsing.
std::unique_ptr<UnicodeCache> unicode_cache_; std::unique_ptr<UnicodeCache> unicode_cache_;
std::unique_ptr<Zone> zone_; std::unique_ptr<Zone> zone_;
std::unique_ptr<Utf16CharacterStream> character_stream_; std::unique_ptr<Utf16CharacterStream> character_stream_;
std::unique_ptr<ParseInfo> parse_info_; std::unique_ptr<ParseInfo> parse_info_;
std::unique_ptr<Parser> parser_;
bool can_parse_on_background_thread_; bool can_parse_on_background_thread_;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <memory> #include <memory>
#include "src/compiler-dispatcher/compiler-dispatcher-job.h" #include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/flags.h"
#include "src/isolate-inl.h" #include "src/isolate-inl.h"
#include "test/unittests/test-utils.h" #include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -14,20 +15,78 @@ namespace internal { ...@@ -14,20 +15,78 @@ namespace internal {
typedef TestWithContext CompilerDispatcherJobTest; typedef TestWithContext CompilerDispatcherJobTest;
namespace {
class ScriptResource : public v8::String::ExternalOneByteStringResource {
public:
ScriptResource(const char* data, size_t length)
: data_(data), length_(length) {}
const char* data() const { return data_; }
size_t length() const { return length_; }
private:
const char* data_;
size_t length_;
DISALLOW_COPY_AND_ASSIGN(ScriptResource);
};
Handle<JSFunction> CreateFunction(
Isolate* isolate, ExternalOneByteString::Resource* maybe_resource) {
HandleScope scope(isolate);
Handle<String> source;
if (maybe_resource) {
source = isolate->factory()
->NewExternalStringFromOneByte(maybe_resource)
.ToHandleChecked();
} else {
source = isolate->factory()->NewStringFromStaticChars("source");
}
Handle<Script> script = isolate->factory()->NewScript(source);
Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
isolate->factory()->NewStringFromStaticChars("f"), MaybeHandle<Code>(),
false);
SharedFunctionInfo::SetScript(shared, script);
Handle<JSFunction> function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(
shared, handle(isolate->context(), isolate));
return scope.CloseAndEscape(function);
}
} // namespace
TEST_F(CompilerDispatcherJobTest, Construct) { TEST_F(CompilerDispatcherJobTest, Construct) {
Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate()); Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate());
std::unique_ptr<CompilerDispatcherJob> job( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
new CompilerDispatcherJob(i_isolate, i_isolate->object_function())); i_isolate, CreateFunction(i_isolate, nullptr), FLAG_stack_size));
}
TEST_F(CompilerDispatcherJobTest, CanParseOnBackgroundThread) {
Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate());
{
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate, CreateFunction(i_isolate, nullptr), FLAG_stack_size));
ASSERT_FALSE(job->can_parse_on_background_thread());
}
{
ScriptResource script("script", strlen("script"));
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
i_isolate, CreateFunction(i_isolate, &script), FLAG_stack_size));
ASSERT_TRUE(job->can_parse_on_background_thread());
}
} }
TEST_F(CompilerDispatcherJobTest, PrepareToParse) { TEST_F(CompilerDispatcherJobTest, StateTransitions) {
Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate()); Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate());
std::unique_ptr<CompilerDispatcherJob> job( std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
new CompilerDispatcherJob(i_isolate, i_isolate->object_function())); i_isolate, CreateFunction(i_isolate, nullptr), FLAG_stack_size));
ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); ASSERT_TRUE(job->status() == CompileJobStatus::kInitial);
job->PrepareToParseOnMainThread(); job->PrepareToParseOnMainThread();
ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToParse); ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToParse);
job->Parse();
ASSERT_TRUE(job->status() == CompileJobStatus::kParsed);
} }
} // namespace internal } // namespace internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment