| Index: src/compiler-dispatcher/compiler-dispatcher-job.cc
|
| diff --git a/src/compiler-dispatcher/compiler-dispatcher-job.cc b/src/compiler-dispatcher/compiler-dispatcher-job.cc
|
| index 2ca26011bb5646dbacef9b725ac015d2de52af5c..fdb975a5e419fde3427a53514cc5a8730ec33694 100644
|
| --- a/src/compiler-dispatcher/compiler-dispatcher-job.cc
|
| +++ b/src/compiler-dispatcher/compiler-dispatcher-job.cc
|
| @@ -22,6 +22,46 @@
|
| 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(Isolate* isolate,
|
| CompilerDispatcherTracer* tracer,
|
| Handle<SharedFunctionInfo> shared,
|
| @@ -31,14 +71,11 @@ CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate,
|
| shared_(Handle<SharedFunctionInfo>::cast(
|
| isolate_->global_handles()->Create(*shared))),
|
| max_stack_size_(max_stack_size),
|
| - can_compile_on_background_thread_(false),
|
| trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
|
| HandleScope scope(isolate_);
|
| DCHECK(!shared_->outer_scope_info()->IsTheHole(isolate_));
|
| Handle<Script> script(Script::cast(shared_->script()), isolate_);
|
| Handle<String> source(String::cast(script->source()), isolate_);
|
| - can_parse_on_background_thread_ =
|
| - source->IsExternalTwoByteString() || source->IsExternalOneByteString();
|
| if (trace_compiler_dispatcher_jobs_) {
|
| PrintF("CompilerDispatcherJob[%p] created for ", static_cast<void*>(this));
|
| shared_->ShortPrint();
|
| @@ -78,11 +115,68 @@ void CompilerDispatcherJob::PrepareToParseOnMainThread() {
|
| source, shared_->start_position(), shared_->end_position()));
|
| } else {
|
| source = String::Flatten(source);
|
| - // Have to globalize the reference here, so it survives between function
|
| - // calls.
|
| - source_ = Handle<String>::cast(isolate_->global_handles()->Create(*source));
|
| - character_stream_.reset(ScannerStream::For(
|
| - source_, shared_->start_position(), shared_->end_position()));
|
| + 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_ =
|
| + Handle<String>::cast(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 = 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_ =
|
| + Handle<String>::cast(isolate_->global_handles()->Create(*wrapper));
|
| +
|
| + character_stream_.reset(
|
| + ScannerStream::For(wrapper_, shared_->start_position() - offset,
|
| + shared_->end_position() - offset));
|
| }
|
| parse_info_.reset(new ParseInfo(zone_.get()));
|
| parse_info_->set_isolate(isolate_);
|
| @@ -111,8 +205,6 @@ void CompilerDispatcherJob::PrepareToParseOnMainThread() {
|
| }
|
|
|
| void CompilerDispatcherJob::Parse() {
|
| - DCHECK(can_parse_on_background_thread_ ||
|
| - ThreadId::Current().Equals(isolate_->thread_id()));
|
| DCHECK(status() == CompileJobStatus::kReadyToParse);
|
| COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM(
|
| tracer_, kParse,
|
| @@ -123,12 +215,7 @@ void CompilerDispatcherJob::Parse() {
|
|
|
| DisallowHeapAllocation no_allocation;
|
| DisallowHandleAllocation no_handles;
|
| - std::unique_ptr<DisallowHandleDereference> no_deref;
|
| - // If we can't parse on a background thread, we need to be able to deref the
|
| - // source string.
|
| - if (can_parse_on_background_thread_) {
|
| - no_deref.reset(new DisallowHandleDereference());
|
| - }
|
| + DisallowHandleDereference no_deref;
|
|
|
| // Nullify the Isolate temporarily so that the parser doesn't accidentally
|
| // use it.
|
| @@ -157,6 +244,10 @@ bool CompilerDispatcherJob::FinalizeParsingOnMainThread() {
|
| 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();
|
| + }
|
|
|
| if (parse_info_->literal() == nullptr) {
|
| status_ = CompileJobStatus::kFailed;
|
| @@ -217,16 +308,13 @@ bool CompilerDispatcherJob::PrepareToCompileOnMainThread() {
|
| return false;
|
| }
|
|
|
| - can_compile_on_background_thread_ =
|
| - compile_job_->can_execute_on_background_thread();
|
| + CHECK(compile_job_->can_execute_on_background_thread());
|
| status_ = CompileJobStatus::kReadyToCompile;
|
| return true;
|
| }
|
|
|
| void CompilerDispatcherJob::Compile() {
|
| DCHECK(status() == CompileJobStatus::kReadyToCompile);
|
| - DCHECK(can_compile_on_background_thread_ ||
|
| - ThreadId::Current().Equals(isolate_->thread_id()));
|
| COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM(
|
| tracer_, kCompile, parse_info_->literal()->ast_node_count());
|
| if (trace_compiler_dispatcher_jobs_) {
|
| @@ -293,6 +381,10 @@ void CompilerDispatcherJob::ResetOnMainThread() {
|
| 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();
|
| + }
|
|
|
| status_ = CompileJobStatus::kInitial;
|
| }
|
|
|