Commit 455cb6c0 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[offthread] Allow off-thread bytecode finalization

Add the remaining missing templatizations to allow an initial wiring in
of the off-thread factory into streaming compilation finalization.

The off-thread finalization is behind a flag, disabled by default:
    --finalize-streaming-on-background

When the flag is enabled, background tasks will perform perform the
finalization during their background execution, and will release the
parser and compilation jobs once they are no longer needed.

The implementation is complete enough for performance testing, but not
enough for launch. Notably, there is no support for:

  * Class boilerplates (the code is marked unreachable),
  * Exceptions during finalization, i.e. parse/compile warnings/errors,
  * Allocation sampling,
  * Logging,
  * Asm.js,
  * Parallel complication tasks
  * Forced source positions (for "NeedsDetailedOptimizedCodeLineInfo()")

This patch also adds some tracing events for the various stages of the
off-thread finalization (including the main-thread merge) for further
performance improvements.

Bug: chromium:1011762
Change-Id: Ia44fa56975dd689f0d92c1543b294cdb063eb199
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2066965
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66566}
parent c2e21592
...@@ -200,6 +200,10 @@ class AsmJsCompilationJob final : public UnoptimizedCompilationJob { ...@@ -200,6 +200,10 @@ class AsmJsCompilationJob final : public UnoptimizedCompilationJob {
Status ExecuteJobImpl() final; Status ExecuteJobImpl() final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info, Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) final; Isolate* isolate) final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
OffThreadIsolate* isolate) final {
UNREACHABLE();
}
private: private:
void RecordHistograms(Isolate* isolate); void RecordHistograms(Isolate* isolate);
......
This diff is collapsed.
...@@ -10,10 +10,11 @@ ...@@ -10,10 +10,11 @@
#include "src/base/platform/elapsed-timer.h" #include "src/base/platform/elapsed-timer.h"
#include "src/codegen/bailout-reason.h" #include "src/codegen/bailout-reason.h"
#include "src/common/globals.h"
#include "src/execution/isolate.h" #include "src/execution/isolate.h"
#include "src/logging/code-events.h" #include "src/logging/code-events.h"
#include "src/utils/allocation.h"
#include "src/objects/contexts.h" #include "src/objects/contexts.h"
#include "src/utils/allocation.h"
#include "src/zone/zone.h" #include "src/zone/zone.h"
namespace v8 { namespace v8 {
...@@ -258,6 +259,10 @@ class UnoptimizedCompilationJob : public CompilationJob { ...@@ -258,6 +259,10 @@ class UnoptimizedCompilationJob : public CompilationJob {
V8_WARN_UNUSED_RESULT Status V8_WARN_UNUSED_RESULT Status
FinalizeJob(Handle<SharedFunctionInfo> shared_info, Isolate* isolate); FinalizeJob(Handle<SharedFunctionInfo> shared_info, Isolate* isolate);
// Finalizes the compile job. Can be called on a background thread.
V8_WARN_UNUSED_RESULT Status FinalizeJob(
Handle<SharedFunctionInfo> shared_info, OffThreadIsolate* isolate);
void RecordCompilationStats(Isolate* isolate) const; void RecordCompilationStats(Isolate* isolate) const;
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag, void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
Handle<SharedFunctionInfo> shared, Handle<SharedFunctionInfo> shared,
...@@ -275,6 +280,8 @@ class UnoptimizedCompilationJob : public CompilationJob { ...@@ -275,6 +280,8 @@ class UnoptimizedCompilationJob : public CompilationJob {
virtual Status ExecuteJobImpl() = 0; virtual Status ExecuteJobImpl() = 0;
virtual Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info, virtual Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) = 0; Isolate* isolate) = 0;
virtual Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
OffThreadIsolate* isolate) = 0;
private: private:
uintptr_t stack_limit_; uintptr_t stack_limit_;
...@@ -364,7 +371,10 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask { ...@@ -364,7 +371,10 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
void Run(); void Run();
ParseInfo* info() { return info_.get(); } ParseInfo* info() {
DCHECK_NOT_NULL(info_);
return info_.get();
}
Parser* parser() { return parser_.get(); } Parser* parser() { return parser_.get(); }
UnoptimizedCompilationJob* outer_function_job() { UnoptimizedCompilationJob* outer_function_job() {
return outer_function_job_.get(); return outer_function_job_.get();
...@@ -372,6 +382,18 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask { ...@@ -372,6 +382,18 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
UnoptimizedCompilationJobList* inner_function_jobs() { UnoptimizedCompilationJobList* inner_function_jobs() {
return &inner_function_jobs_; return &inner_function_jobs_;
} }
LanguageMode language_mode() { return language_mode_; }
bool collected_source_positions() { return collected_source_positions_; }
bool finalize_on_background_thread() {
return finalize_on_background_thread_;
}
OffThreadIsolate* off_thread_isolate() { return off_thread_isolate_.get(); }
SharedFunctionInfo outer_function_sfi() {
// Make sure that this is an off-thread object, so that it won't have been
// moved by the GC.
DCHECK(Heap::InOffThreadSpace(outer_function_sfi_));
return outer_function_sfi_;
}
private: private:
// Data needed for parsing, and data needed to to be passed between thread // Data needed for parsing, and data needed to to be passed between thread
...@@ -384,10 +406,27 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask { ...@@ -384,10 +406,27 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
std::unique_ptr<UnoptimizedCompilationJob> outer_function_job_; std::unique_ptr<UnoptimizedCompilationJob> outer_function_job_;
UnoptimizedCompilationJobList inner_function_jobs_; UnoptimizedCompilationJobList inner_function_jobs_;
// Data needed for merging onto the main thread after background finalization.
// TODO(leszeks): When these are available, the above fields are not. We
// should add some stricter type-safety or DCHECKs to ensure that the user of
// the task knows this.
std::unique_ptr<OffThreadIsolate> off_thread_isolate_;
// This is a raw pointer to the off-thread allocated SharedFunctionInfo.
SharedFunctionInfo outer_function_sfi_;
int stack_size_; int stack_size_;
WorkerThreadRuntimeCallStats* worker_thread_runtime_call_stats_; WorkerThreadRuntimeCallStats* worker_thread_runtime_call_stats_;
AccountingAllocator* allocator_; AccountingAllocator* allocator_;
TimedHistogram* timer_; TimedHistogram* timer_;
LanguageMode language_mode_;
bool collected_source_positions_;
// True if the background compilation should be finalized on the background
// thread. When this is true, the ParseInfo, Parser and compilation jobs are
// freed on the background thread, the outer_function_sfi holds the top-level
// function, and the off_thread_isolate has to be merged into the main-thread
// Isolate.
bool finalize_on_background_thread_;
DISALLOW_COPY_AND_ASSIGN(BackgroundCompileTask); DISALLOW_COPY_AND_ASSIGN(BackgroundCompileTask);
}; };
......
...@@ -48,7 +48,10 @@ class V8_EXPORT_PRIVATE OffThreadIsolate final ...@@ -48,7 +48,10 @@ class V8_EXPORT_PRIVATE OffThreadIsolate final
// This method finishes the use of the off-thread Isolate, and can be safely // This method finishes the use of the off-thread Isolate, and can be safely
// called off-thread. // called off-thread.
void FinishOffThread() { factory()->FinishOffThread(); } void FinishOffThread() {
factory()->FinishOffThread();
handle_zone_ = nullptr;
}
template <typename T> template <typename T>
Handle<T> Throw(Handle<Object> exception) { Handle<T> Throw(Handle<Object> exception) {
...@@ -59,6 +62,7 @@ class V8_EXPORT_PRIVATE OffThreadIsolate final ...@@ -59,6 +62,7 @@ class V8_EXPORT_PRIVATE OffThreadIsolate final
} }
Address* NewHandle(Address object) { Address* NewHandle(Address object) {
DCHECK_NOT_NULL(handle_zone_);
Address* location = Address* location =
static_cast<Address*>(handle_zone_->New(sizeof(Address))); static_cast<Address*>(handle_zone_->New(sizeof(Address)));
*location = object; *location = object;
......
...@@ -1073,6 +1073,9 @@ DEFINE_BOOL(enable_regexp_unaligned_accesses, true, ...@@ -1073,6 +1073,9 @@ DEFINE_BOOL(enable_regexp_unaligned_accesses, true,
// api.cc // api.cc
DEFINE_BOOL(script_streaming, true, "enable parsing on background") DEFINE_BOOL(script_streaming, true, "enable parsing on background")
DEFINE_BOOL(
finalize_streaming_on_background, false,
"perform the script streaming finalization on the background thread")
DEFINE_BOOL(disable_old_api_accessors, false, DEFINE_BOOL(disable_old_api_accessors, false,
"Disable old-style API accessors whose setters trigger through the " "Disable old-style API accessors whose setters trigger through the "
"prototype chain") "prototype chain")
......
...@@ -34,13 +34,13 @@ bool HandleBase::IsDereferenceAllowed() const { ...@@ -34,13 +34,13 @@ bool HandleBase::IsDereferenceAllowed() const {
if (object.IsSmi()) return true; if (object.IsSmi()) return true;
HeapObject heap_object = HeapObject::cast(object); HeapObject heap_object = HeapObject::cast(object);
if (IsReadOnlyHeapObject(heap_object)) return true; if (IsReadOnlyHeapObject(heap_object)) return true;
if (!Heap::InOffThreadSpace(heap_object)) { if (Heap::InOffThreadSpace(heap_object)) return true;
Isolate* isolate = GetIsolateFromWritableObject(heap_object);
RootIndex root_index; Isolate* isolate = GetIsolateFromWritableObject(heap_object);
if (isolate->roots_table().IsRootHandleLocation(location_, &root_index) && RootIndex root_index;
RootsTable::IsImmortalImmovable(root_index)) { if (isolate->roots_table().IsRootHandleLocation(location_, &root_index) &&
return true; RootsTable::IsImmortalImmovable(root_index)) {
} return true;
} }
return AllowHandleDereference::IsAllowed(); return AllowHandleDereference::IsAllowed();
} }
......
...@@ -392,6 +392,26 @@ FactoryBase<Impl>::NewTemplateObjectDescription( ...@@ -392,6 +392,26 @@ FactoryBase<Impl>::NewTemplateObjectDescription(
return result; return result;
} }
template <typename Impl>
Handle<FeedbackMetadata> FactoryBase<Impl>::NewFeedbackMetadata(
int slot_count, int feedback_cell_count, AllocationType allocation) {
DCHECK_LE(0, slot_count);
int size = FeedbackMetadata::SizeFor(slot_count);
HeapObject result = AllocateRawWithImmortalMap(
size, allocation, read_only_roots().feedback_metadata_map());
Handle<FeedbackMetadata> data(FeedbackMetadata::cast(result), isolate());
data->set_slot_count(slot_count);
data->set_closure_feedback_cell_count(feedback_cell_count);
// Initialize the data section to 0.
int data_size = size - FeedbackMetadata::kHeaderSize;
Address data_start = data->address() + FeedbackMetadata::kHeaderSize;
memset(reinterpret_cast<byte*>(data_start), 0, data_size);
// Fields have been zeroed out but not initialized, so this object will not
// pass object verification at this point.
return data;
}
template <typename Impl> template <typename Impl>
Handle<CoverageInfo> FactoryBase<Impl>::NewCoverageInfo( Handle<CoverageInfo> FactoryBase<Impl>::NewCoverageInfo(
const ZoneVector<SourceRange>& slots) { const ZoneVector<SourceRange>& slots) {
......
...@@ -130,6 +130,11 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase { ...@@ -130,6 +130,11 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase {
Handle<String> inferred_name, int32_t start_position, Handle<String> inferred_name, int32_t start_position,
int32_t end_position, Handle<PreparseData>); int32_t end_position, Handle<PreparseData>);
// Allocates a FeedbackMedata object and zeroes the data section.
Handle<FeedbackMetadata> NewFeedbackMetadata(
int slot_count, int feedback_cell_count,
AllocationType allocation = AllocationType::kOld);
Handle<CoverageInfo> NewCoverageInfo(const ZoneVector<SourceRange>& slots); Handle<CoverageInfo> NewCoverageInfo(const ZoneVector<SourceRange>& slots);
Handle<SeqOneByteString> NewOneByteInternalizedString( Handle<SeqOneByteString> NewOneByteInternalizedString(
......
...@@ -439,25 +439,6 @@ Handle<FixedArrayBase> Factory::NewFixedDoubleArrayWithHoles(int length) { ...@@ -439,25 +439,6 @@ Handle<FixedArrayBase> Factory::NewFixedDoubleArrayWithHoles(int length) {
return array; return array;
} }
Handle<FeedbackMetadata> Factory::NewFeedbackMetadata(
int slot_count, int feedback_cell_count, AllocationType allocation) {
DCHECK_LE(0, slot_count);
int size = FeedbackMetadata::SizeFor(slot_count);
HeapObject result =
AllocateRawWithImmortalMap(size, allocation, *feedback_metadata_map());
Handle<FeedbackMetadata> data(FeedbackMetadata::cast(result), isolate());
data->set_slot_count(slot_count);
data->set_closure_feedback_cell_count(feedback_cell_count);
// Initialize the data section to 0.
int data_size = size - FeedbackMetadata::kHeaderSize;
Address data_start = data->address() + FeedbackMetadata::kHeaderSize;
memset(reinterpret_cast<byte*>(data_start), 0, data_size);
// Fields have been zeroed out but not initialized, so this object will not
// pass object verification at this point.
return data;
}
Handle<FrameArray> Factory::NewFrameArray(int number_of_frames) { Handle<FrameArray> Factory::NewFrameArray(int number_of_frames) {
DCHECK_LE(0, number_of_frames); DCHECK_LE(0, number_of_frames);
Handle<FixedArray> result = Handle<FixedArray> result =
......
...@@ -146,11 +146,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> { ...@@ -146,11 +146,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
// Allocate a new fixed double array with hole values. // Allocate a new fixed double array with hole values.
Handle<FixedArrayBase> NewFixedDoubleArrayWithHoles(int size); Handle<FixedArrayBase> NewFixedDoubleArrayWithHoles(int size);
// Allocates a FeedbackMedata object and zeroes the data section.
Handle<FeedbackMetadata> NewFeedbackMetadata(
int slot_count, int feedback_cell_count,
AllocationType allocation = AllocationType::kOld);
Handle<FrameArray> NewFrameArray(int number_of_frames); Handle<FrameArray> NewFrameArray(int number_of_frames);
Handle<OrderedHashSet> NewOrderedHashSet(); Handle<OrderedHashSet> NewOrderedHashSet();
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "src/objects/visitors.h" #include "src/objects/visitors.h"
#include "src/roots/roots-inl.h" #include "src/roots/roots-inl.h"
#include "src/roots/roots.h" #include "src/roots/roots.h"
#include "src/tracing/trace-event.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -107,73 +108,87 @@ void OffThreadFactory::Publish(Isolate* isolate) { ...@@ -107,73 +108,87 @@ void OffThreadFactory::Publish(Isolate* isolate) {
// structure off-thread and merge it into the current handle scope all in one // structure off-thread and merge it into the current handle scope all in one
// go (DeferredHandles maybe?). // go (DeferredHandles maybe?).
std::vector<Handle<HeapObject>> heap_object_handles; std::vector<Handle<HeapObject>> heap_object_handles;
heap_object_handles.reserve(string_slots_.size());
for (RelativeSlot relative_slot : string_slots_) {
// TODO(leszeks): Group slots in the same parent object to avoid creating
// multiple duplicate handles.
heap_object_handles.push_back(handle(
HeapObject::cast(Object(relative_slot.object_address)), isolate));
// De-internalize the string so that we can re-internalize it later.
ObjectSlot slot(relative_slot.object_address + relative_slot.slot_offset);
String string = String::cast(slot.Acquire_Load());
bool one_byte = string.IsOneByteRepresentation();
Map map = one_byte ? read_only_roots().one_byte_string_map()
: read_only_roots().string_map();
string.set_map_no_write_barrier(map);
}
std::vector<Handle<Script>> script_handles; std::vector<Handle<Script>> script_handles;
for (Script script : script_list_) { {
script_handles.push_back(handle(script, isolate)); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.OffThreadFinalization.Publish.CollectHandles");
heap_object_handles.reserve(string_slots_.size());
for (RelativeSlot relative_slot : string_slots_) {
// TODO(leszeks): Group slots in the same parent object to avoid creating
// multiple duplicate handles.
heap_object_handles.push_back(handle(
HeapObject::cast(Object(relative_slot.object_address)), isolate));
// De-internalize the string so that we can re-internalize it later.
ObjectSlot slot(relative_slot.object_address + relative_slot.slot_offset);
String string = String::cast(slot.Acquire_Load());
bool one_byte = string.IsOneByteRepresentation();
Map map = one_byte ? read_only_roots().one_byte_string_map()
: read_only_roots().string_map();
string.set_map_no_write_barrier(map);
}
script_handles.reserve(script_list_.size());
for (Script script : script_list_) {
script_handles.push_back(handle(script, isolate));
}
} }
// Then merge the spaces. At this point, we are allowed to point between (no // Then merge the spaces. At this point, we are allowed to point between (no
// longer) off-thread pages and main-thread heap pages, and objects in the // longer) off-thread pages and main-thread heap pages, and objects in the
// previously off-thread page can move. // previously off-thread page can move.
isolate->heap()->old_space()->MergeLocalSpace(&space_); {
isolate->heap()->lo_space()->MergeOffThreadSpace(&lo_space_); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.OffThreadFinalization.Publish.Merge");
isolate->heap()->old_space()->MergeLocalSpace(&space_);
isolate->heap()->lo_space()->MergeOffThreadSpace(&lo_space_);
}
// Iterate the string slots, as an offset from the holders we have handles to. // Iterate the string slots, as an offset from the holders we have handles to.
for (size_t i = 0; i < string_slots_.size(); ++i) { {
int slot_offset = string_slots_[i].slot_offset; TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.OffThreadFinalization.Publish.UpdateHandles");
// There's currently no cases where the holder object could have been for (size_t i = 0; i < string_slots_.size(); ++i) {
// resized. int slot_offset = string_slots_[i].slot_offset;
DCHECK_LT(slot_offset, heap_object_handles[i]->Size());
// There's currently no cases where the holder object could have been
ObjectSlot slot(heap_object_handles[i]->ptr() + slot_offset); // resized.
DCHECK_LT(slot_offset, heap_object_handles[i]->Size());
String string = String::cast(slot.Acquire_Load());
if (string.IsThinString()) { ObjectSlot slot(heap_object_handles[i]->ptr() + slot_offset);
// We may have already internalized this string via another slot.
slot.Release_Store(ThinString::cast(string).GetUnderlying()); String string = String::cast(slot.Acquire_Load());
} else { if (string.IsThinString()) {
HandleScope handle_scope(isolate); // We may have already internalized this string via another slot.
slot.Release_Store(ThinString::cast(string).GetUnderlying());
Handle<String> string_handle = handle(string, isolate); } else {
Handle<String> internalized_string = HandleScope handle_scope(isolate);
isolate->factory()->InternalizeString(string_handle);
Handle<String> string_handle = handle(string, isolate);
// Recalculate the slot in case there was GC and the holder moved. Handle<String> internalized_string =
ObjectSlot slot(heap_object_handles[i]->ptr() + isolate->factory()->InternalizeString(string_handle);
string_slots_[i].slot_offset);
// Recalculate the slot in case there was GC and the holder moved.
DCHECK(string_handle->IsThinString() || ObjectSlot slot(heap_object_handles[i]->ptr() +
string_handle->IsInternalizedString()); string_slots_[i].slot_offset);
if (*string_handle != *internalized_string) {
slot.Release_Store(*internalized_string); DCHECK(string_handle->IsThinString() ||
string_handle->IsInternalizedString());
if (*string_handle != *internalized_string) {
slot.Release_Store(*internalized_string);
}
} }
} }
}
// Merge the recorded scripts into the isolate's script list. // Merge the recorded scripts into the isolate's script list.
// This for loop may seem expensive, but practically there's unlikely to be // This for loop may seem expensive, but practically there's unlikely to be
// more than one script in the OffThreadFactory. // more than one script in the OffThreadFactory.
Handle<WeakArrayList> scripts = isolate->factory()->script_list(); Handle<WeakArrayList> scripts = isolate->factory()->script_list();
for (Handle<Script> script_handle : script_handles) { for (Handle<Script> script_handle : script_handles) {
scripts = WeakArrayList::Append(isolate, scripts, scripts = WeakArrayList::Append(isolate, scripts,
MaybeObjectHandle::Weak(script_handle)); MaybeObjectHandle::Weak(script_handle));
}
isolate->heap()->SetRootScriptList(*scripts);
} }
} }
...@@ -208,6 +223,20 @@ Handle<String> OffThreadFactory::MakeOrFindTwoCharacterString(uint16_t c1, ...@@ -208,6 +223,20 @@ Handle<String> OffThreadFactory::MakeOrFindTwoCharacterString(uint16_t c1,
return ret; return ret;
} }
Handle<String> OffThreadFactory::InternalizeString(
const Vector<const uint8_t>& string) {
uint32_t hash = StringHasher::HashSequentialString(
string.begin(), string.length(), HashSeed(read_only_roots()));
return NewOneByteInternalizedString(string, hash);
}
Handle<String> OffThreadFactory::InternalizeString(
const Vector<const uint16_t>& string) {
uint32_t hash = StringHasher::HashSequentialString(
string.begin(), string.length(), HashSeed(read_only_roots()));
return NewTwoByteInternalizedString(string, hash);
}
void OffThreadFactory::AddToScriptList(Handle<Script> shared) { void OffThreadFactory::AddToScriptList(Handle<Script> shared) {
script_list_.push_back(*shared); script_list_.push_back(*shared);
} }
......
...@@ -53,6 +53,9 @@ class V8_EXPORT_PRIVATE OffThreadFactory ...@@ -53,6 +53,9 @@ class V8_EXPORT_PRIVATE OffThreadFactory
ACCESSOR_INFO_ROOT_LIST(ROOT_ACCESSOR) ACCESSOR_INFO_ROOT_LIST(ROOT_ACCESSOR)
#undef ROOT_ACCESSOR #undef ROOT_ACCESSOR
Handle<String> InternalizeString(const Vector<const uint8_t>& string);
Handle<String> InternalizeString(const Vector<const uint16_t>& string);
void FinishOffThread(); void FinishOffThread();
void Publish(Isolate* isolate); void Publish(Isolate* isolate);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "src/ast/scopes.h" #include "src/ast/scopes.h"
#include "src/codegen/compiler.h" #include "src/codegen/compiler.h"
#include "src/codegen/unoptimized-compilation-info.h" #include "src/codegen/unoptimized-compilation-info.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/init/bootstrapper.h" #include "src/init/bootstrapper.h"
#include "src/init/setup-isolate.h" #include "src/init/setup-isolate.h"
#include "src/interpreter/bytecode-generator.h" #include "src/interpreter/bytecode-generator.h"
...@@ -40,12 +41,20 @@ class InterpreterCompilationJob final : public UnoptimizedCompilationJob { ...@@ -40,12 +41,20 @@ class InterpreterCompilationJob final : public UnoptimizedCompilationJob {
Status ExecuteJobImpl() final; Status ExecuteJobImpl() final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info, Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) final; Isolate* isolate) final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
OffThreadIsolate* isolate) final;
private: private:
BytecodeGenerator* generator() { return &generator_; } BytecodeGenerator* generator() { return &generator_; }
void CheckAndPrintBytecodeMismatch(Isolate* isolate, Handle<Script> script, template <typename LocalIsolate>
void CheckAndPrintBytecodeMismatch(LocalIsolate* isolate,
Handle<Script> script,
Handle<BytecodeArray> bytecode); Handle<BytecodeArray> bytecode);
template <typename LocalIsolate>
Status DoFinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
LocalIsolate* isolate);
Zone zone_; Zone zone_;
UnoptimizedCompilationInfo compilation_info_; UnoptimizedCompilationInfo compilation_info_;
BytecodeGenerator generator_; BytecodeGenerator generator_;
...@@ -167,8 +176,10 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() { ...@@ -167,8 +176,10 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() {
} }
#ifdef DEBUG #ifdef DEBUG
template <typename LocalIsolate>
void InterpreterCompilationJob::CheckAndPrintBytecodeMismatch( void InterpreterCompilationJob::CheckAndPrintBytecodeMismatch(
Isolate* isolate, Handle<Script> script, Handle<BytecodeArray> bytecode) { LocalIsolate* isolate, Handle<Script> script,
Handle<BytecodeArray> bytecode) {
int first_mismatch = generator()->CheckBytecodeMatches(*bytecode); int first_mismatch = generator()->CheckBytecodeMatches(*bytecode);
if (first_mismatch >= 0) { if (first_mismatch >= 0) {
parse_info()->ast_value_factory()->Internalize(isolate); parse_info()->ast_value_factory()->Internalize(isolate);
...@@ -209,6 +220,27 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl( ...@@ -209,6 +220,27 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
RuntimeCallCounterId::kCompileIgnitionFinalization); RuntimeCallCounterId::kCompileIgnitionFinalization);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileIgnitionFinalization"); "V8.CompileIgnitionFinalization");
return DoFinalizeJobImpl(shared_info, isolate);
}
InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
Handle<SharedFunctionInfo> shared_info, OffThreadIsolate* isolate) {
RuntimeCallTimerScope runtimeTimerScope(
parse_info()->runtime_call_stats(),
RuntimeCallCounterId::kCompileBackgroundIgnitionFinalization);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileIgnitionFinalization");
return DoFinalizeJobImpl(shared_info, isolate);
}
template <typename LocalIsolate>
InterpreterCompilationJob::Status InterpreterCompilationJob::DoFinalizeJobImpl(
Handle<SharedFunctionInfo> shared_info, LocalIsolate* isolate) {
RuntimeCallTimerScope runtimeTimerScope(
parse_info()->runtime_call_stats(),
RuntimeCallCounterId::kCompileIgnitionFinalization);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileIgnitionFinalization");
Handle<BytecodeArray> bytecodes = compilation_info_.bytecode_array(); Handle<BytecodeArray> bytecodes = compilation_info_.bytecode_array();
if (bytecodes.is_null()) { if (bytecodes.is_null()) {
......
...@@ -907,6 +907,7 @@ class RuntimeCallTimer final { ...@@ -907,6 +907,7 @@ class RuntimeCallTimer final {
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Eval) \ ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Eval) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Function) \ ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Function) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Ignition) \ ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Ignition) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, IgnitionFinalization) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, RewriteReturnResult) \ ADD_THREAD_SPECIFIC_COUNTER(V, Compile, RewriteReturnResult) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, ScopeAnalysis) \ ADD_THREAD_SPECIFIC_COUNTER(V, Compile, ScopeAnalysis) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Script) \ ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Script) \
...@@ -986,7 +987,7 @@ class RuntimeCallTimer final { ...@@ -986,7 +987,7 @@ class RuntimeCallTimer final {
V(CompileFinalizeBackgroundCompileTask) \ V(CompileFinalizeBackgroundCompileTask) \
V(CompileFinishNowOnDispatcher) \ V(CompileFinishNowOnDispatcher) \
V(CompileGetFromOptimizedCodeMap) \ V(CompileGetFromOptimizedCodeMap) \
V(CompileIgnitionFinalization) \ V(CompilePublishBackgroundFinalization) \
V(CompileSerialize) \ V(CompileSerialize) \
V(CompileWaitForDispatcher) \ V(CompileWaitForDispatcher) \
V(DeoptimizeCode) \ V(DeoptimizeCode) \
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/objects/feedback-vector.h" #include "src/objects/feedback-vector.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/ic/handler-configuration-inl.h" #include "src/ic/handler-configuration-inl.h"
#include "src/ic/ic-inl.h" #include "src/ic/ic-inl.h"
#include "src/objects/data-handler-inl.h" #include "src/objects/data-handler-inl.h"
...@@ -73,9 +74,10 @@ void FeedbackMetadata::SetKind(FeedbackSlot slot, FeedbackSlotKind kind) { ...@@ -73,9 +74,10 @@ void FeedbackMetadata::SetKind(FeedbackSlot slot, FeedbackSlotKind kind) {
} }
// static // static
Handle<FeedbackMetadata> FeedbackMetadata::New(Isolate* isolate, template <typename LocalIsolate>
Handle<FeedbackMetadata> FeedbackMetadata::New(LocalIsolate* isolate,
const FeedbackVectorSpec* spec) { const FeedbackVectorSpec* spec) {
Factory* factory = isolate->factory(); auto* factory = isolate->factory();
const int slot_count = spec == nullptr ? 0 : spec->slots(); const int slot_count = spec == nullptr ? 0 : spec->slots();
const int closure_feedback_cell_count = const int closure_feedback_cell_count =
...@@ -111,6 +113,11 @@ Handle<FeedbackMetadata> FeedbackMetadata::New(Isolate* isolate, ...@@ -111,6 +113,11 @@ Handle<FeedbackMetadata> FeedbackMetadata::New(Isolate* isolate,
return metadata; return metadata;
} }
template Handle<FeedbackMetadata> FeedbackMetadata::New(
Isolate* isolate, const FeedbackVectorSpec* spec);
template Handle<FeedbackMetadata> FeedbackMetadata::New(
OffThreadIsolate* isolate, const FeedbackVectorSpec* spec);
bool FeedbackMetadata::SpecDiffersFrom( bool FeedbackMetadata::SpecDiffersFrom(
const FeedbackVectorSpec* other_spec) const { const FeedbackVectorSpec* other_spec) const {
if (other_spec->slots() != slot_count()) { if (other_spec->slots() != slot_count()) {
......
...@@ -510,8 +510,9 @@ class FeedbackMetadata : public HeapObject { ...@@ -510,8 +510,9 @@ class FeedbackMetadata : public HeapObject {
V8_EXPORT_PRIVATE FeedbackSlotKind GetKind(FeedbackSlot slot) const; V8_EXPORT_PRIVATE FeedbackSlotKind GetKind(FeedbackSlot slot) const;
// If {spec} is null, then it is considered empty. // If {spec} is null, then it is considered empty.
template <typename LocalIsolate>
V8_EXPORT_PRIVATE static Handle<FeedbackMetadata> New( V8_EXPORT_PRIVATE static Handle<FeedbackMetadata> New(
Isolate* isolate, const FeedbackVectorSpec* spec = nullptr); LocalIsolate* isolate, const FeedbackVectorSpec* spec = nullptr);
DECL_PRINTER(FeedbackMetadata) DECL_PRINTER(FeedbackMetadata)
DECL_VERIFIER(FeedbackMetadata) DECL_VERIFIER(FeedbackMetadata)
......
...@@ -5,19 +5,25 @@ ...@@ -5,19 +5,25 @@
#include "src/parsing/literal-buffer.h" #include "src/parsing/literal-buffer.h"
#include "src/execution/isolate.h" #include "src/execution/isolate.h"
#include "src/execution/off-thread-isolate.h"
#include "src/heap/factory.h" #include "src/heap/factory.h"
#include "src/utils/memcopy.h" #include "src/utils/memcopy.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
Handle<String> LiteralBuffer::Internalize(Isolate* isolate) const { template <typename LocalIsolate>
Handle<String> LiteralBuffer::Internalize(LocalIsolate* isolate) const {
if (is_one_byte()) { if (is_one_byte()) {
return isolate->factory()->InternalizeString(one_byte_literal()); return isolate->factory()->InternalizeString(one_byte_literal());
} }
return isolate->factory()->InternalizeString(two_byte_literal()); return isolate->factory()->InternalizeString(two_byte_literal());
} }
template Handle<String> LiteralBuffer::Internalize(Isolate* isolate) const;
template Handle<String> LiteralBuffer::Internalize(
OffThreadIsolate* isolate) const;
int LiteralBuffer::NewCapacity(int min_capacity) { int LiteralBuffer::NewCapacity(int min_capacity) {
return min_capacity < (kMaxGrowth / (kGrowthFactor - 1)) return min_capacity < (kMaxGrowth / (kGrowthFactor - 1))
? min_capacity * kGrowthFactor ? min_capacity * kGrowthFactor
......
...@@ -63,7 +63,8 @@ class LiteralBuffer final { ...@@ -63,7 +63,8 @@ class LiteralBuffer final {
is_one_byte_ = true; is_one_byte_ = true;
} }
Handle<String> Internalize(Isolate* isolate) const; template <typename LocalIsolate>
Handle<String> Internalize(LocalIsolate* isolate) const;
private: private:
static const int kInitialCapacity = 16; static const int kInitialCapacity = 16;
......
...@@ -3024,7 +3024,9 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) { ...@@ -3024,7 +3024,9 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Parser support // Parser support
void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) { template <typename LocalIsolate>
void Parser::HandleSourceURLComments(LocalIsolate* isolate,
Handle<Script> script) {
Handle<String> source_url = scanner_.SourceUrl(isolate); Handle<String> source_url = scanner_.SourceUrl(isolate);
if (!source_url.is_null()) { if (!source_url.is_null()) {
script->set_source_url(*source_url); script->set_source_url(*source_url);
...@@ -3035,6 +3037,11 @@ void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) { ...@@ -3035,6 +3037,11 @@ void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
} }
} }
template void Parser::HandleSourceURLComments(Isolate* isolate,
Handle<Script> script);
template void Parser::HandleSourceURLComments(OffThreadIsolate* isolate,
Handle<Script> script);
void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) { void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) {
// Move statistics to Isolate. // Move statistics to Isolate.
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
......
...@@ -155,7 +155,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ...@@ -155,7 +155,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// Move statistics to Isolate // Move statistics to Isolate
void UpdateStatistics(Isolate* isolate, Handle<Script> script); void UpdateStatistics(Isolate* isolate, Handle<Script> script);
void HandleSourceURLComments(Isolate* isolate, Handle<Script> script); template <typename LocalIsolate>
void HandleSourceURLComments(LocalIsolate* isolate, Handle<Script> script);
private: private:
friend class ParserBase<Parser>; friend class ParserBase<Parser>;
......
...@@ -75,6 +75,12 @@ void PendingCompilationErrorHandler::ReportWarnings(Isolate* isolate, ...@@ -75,6 +75,12 @@ void PendingCompilationErrorHandler::ReportWarnings(Isolate* isolate,
} }
} }
void PendingCompilationErrorHandler::ReportWarnings(OffThreadIsolate* isolate,
Handle<Script> script) {
// TODO(leszeks): Do nothing, re-report on the main thread.
UNREACHABLE();
}
void PendingCompilationErrorHandler::ReportErrors( void PendingCompilationErrorHandler::ReportErrors(
Isolate* isolate, Handle<Script> script, Isolate* isolate, Handle<Script> script,
AstValueFactory* ast_value_factory) { AstValueFactory* ast_value_factory) {
......
...@@ -52,6 +52,7 @@ class PendingCompilationErrorHandler { ...@@ -52,6 +52,7 @@ class PendingCompilationErrorHandler {
// Handle warnings detected during compilation. // Handle warnings detected during compilation.
void ReportWarnings(Isolate* isolate, Handle<Script> script); void ReportWarnings(Isolate* isolate, Handle<Script> script);
void ReportWarnings(OffThreadIsolate* isolate, Handle<Script> script);
V8_EXPORT_PRIVATE Handle<String> FormatErrorMessageForTest( V8_EXPORT_PRIVATE Handle<String> FormatErrorMessageForTest(
Isolate* isolate) const; Isolate* isolate) const;
......
...@@ -576,7 +576,8 @@ Token::Value Scanner::ScanTemplateSpan() { ...@@ -576,7 +576,8 @@ Token::Value Scanner::ScanTemplateSpan() {
return result; return result;
} }
Handle<String> Scanner::SourceUrl(Isolate* isolate) const { template <typename LocalIsolate>
Handle<String> Scanner::SourceUrl(LocalIsolate* isolate) const {
Handle<String> tmp; Handle<String> tmp;
if (source_url_.length() > 0) { if (source_url_.length() > 0) {
tmp = source_url_.Internalize(isolate); tmp = source_url_.Internalize(isolate);
...@@ -584,7 +585,11 @@ Handle<String> Scanner::SourceUrl(Isolate* isolate) const { ...@@ -584,7 +585,11 @@ Handle<String> Scanner::SourceUrl(Isolate* isolate) const {
return tmp; return tmp;
} }
Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const { template Handle<String> Scanner::SourceUrl(Isolate* isolate) const;
template Handle<String> Scanner::SourceUrl(OffThreadIsolate* isolate) const;
template <typename LocalIsolate>
Handle<String> Scanner::SourceMappingUrl(LocalIsolate* isolate) const {
Handle<String> tmp; Handle<String> tmp;
if (source_mapping_url_.length() > 0) { if (source_mapping_url_.length() > 0) {
tmp = source_mapping_url_.Internalize(isolate); tmp = source_mapping_url_.Internalize(isolate);
...@@ -592,6 +597,10 @@ Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const { ...@@ -592,6 +597,10 @@ Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const {
return tmp; return tmp;
} }
template Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const;
template Handle<String> Scanner::SourceMappingUrl(
OffThreadIsolate* isolate) const;
bool Scanner::ScanDigitsWithNumericSeparators(bool (*predicate)(uc32 ch), bool Scanner::ScanDigitsWithNumericSeparators(bool (*predicate)(uc32 ch),
bool is_check_first_digit) { bool is_check_first_digit) {
// we must have at least one digit after 'x'/'b'/'o' // we must have at least one digit after 'x'/'b'/'o'
......
...@@ -403,8 +403,10 @@ class V8_EXPORT_PRIVATE Scanner { ...@@ -403,8 +403,10 @@ class V8_EXPORT_PRIVATE Scanner {
return ScanTemplateSpan(); return ScanTemplateSpan();
} }
Handle<String> SourceUrl(Isolate* isolate) const; template <typename LocalIsolate>
Handle<String> SourceMappingUrl(Isolate* isolate) const; Handle<String> SourceUrl(LocalIsolate* isolate) const;
template <typename LocalIsolate>
Handle<String> SourceMappingUrl(LocalIsolate* isolate) const;
bool FoundHtmlComment() const { return found_html_comment_; } bool FoundHtmlComment() const { return found_html_comment_; }
......
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