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 {
Status ExecuteJobImpl() final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
OffThreadIsolate* isolate) final {
UNREACHABLE();
}
private:
void RecordHistograms(Isolate* isolate);
......
This diff is collapsed.
......@@ -10,10 +10,11 @@
#include "src/base/platform/elapsed-timer.h"
#include "src/codegen/bailout-reason.h"
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/logging/code-events.h"
#include "src/utils/allocation.h"
#include "src/objects/contexts.h"
#include "src/utils/allocation.h"
#include "src/zone/zone.h"
namespace v8 {
......@@ -258,6 +259,10 @@ class UnoptimizedCompilationJob : public CompilationJob {
V8_WARN_UNUSED_RESULT Status
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 RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
Handle<SharedFunctionInfo> shared,
......@@ -275,6 +280,8 @@ class UnoptimizedCompilationJob : public CompilationJob {
virtual Status ExecuteJobImpl() = 0;
virtual Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) = 0;
virtual Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
OffThreadIsolate* isolate) = 0;
private:
uintptr_t stack_limit_;
......@@ -364,7 +371,10 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
void Run();
ParseInfo* info() { return info_.get(); }
ParseInfo* info() {
DCHECK_NOT_NULL(info_);
return info_.get();
}
Parser* parser() { return parser_.get(); }
UnoptimizedCompilationJob* outer_function_job() {
return outer_function_job_.get();
......@@ -372,6 +382,18 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
UnoptimizedCompilationJobList* 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:
// Data needed for parsing, and data needed to to be passed between thread
......@@ -384,10 +406,27 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
std::unique_ptr<UnoptimizedCompilationJob> outer_function_job_;
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_;
WorkerThreadRuntimeCallStats* worker_thread_runtime_call_stats_;
AccountingAllocator* allocator_;
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);
};
......
......@@ -48,7 +48,10 @@ class V8_EXPORT_PRIVATE OffThreadIsolate final
// This method finishes the use of the off-thread Isolate, and can be safely
// called off-thread.
void FinishOffThread() { factory()->FinishOffThread(); }
void FinishOffThread() {
factory()->FinishOffThread();
handle_zone_ = nullptr;
}
template <typename T>
Handle<T> Throw(Handle<Object> exception) {
......@@ -59,6 +62,7 @@ class V8_EXPORT_PRIVATE OffThreadIsolate final
}
Address* NewHandle(Address object) {
DCHECK_NOT_NULL(handle_zone_);
Address* location =
static_cast<Address*>(handle_zone_->New(sizeof(Address)));
*location = object;
......
......@@ -1073,6 +1073,9 @@ DEFINE_BOOL(enable_regexp_unaligned_accesses, true,
// api.cc
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,
"Disable old-style API accessors whose setters trigger through the "
"prototype chain")
......
......@@ -34,13 +34,13 @@ bool HandleBase::IsDereferenceAllowed() const {
if (object.IsSmi()) return true;
HeapObject heap_object = HeapObject::cast(object);
if (IsReadOnlyHeapObject(heap_object)) return true;
if (!Heap::InOffThreadSpace(heap_object)) {
Isolate* isolate = GetIsolateFromWritableObject(heap_object);
RootIndex root_index;
if (isolate->roots_table().IsRootHandleLocation(location_, &root_index) &&
RootsTable::IsImmortalImmovable(root_index)) {
return true;
}
if (Heap::InOffThreadSpace(heap_object)) return true;
Isolate* isolate = GetIsolateFromWritableObject(heap_object);
RootIndex root_index;
if (isolate->roots_table().IsRootHandleLocation(location_, &root_index) &&
RootsTable::IsImmortalImmovable(root_index)) {
return true;
}
return AllowHandleDereference::IsAllowed();
}
......
......@@ -392,6 +392,26 @@ FactoryBase<Impl>::NewTemplateObjectDescription(
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>
Handle<CoverageInfo> FactoryBase<Impl>::NewCoverageInfo(
const ZoneVector<SourceRange>& slots) {
......
......@@ -130,6 +130,11 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase {
Handle<String> inferred_name, int32_t start_position,
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<SeqOneByteString> NewOneByteInternalizedString(
......
......@@ -439,25 +439,6 @@ Handle<FixedArrayBase> Factory::NewFixedDoubleArrayWithHoles(int length) {
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) {
DCHECK_LE(0, number_of_frames);
Handle<FixedArray> result =
......
......@@ -146,11 +146,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
// Allocate a new fixed double array with hole values.
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<OrderedHashSet> NewOrderedHashSet();
......
......@@ -21,6 +21,7 @@
#include "src/objects/visitors.h"
#include "src/roots/roots-inl.h"
#include "src/roots/roots.h"
#include "src/tracing/trace-event.h"
namespace v8 {
namespace internal {
......@@ -107,73 +108,87 @@ void OffThreadFactory::Publish(Isolate* isolate) {
// structure off-thread and merge it into the current handle scope all in one
// go (DeferredHandles maybe?).
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;
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
// longer) off-thread pages and main-thread heap pages, and objects in the
// 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.
for (size_t i = 0; i < string_slots_.size(); ++i) {
int slot_offset = string_slots_[i].slot_offset;
// There's currently no cases where the holder object could have been
// resized.
DCHECK_LT(slot_offset, heap_object_handles[i]->Size());
ObjectSlot slot(heap_object_handles[i]->ptr() + slot_offset);
String string = String::cast(slot.Acquire_Load());
if (string.IsThinString()) {
// We may have already internalized this string via another slot.
slot.Release_Store(ThinString::cast(string).GetUnderlying());
} else {
HandleScope handle_scope(isolate);
Handle<String> string_handle = handle(string, isolate);
Handle<String> internalized_string =
isolate->factory()->InternalizeString(string_handle);
// Recalculate the slot in case there was GC and the holder moved.
ObjectSlot slot(heap_object_handles[i]->ptr() +
string_slots_[i].slot_offset);
DCHECK(string_handle->IsThinString() ||
string_handle->IsInternalizedString());
if (*string_handle != *internalized_string) {
slot.Release_Store(*internalized_string);
{
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.OffThreadFinalization.Publish.UpdateHandles");
for (size_t i = 0; i < string_slots_.size(); ++i) {
int slot_offset = string_slots_[i].slot_offset;
// There's currently no cases where the holder object could have been
// resized.
DCHECK_LT(slot_offset, heap_object_handles[i]->Size());
ObjectSlot slot(heap_object_handles[i]->ptr() + slot_offset);
String string = String::cast(slot.Acquire_Load());
if (string.IsThinString()) {
// We may have already internalized this string via another slot.
slot.Release_Store(ThinString::cast(string).GetUnderlying());
} else {
HandleScope handle_scope(isolate);
Handle<String> string_handle = handle(string, isolate);
Handle<String> internalized_string =
isolate->factory()->InternalizeString(string_handle);
// Recalculate the slot in case there was GC and the holder moved.
ObjectSlot slot(heap_object_handles[i]->ptr() +
string_slots_[i].slot_offset);
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.
// This for loop may seem expensive, but practically there's unlikely to be
// more than one script in the OffThreadFactory.
Handle<WeakArrayList> scripts = isolate->factory()->script_list();
for (Handle<Script> script_handle : script_handles) {
scripts = WeakArrayList::Append(isolate, scripts,
MaybeObjectHandle::Weak(script_handle));
// Merge the recorded scripts into the isolate's script list.
// This for loop may seem expensive, but practically there's unlikely to be
// more than one script in the OffThreadFactory.
Handle<WeakArrayList> scripts = isolate->factory()->script_list();
for (Handle<Script> script_handle : script_handles) {
scripts = WeakArrayList::Append(isolate, scripts,
MaybeObjectHandle::Weak(script_handle));
}
isolate->heap()->SetRootScriptList(*scripts);
}
}
......@@ -208,6 +223,20 @@ Handle<String> OffThreadFactory::MakeOrFindTwoCharacterString(uint16_t c1,
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) {
script_list_.push_back(*shared);
}
......
......@@ -53,6 +53,9 @@ class V8_EXPORT_PRIVATE OffThreadFactory
ACCESSOR_INFO_ROOT_LIST(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 Publish(Isolate* isolate);
......
......@@ -12,6 +12,7 @@
#include "src/ast/scopes.h"
#include "src/codegen/compiler.h"
#include "src/codegen/unoptimized-compilation-info.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/init/bootstrapper.h"
#include "src/init/setup-isolate.h"
#include "src/interpreter/bytecode-generator.h"
......@@ -40,12 +41,20 @@ class InterpreterCompilationJob final : public UnoptimizedCompilationJob {
Status ExecuteJobImpl() final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
OffThreadIsolate* isolate) final;
private:
BytecodeGenerator* generator() { return &generator_; }
void CheckAndPrintBytecodeMismatch(Isolate* isolate, Handle<Script> script,
template <typename LocalIsolate>
void CheckAndPrintBytecodeMismatch(LocalIsolate* isolate,
Handle<Script> script,
Handle<BytecodeArray> bytecode);
template <typename LocalIsolate>
Status DoFinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
LocalIsolate* isolate);
Zone zone_;
UnoptimizedCompilationInfo compilation_info_;
BytecodeGenerator generator_;
......@@ -167,8 +176,10 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() {
}
#ifdef DEBUG
template <typename LocalIsolate>
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);
if (first_mismatch >= 0) {
parse_info()->ast_value_factory()->Internalize(isolate);
......@@ -209,6 +220,27 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
RuntimeCallCounterId::kCompileIgnitionFinalization);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"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();
if (bytecodes.is_null()) {
......
......@@ -907,6 +907,7 @@ class RuntimeCallTimer final {
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Eval) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Function) \
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, ScopeAnalysis) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Script) \
......@@ -986,7 +987,7 @@ class RuntimeCallTimer final {
V(CompileFinalizeBackgroundCompileTask) \
V(CompileFinishNowOnDispatcher) \
V(CompileGetFromOptimizedCodeMap) \
V(CompileIgnitionFinalization) \
V(CompilePublishBackgroundFinalization) \
V(CompileSerialize) \
V(CompileWaitForDispatcher) \
V(DeoptimizeCode) \
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/objects/feedback-vector.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/ic/ic-inl.h"
#include "src/objects/data-handler-inl.h"
......@@ -73,9 +74,10 @@ void FeedbackMetadata::SetKind(FeedbackSlot slot, FeedbackSlotKind kind) {
}
// static
Handle<FeedbackMetadata> FeedbackMetadata::New(Isolate* isolate,
template <typename LocalIsolate>
Handle<FeedbackMetadata> FeedbackMetadata::New(LocalIsolate* isolate,
const FeedbackVectorSpec* spec) {
Factory* factory = isolate->factory();
auto* factory = isolate->factory();
const int slot_count = spec == nullptr ? 0 : spec->slots();
const int closure_feedback_cell_count =
......@@ -111,6 +113,11 @@ Handle<FeedbackMetadata> FeedbackMetadata::New(Isolate* isolate,
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(
const FeedbackVectorSpec* other_spec) const {
if (other_spec->slots() != slot_count()) {
......
......@@ -510,8 +510,9 @@ class FeedbackMetadata : public HeapObject {
V8_EXPORT_PRIVATE FeedbackSlotKind GetKind(FeedbackSlot slot) const;
// If {spec} is null, then it is considered empty.
template <typename LocalIsolate>
V8_EXPORT_PRIVATE static Handle<FeedbackMetadata> New(
Isolate* isolate, const FeedbackVectorSpec* spec = nullptr);
LocalIsolate* isolate, const FeedbackVectorSpec* spec = nullptr);
DECL_PRINTER(FeedbackMetadata)
DECL_VERIFIER(FeedbackMetadata)
......
......@@ -5,19 +5,25 @@
#include "src/parsing/literal-buffer.h"
#include "src/execution/isolate.h"
#include "src/execution/off-thread-isolate.h"
#include "src/heap/factory.h"
#include "src/utils/memcopy.h"
namespace v8 {
namespace internal {
Handle<String> LiteralBuffer::Internalize(Isolate* isolate) const {
template <typename LocalIsolate>
Handle<String> LiteralBuffer::Internalize(LocalIsolate* isolate) const {
if (is_one_byte()) {
return isolate->factory()->InternalizeString(one_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) {
return min_capacity < (kMaxGrowth / (kGrowthFactor - 1))
? min_capacity * kGrowthFactor
......
......@@ -63,7 +63,8 @@ class LiteralBuffer final {
is_one_byte_ = true;
}
Handle<String> Internalize(Isolate* isolate) const;
template <typename LocalIsolate>
Handle<String> Internalize(LocalIsolate* isolate) const;
private:
static const int kInitialCapacity = 16;
......
......@@ -3024,7 +3024,9 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
// ----------------------------------------------------------------------------
// 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);
if (!source_url.is_null()) {
script->set_source_url(*source_url);
......@@ -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) {
// Move statistics to Isolate.
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
......
......@@ -155,7 +155,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// Move statistics to Isolate
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:
friend class ParserBase<Parser>;
......
......@@ -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(
Isolate* isolate, Handle<Script> script,
AstValueFactory* ast_value_factory) {
......
......@@ -52,6 +52,7 @@ class PendingCompilationErrorHandler {
// Handle warnings detected during compilation.
void ReportWarnings(Isolate* isolate, Handle<Script> script);
void ReportWarnings(OffThreadIsolate* isolate, Handle<Script> script);
V8_EXPORT_PRIVATE Handle<String> FormatErrorMessageForTest(
Isolate* isolate) const;
......
......@@ -576,7 +576,8 @@ Token::Value Scanner::ScanTemplateSpan() {
return result;
}
Handle<String> Scanner::SourceUrl(Isolate* isolate) const {
template <typename LocalIsolate>
Handle<String> Scanner::SourceUrl(LocalIsolate* isolate) const {
Handle<String> tmp;
if (source_url_.length() > 0) {
tmp = source_url_.Internalize(isolate);
......@@ -584,7 +585,11 @@ Handle<String> Scanner::SourceUrl(Isolate* isolate) const {
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;
if (source_mapping_url_.length() > 0) {
tmp = source_mapping_url_.Internalize(isolate);
......@@ -592,6 +597,10 @@ Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const {
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 is_check_first_digit) {
// we must have at least one digit after 'x'/'b'/'o'
......
......@@ -403,8 +403,10 @@ class V8_EXPORT_PRIVATE Scanner {
return ScanTemplateSpan();
}
Handle<String> SourceUrl(Isolate* isolate) const;
Handle<String> SourceMappingUrl(Isolate* isolate) const;
template <typename LocalIsolate>
Handle<String> SourceUrl(LocalIsolate* isolate) const;
template <typename LocalIsolate>
Handle<String> SourceMappingUrl(LocalIsolate* isolate) const;
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