[offthread] Add OffThreadIsolate support to bytecode generator

Bug: chromium:1011762
Change-Id: I58284d50acaf349ed5c56654972e2c2bcece1ec3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2061550
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66378}
This commit is contained in:
Leszek Swirski 2020-02-20 20:26:47 +01:00 committed by Commit Bot
parent edad3a0f0f
commit 9bb73365eb
29 changed files with 431 additions and 210 deletions

View File

@ -164,7 +164,8 @@ CompilationJob::Status UnoptimizedCompilationJob::FinalizeJob(
void UnoptimizedCompilationJob::RecordCompilationStats(Isolate* isolate) const {
int code_size;
if (compilation_info()->has_bytecode_array()) {
code_size = compilation_info()->bytecode_array()->SizeIncludingMetadata();
code_size =
compilation_info()->bytecode_array<Isolate>()->SizeIncludingMetadata();
} else {
DCHECK(compilation_info()->has_asm_wasm_data());
code_size = compilation_info()->asm_wasm_data()->Size();
@ -184,8 +185,8 @@ void UnoptimizedCompilationJob::RecordFunctionCompilation(
Isolate* isolate) const {
Handle<AbstractCode> abstract_code;
if (compilation_info()->has_bytecode_array()) {
abstract_code =
Handle<AbstractCode>::cast(compilation_info()->bytecode_array());
abstract_code = Handle<AbstractCode>::cast(
compilation_info()->bytecode_array<Isolate>());
} else {
DCHECK(compilation_info()->has_asm_wasm_data());
abstract_code =
@ -420,8 +421,8 @@ void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
shared_info->set_is_asm_wasm_broken(true);
}
InstallBytecodeArray(compilation_info->bytecode_array(), shared_info,
parse_info, isolate);
InstallBytecodeArray(compilation_info->bytecode_array<Isolate>(),
shared_info, parse_info, isolate);
Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
isolate, compilation_info->feedback_vector_spec());
@ -437,8 +438,8 @@ void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
if (compilation_info->has_coverage_info() &&
!shared_info->HasCoverageInfo()) {
DCHECK(isolate->is_block_code_coverage());
isolate->debug()->InstallCoverageInfo(shared_info,
compilation_info->coverage_info());
isolate->debug()->InstallCoverageInfo(
shared_info, compilation_info->coverage_info<Isolate>());
}
}
@ -1282,8 +1283,9 @@ bool Compiler::CollectSourcePositions(Isolate* isolate,
// table set on it as well.
if (shared_info->HasDebugInfo() &&
shared_info->GetDebugInfo().HasInstrumentedBytecodeArray()) {
ByteArray source_position_table =
job->compilation_info()->bytecode_array()->SourcePositionTable();
ByteArray source_position_table = job->compilation_info()
->bytecode_array<Isolate>()
->SourcePositionTable();
shared_info->GetDebugBytecodeArray().set_source_position_table(
source_position_table);
}
@ -2259,23 +2261,25 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
return maybe_result;
}
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
FunctionLiteral* literal, Handle<Script> script, Isolate* isolate) {
template <typename Isolate>
HandleFor<Isolate, SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
FunctionLiteral* literal, HandleFor<Isolate, Script> script,
Isolate* isolate) {
// Precondition: code has been parsed and scopes have been analyzed.
MaybeHandle<SharedFunctionInfo> maybe_existing;
MaybeHandleFor<Isolate, SharedFunctionInfo> maybe_existing;
// Find any previously allocated shared function info for the given literal.
maybe_existing = script->FindSharedFunctionInfo(isolate, literal);
// If we found an existing shared function info, return it.
Handle<SharedFunctionInfo> existing;
HandleFor<Isolate, SharedFunctionInfo> existing;
if (maybe_existing.ToHandle(&existing)) {
// If the function has been uncompiled (bytecode flushed) it will have lost
// any preparsed data. If we produced preparsed data during this compile for
// this function, replace the uncompiled data with one that includes it.
if (literal->produced_preparse_data() != nullptr &&
existing->HasUncompiledDataWithoutPreparseData()) {
Handle<UncompiledData> existing_uncompiled_data =
HandleFor<Isolate, UncompiledData> existing_uncompiled_data =
handle(existing->uncompiled_data(), isolate);
DCHECK_EQ(literal->start_position(),
existing_uncompiled_data->start_position());
@ -2283,11 +2287,11 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
existing_uncompiled_data->end_position());
// Use existing uncompiled data's inferred name as it may be more
// accurate than the literal we preparsed.
Handle<String> inferred_name =
HandleFor<Isolate, String> inferred_name =
handle(existing_uncompiled_data->inferred_name(), isolate);
Handle<PreparseData> preparse_data =
HandleFor<Isolate, PreparseData> preparse_data =
literal->produced_preparse_data()->Serialize(isolate);
Handle<UncompiledData> new_uncompiled_data =
HandleFor<Isolate, UncompiledData> new_uncompiled_data =
isolate->factory()->NewUncompiledDataWithPreparseData(
inferred_name, existing_uncompiled_data->start_position(),
existing_uncompiled_data->end_position(), preparse_data);
@ -2297,12 +2301,18 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
}
// Allocate a shared function info object which will be compiled lazily.
Handle<SharedFunctionInfo> result =
HandleFor<Isolate, SharedFunctionInfo> result =
isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script,
false);
return result;
}
template Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
FunctionLiteral* literal, Handle<Script> script, Isolate* isolate);
template OffThreadHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
FunctionLiteral* literal, OffThreadHandle<Script> script,
OffThreadIsolate* isolate);
MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
BailoutId osr_offset,
JavaScriptFrame* osr_frame) {

View File

@ -176,9 +176,10 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
// Create a shared function info object for the given function literal
// node (the code may be lazily compiled).
static Handle<SharedFunctionInfo> GetSharedFunctionInfo(FunctionLiteral* node,
Handle<Script> script,
Isolate* isolate);
template <typename Isolate>
static HandleFor<Isolate, SharedFunctionInfo> GetSharedFunctionInfo(
FunctionLiteral* node, HandleFor<Isolate, Script> script,
Isolate* isolate);
// ===========================================================================
// The following family of methods provides support for OSR. Code generated

View File

@ -4,6 +4,8 @@
#include "src/codegen/source-position-table.h"
#include "src/base/export-template.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
@ -153,12 +155,13 @@ void SourcePositionTableBuilder::AddEntry(const PositionTableEntry& entry) {
#endif
}
Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable(
template <typename Isolate>
HandleFor<Isolate, ByteArray> SourcePositionTableBuilder::ToSourcePositionTable(
Isolate* isolate) {
if (bytes_.empty()) return isolate->factory()->empty_byte_array();
DCHECK(!Omit());
Handle<ByteArray> table = isolate->factory()->NewByteArray(
HandleFor<Isolate, ByteArray> table = isolate->factory()->NewByteArray(
static_cast<int>(bytes_.size()), AllocationType::kOld);
MemCopy(table->GetDataStartAddress(), bytes_.data(), bytes_.size());
@ -175,6 +178,13 @@ Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable(
return table;
}
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable(
Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
OffThreadHandle<ByteArray> SourcePositionTableBuilder::
ToSourcePositionTable(OffThreadIsolate* isolate);
OwnedVector<byte> SourcePositionTableBuilder::ToSourcePositionTableVector() {
if (bytes_.empty()) return OwnedVector<byte>();
DCHECK(!Omit());

View File

@ -5,6 +5,7 @@
#ifndef V8_CODEGEN_SOURCE_POSITION_TABLE_H_
#define V8_CODEGEN_SOURCE_POSITION_TABLE_H_
#include "src/base/export-template.h"
#include "src/codegen/source-position.h"
#include "src/common/assert-scope.h"
#include "src/common/checks.h"
@ -53,7 +54,9 @@ class V8_EXPORT_PRIVATE SourcePositionTableBuilder {
void AddPosition(size_t code_offset, SourcePosition source_position,
bool is_statement);
Handle<ByteArray> ToSourcePositionTable(Isolate* isolate);
template <typename Isolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
HandleFor<Isolate, ByteArray> ToSourcePositionTable(Isolate* isolate);
OwnedVector<byte> ToSourcePositionTableVector();
inline bool Omit() const { return mode_ != RECORD_SOURCE_POSITIONS; }

View File

@ -75,16 +75,22 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final {
}
bool has_coverage_info() const { return !coverage_info_.is_null(); }
Handle<CoverageInfo> coverage_info() const { return coverage_info_; }
void set_coverage_info(Handle<CoverageInfo> coverage_info) {
template <typename Isolate>
HandleFor<Isolate, CoverageInfo> coverage_info() const {
return coverage_info_.get<Isolate>();
}
void set_coverage_info(HandleOrOffThreadHandle<CoverageInfo> coverage_info) {
coverage_info_ = coverage_info;
}
// Accessors for the output of compilation.
bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
void SetBytecodeArray(Handle<BytecodeArray> bytecode_array) {
template <typename Isolate>
HandleFor<Isolate, BytecodeArray> bytecode_array() const {
return bytecode_array_.get<Isolate>();
}
void SetBytecodeArray(HandleOrOffThreadHandle<BytecodeArray> bytecode_array) {
bytecode_array_ = bytecode_array;
}
@ -124,10 +130,10 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final {
// Encapsulates coverage information gathered by the bytecode generator.
// Needs to be stored on the shared function info once compilation completes.
Handle<CoverageInfo> coverage_info_;
HandleOrOffThreadHandle<CoverageInfo> coverage_info_;
// Holds the bytecode array generated by the interpreter.
Handle<BytecodeArray> bytecode_array_;
HandleOrOffThreadHandle<BytecodeArray> bytecode_array_;
// Holds the asm_wasm data struct generated by the asmjs compiler.
Handle<AsmWasmData> asm_wasm_data_;

View File

@ -5,6 +5,7 @@
#include "src/execution/off-thread-isolate.h"
#include "src/execution/isolate.h"
#include "src/execution/thread-id.h"
#include "src/logging/off-thread-logger.h"
namespace v8 {
@ -13,7 +14,8 @@ namespace internal {
OffThreadIsolate::OffThreadIsolate(Isolate* isolate)
: HiddenOffThreadFactory(isolate),
isolate_(isolate),
logger_(new OffThreadLogger()) {}
logger_(new OffThreadLogger()),
thread_id_(ThreadId::Current()) {}
OffThreadIsolate::~OffThreadIsolate() { delete logger_; }
int OffThreadIsolate::GetNextScriptId() { return isolate_->GetNextScriptId(); }

View File

@ -6,6 +6,7 @@
#define V8_EXECUTION_OFF_THREAD_ISOLATE_H_
#include "src/base/logging.h"
#include "src/execution/thread-id.h"
#include "src/handles/handle-for.h"
#include "src/heap/off-thread-factory.h"
@ -70,12 +71,15 @@ class V8_EXPORT_PRIVATE OffThreadIsolate final
OffThreadLogger* logger() { return logger_; }
ThreadId thread_id() { return thread_id_; }
private:
// TODO(leszeks): Extract out the fields of the Isolate we want and store
// those instead of the whole thing.
Isolate* isolate_;
OffThreadLogger* logger_;
ThreadId thread_id_;
};
} // namespace internal

View File

@ -260,11 +260,11 @@ class HandleOrOffThreadHandle {
}
// Explicit getters for the Handle and OffThreadHandle.
inline Handle<T> get_handle() {
inline Handle<T> get_handle() const {
DCHECK_NE(which_, kOffThreadHandle);
return Handle<T>(reinterpret_cast<Address*>(value_));
}
inline OffThreadHandle<T> get_off_thread_handle() {
inline OffThreadHandle<T> get_off_thread_handle() const {
DCHECK_NE(which_, kHandle);
return OffThreadHandle<T>(T::unchecked_cast(Object(value_)));
}
@ -272,21 +272,21 @@ class HandleOrOffThreadHandle {
// Implicitly convert to Handle, MaybeHandle and OffThreadHandle, whenever
// the conversion can be implicit.
template <typename U>
operator Handle<U>() { // NOLINT
operator Handle<U>() const { // NOLINT
return get_handle();
}
template <typename U>
operator MaybeHandle<U>() { // NOLINT
operator MaybeHandle<U>() const { // NOLINT
return get_handle();
}
template <typename U>
operator OffThreadHandle<U>() { // NOLINT
operator OffThreadHandle<U>() const { // NOLINT
return get_off_thread_handle();
}
// Allow templated dispatch on which type of handle to get.
template <typename IsolateType>
inline HandleFor<IsolateType, T> get() {
inline HandleFor<IsolateType, T> get() const {
return get_for(Tag<IsolateType>());
}
@ -302,8 +302,8 @@ class HandleOrOffThreadHandle {
template <typename IsolateType>
struct Tag {};
V8_INLINE Handle<T> get_for(Tag<class Isolate>) { return get_handle(); }
V8_INLINE OffThreadHandle<T> get_for(Tag<class OffThreadIsolate>) {
V8_INLINE Handle<T> get_for(Tag<class Isolate>) const { return get_handle(); }
V8_INLINE OffThreadHandle<T> get_for(Tag<class OffThreadIsolate>) const {
return get_off_thread_handle();
}

View File

@ -4,10 +4,12 @@
#include "src/heap/factory-base.h"
#include "src/ast/ast-source-ranges.h"
#include "src/ast/ast.h"
#include "src/execution/off-thread-isolate.h"
#include "src/handles/handles-inl.h"
#include "src/heap/factory.h"
#include "src/heap/heap-inl.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/read-only-heap.h"
#include "src/logging/log.h"
@ -143,6 +145,54 @@ HandleFor<Impl, WeakFixedArray> FactoryBase<Impl>::NewWeakFixedArray(
length, allocation);
}
template <typename Impl>
HandleFor<Impl, ByteArray> FactoryBase<Impl>::NewByteArray(
int length, AllocationType allocation) {
if (length < 0 || length > ByteArray::kMaxLength) {
isolate()->FatalProcessOutOfHeapMemory("invalid array length");
}
int size = ByteArray::SizeFor(length);
HeapObject result = AllocateRawWithImmortalMap(
size, allocation, read_only_roots().byte_array_map());
HandleFor<Impl, ByteArray> array(ByteArray::cast(result), isolate());
array->set_length(length);
array->clear_padding();
return array;
}
template <typename Impl>
HandleFor<Impl, BytecodeArray> FactoryBase<Impl>::NewBytecodeArray(
int length, const byte* raw_bytecodes, int frame_size, int parameter_count,
HandleFor<Impl, FixedArray> constant_pool) {
if (length < 0 || length > BytecodeArray::kMaxLength) {
isolate()->FatalProcessOutOfHeapMemory("invalid array length");
}
// Bytecode array is AllocationType::kOld, so constant pool array should be
// too.
DCHECK(!Heap::InYoungGeneration(*constant_pool));
int size = BytecodeArray::SizeFor(length);
HeapObject result = AllocateRawWithImmortalMap(
size, AllocationType::kOld, read_only_roots().bytecode_array_map());
HandleFor<Impl, BytecodeArray> instance(BytecodeArray::cast(result),
isolate());
instance->set_length(length);
instance->set_frame_size(frame_size);
instance->set_parameter_count(parameter_count);
instance->set_incoming_new_target_or_generator_register(
interpreter::Register::invalid_value());
instance->set_osr_loop_nesting_level(0);
instance->set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge);
instance->set_constant_pool(*constant_pool);
instance->set_handler_table(read_only_roots().empty_byte_array());
instance->set_source_position_table(read_only_roots().undefined_value());
CopyBytes(reinterpret_cast<byte*>(instance->GetFirstBytecodeAddress()),
raw_bytecodes, length);
instance->clear_padding();
return instance;
}
template <typename Impl>
HandleFor<Impl, Script> FactoryBase<Impl>::NewScript(
HandleFor<Impl, String> source) {
@ -350,6 +400,26 @@ FactoryBase<Impl>::NewTemplateObjectDescription(
return result;
}
template <typename Impl>
HandleFor<Impl, CoverageInfo> FactoryBase<Impl>::NewCoverageInfo(
const ZoneVector<SourceRange>& slots) {
const int slot_count = static_cast<int>(slots.size());
int size = CoverageInfo::SizeFor(slot_count);
Map map = read_only_roots().coverage_info_map();
HeapObject result =
AllocateRawWithImmortalMap(size, AllocationType::kYoung, map);
HandleFor<Impl, CoverageInfo> info(CoverageInfo::cast(result), isolate());
info->set_slot_count(slot_count);
for (int i = 0; i < slot_count; i++) {
SourceRange range = slots[i];
info->InitializeSlot(i, range.start, range.end);
}
return info;
}
template <typename Impl>
HandleFor<Impl, SeqOneByteString>
FactoryBase<Impl>::NewOneByteInternalizedString(

View File

@ -28,6 +28,11 @@ class SourceTextModuleInfo;
class PreparseData;
class UncompiledDataWithoutPreparseData;
class UncompiledDataWithPreparseData;
class BytecodeArray;
class CoverageInfo;
struct SourceRange;
template <typename T>
class ZoneVector;
template <typename Impl>
class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase {
@ -89,6 +94,13 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase {
HandleFor<Impl, WeakFixedArray> NewWeakFixedArray(
int length, AllocationType allocation = AllocationType::kYoung);
HandleFor<Impl, ByteArray> NewByteArray(
int length, AllocationType allocation = AllocationType::kYoung);
HandleFor<Impl, BytecodeArray> NewBytecodeArray(
int length, const byte* raw_bytecodes, int frame_size,
int parameter_count, HandleFor<Impl, FixedArray> constant_pool);
// Allocates a fixed array for name-value pairs of boilerplate properties and
// calculates the number of properties we need to store in the backing store.
HandleFor<Impl, ObjectBoilerplateDescription> NewObjectBoilerplateDescription(
@ -126,6 +138,9 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase {
int32_t end_position,
HandleFor<Impl, PreparseData>);
HandleFor<Impl, CoverageInfo> NewCoverageInfo(
const ZoneVector<SourceRange>& slots);
HandleFor<Impl, SeqOneByteString> NewOneByteInternalizedString(
const Vector<const uint8_t>& str, uint32_t hash_field);
HandleFor<Impl, SeqTwoByteString> NewTwoByteInternalizedString(

View File

@ -1328,50 +1328,6 @@ Handle<Foreign> Factory::NewForeign(Address addr) {
return foreign;
}
Handle<ByteArray> Factory::NewByteArray(int length, AllocationType allocation) {
if (length < 0 || length > ByteArray::kMaxLength) {
isolate()->heap()->FatalProcessOutOfMemory("invalid array length");
}
int size = ByteArray::SizeFor(length);
HeapObject result =
AllocateRawWithImmortalMap(size, allocation, *byte_array_map());
Handle<ByteArray> array(ByteArray::cast(result), isolate());
array->set_length(length);
array->clear_padding();
return array;
}
Handle<BytecodeArray> Factory::NewBytecodeArray(
int length, const byte* raw_bytecodes, int frame_size, int parameter_count,
Handle<FixedArray> constant_pool) {
if (length < 0 || length > BytecodeArray::kMaxLength) {
isolate()->heap()->FatalProcessOutOfMemory("invalid array length");
}
// Bytecode array is AllocationType::kOld, so constant pool array should be
// too.
DCHECK(!Heap::InYoungGeneration(*constant_pool));
int size = BytecodeArray::SizeFor(length);
HeapObject result = AllocateRawWithImmortalMap(size, AllocationType::kOld,
*bytecode_array_map());
Handle<BytecodeArray> instance(BytecodeArray::cast(result), isolate());
instance->set_length(length);
instance->set_frame_size(frame_size);
instance->set_parameter_count(parameter_count);
instance->set_incoming_new_target_or_generator_register(
interpreter::Register::invalid_value());
instance->set_osr_loop_nesting_level(0);
instance->set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge);
instance->set_constant_pool(*constant_pool);
instance->set_handler_table(*empty_byte_array());
instance->set_source_position_table(*undefined_value());
CopyBytes(reinterpret_cast<byte*>(instance->GetFirstBytecodeAddress()),
raw_bytecodes, length);
instance->clear_padding();
return instance;
}
Handle<Cell> Factory::NewCell(Handle<Object> value) {
STATIC_ASSERT(Cell::kSize <= kMaxRegularHeapObjectSize);
HeapObject result = AllocateRawWithImmortalMap(
@ -3118,25 +3074,6 @@ Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
return debug_info;
}
Handle<CoverageInfo> Factory::NewCoverageInfo(
const ZoneVector<SourceRange>& slots) {
const int slot_count = static_cast<int>(slots.size());
int size = CoverageInfo::SizeFor(slot_count);
Map map = read_only_roots().coverage_info_map();
HeapObject result =
AllocateRawWithImmortalMap(size, AllocationType::kYoung, map);
Handle<CoverageInfo> info(CoverageInfo::cast(result), isolate());
info->set_slot_count(slot_count);
for (int i = 0; i < slot_count; i++) {
SourceRange range = slots[i];
info->InitializeSlot(i, range.start, range.end);
}
return info;
}
Handle<BreakPointInfo> Factory::NewBreakPointInfo(int source_position) {
Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
NewStruct(BREAK_POINT_INFO_TYPE, AllocationType::kOld));

View File

@ -67,9 +67,6 @@ class WasmCapiFunctionData;
class WasmExportedFunctionData;
class WasmJSFunctionData;
class WeakCell;
struct SourceRange;
template <typename T>
class ZoneVector;
enum class SharedFlag : uint8_t;
enum class InitializedFlag : uint8_t;
@ -397,13 +394,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
// Foreign objects are pretenured when allocated by the bootstrapper.
Handle<Foreign> NewForeign(Address addr);
Handle<ByteArray> NewByteArray(
int length, AllocationType allocation = AllocationType::kYoung);
Handle<BytecodeArray> NewBytecodeArray(int length, const byte* raw_bytecodes,
int frame_size, int parameter_count,
Handle<FixedArray> constant_pool);
Handle<Cell> NewCell(Handle<Object> value);
Handle<PropertyCell> NewPropertyCell(
@ -765,8 +755,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
Handle<ClassPositions> NewClassPositions(int start, int end);
Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
Handle<CoverageInfo> NewCoverageInfo(const ZoneVector<SourceRange>& slots);
// Return a map for given number of properties using the map cache in the
// native context.
Handle<Map> ObjectLiteralMapFromCache(Handle<NativeContext> native_context,

View File

@ -4,6 +4,7 @@
#include "src/interpreter/bytecode-array-builder.h"
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
#include "src/interpreter/bytecode-array-writer.h"
#include "src/interpreter/bytecode-jump-table.h"
@ -81,7 +82,9 @@ Register BytecodeArrayBuilder::Local(int index) const {
return Register(index);
}
Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
template <typename Isolate>
HandleFor<Isolate, BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(
Isolate* isolate) {
DCHECK(RemainderOfBlockIsDead());
DCHECK(!bytecode_generated_);
bytecode_generated_ = true;
@ -93,25 +96,41 @@ Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
register_count = register_optimizer_->maxiumum_register_index() + 1;
}
Handle<ByteArray> handler_table =
HandleFor<Isolate, ByteArray> handler_table =
handler_table_builder()->ToHandlerTable(isolate);
return bytecode_array_writer_.ToBytecodeArray(
isolate, register_count, parameter_count(), handler_table);
}
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(
Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
OffThreadHandle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(
OffThreadIsolate* isolate);
#ifdef DEBUG
int BytecodeArrayBuilder::CheckBytecodeMatches(Handle<BytecodeArray> bytecode) {
int BytecodeArrayBuilder::CheckBytecodeMatches(BytecodeArray bytecode) {
DisallowHeapAllocation no_gc;
return bytecode_array_writer_.CheckBytecodeMatches(bytecode);
}
#endif
Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
template <typename Isolate>
HandleFor<Isolate, ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
Isolate* isolate) {
DCHECK(RemainderOfBlockIsDead());
return bytecode_array_writer_.ToSourcePositionTable(isolate);
}
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
OffThreadHandle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
OffThreadIsolate* isolate);
BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
Bytecode bytecode) {
BytecodeSourceInfo source_position;
@ -1549,8 +1568,8 @@ size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
return constant_array_builder()->InsertDeferred();
}
void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
Handle<Object> object) {
void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(
size_t entry, HandleOrOffThreadHandle<Object> object) {
constant_array_builder()->SetDeferredAt(entry, object);
}

View File

@ -7,6 +7,7 @@
#include "src/ast/ast.h"
#include "src/base/compiler-specific.h"
#include "src/base/export-template.h"
#include "src/common/globals.h"
#include "src/interpreter/bytecode-array-writer.h"
#include "src/interpreter/bytecode-flags.h"
@ -42,11 +43,15 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
SourcePositionTableBuilder::RecordingMode source_position_mode =
SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS);
Handle<BytecodeArray> ToBytecodeArray(Isolate* isolate);
Handle<ByteArray> ToSourcePositionTable(Isolate* isolate);
template <typename Isolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
HandleFor<Isolate, BytecodeArray> ToBytecodeArray(Isolate* isolate);
template <typename Isolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
HandleFor<Isolate, ByteArray> ToSourcePositionTable(Isolate* isolate);
#ifdef DEBUG
int CheckBytecodeMatches(Handle<BytecodeArray> bytecode);
int CheckBytecodeMatches(BytecodeArray bytecode);
#endif
// Get the number of parameters expected by function.
@ -498,7 +503,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
// Allocates a slot in the constant pool which can later be set.
size_t AllocateDeferredConstantPoolEntry();
// Sets the deferred value into an allocated constant pool entry.
void SetDeferredConstantPoolEntry(size_t entry, Handle<Object> object);
void SetDeferredConstantPoolEntry(size_t entry,
HandleOrOffThreadHandle<Object> object);
void InitializeReturnPosition(FunctionLiteral* literal);

View File

@ -5,6 +5,7 @@
#include "src/interpreter/bytecode-array-writer.h"
#include "src/api/api-inl.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/interpreter/bytecode-jump-table.h"
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-node.h"
@ -36,43 +37,63 @@ BytecodeArrayWriter::BytecodeArrayWriter(
bytecodes_.reserve(512); // Derived via experimentation.
}
Handle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
template <typename Isolate>
HandleFor<Isolate, BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count,
Handle<ByteArray> handler_table) {
HandleFor<Isolate, ByteArray> handler_table) {
DCHECK_EQ(0, unbound_jumps_);
int bytecode_size = static_cast<int>(bytecodes()->size());
int frame_size = register_count * kSystemPointerSize;
Handle<FixedArray> constant_pool =
HandleFor<Isolate, FixedArray> constant_pool =
constant_array_builder()->ToFixedArray(isolate);
Handle<BytecodeArray> bytecode_array = isolate->factory()->NewBytecodeArray(
bytecode_size, &bytecodes()->front(), frame_size, parameter_count,
constant_pool);
HandleFor<Isolate, BytecodeArray> bytecode_array =
isolate->factory()->NewBytecodeArray(bytecode_size, &bytecodes()->front(),
frame_size, parameter_count,
constant_pool);
bytecode_array->set_handler_table(*handler_table);
return bytecode_array;
}
Handle<ByteArray> BytecodeArrayWriter::ToSourcePositionTable(Isolate* isolate) {
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count,
Handle<ByteArray> handler_table);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
OffThreadHandle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
OffThreadIsolate* isolate, int register_count, int parameter_count,
OffThreadHandle<ByteArray> handler_table);
template <typename Isolate>
HandleFor<Isolate, ByteArray> BytecodeArrayWriter::ToSourcePositionTable(
Isolate* isolate) {
DCHECK(!source_position_table_builder_.Lazy());
Handle<ByteArray> source_position_table =
HandleFor<Isolate, ByteArray> source_position_table =
source_position_table_builder_.Omit()
? ReadOnlyRoots(isolate).empty_byte_array_handle()
? isolate->factory()->empty_byte_array()
: source_position_table_builder_.ToSourcePositionTable(isolate);
return source_position_table;
}
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<ByteArray> BytecodeArrayWriter::ToSourcePositionTable(
Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
OffThreadHandle<ByteArray> BytecodeArrayWriter::ToSourcePositionTable(
OffThreadIsolate* isolate);
#ifdef DEBUG
int BytecodeArrayWriter::CheckBytecodeMatches(Handle<BytecodeArray> bytecode) {
int BytecodeArrayWriter::CheckBytecodeMatches(BytecodeArray bytecode) {
int mismatches = false;
int bytecode_size = static_cast<int>(bytecodes()->size());
const byte* bytecode_ptr = &bytecodes()->front();
if (bytecode_size != bytecode->length()) mismatches = true;
if (bytecode_size != bytecode.length()) mismatches = true;
// If there's a mismatch only in the length of the bytecode (very unlikely)
// then the first mismatch will be the first extra bytecode.
int first_mismatch = std::min(bytecode_size, bytecode->length());
int first_mismatch = std::min(bytecode_size, bytecode.length());
for (int i = 0; i < first_mismatch; ++i) {
if (bytecode_ptr[i] != bytecode->get(i)) {
if (bytecode_ptr[i] != bytecode.get(i)) {
mismatches = true;
first_mismatch = i;
break;

View File

@ -53,15 +53,19 @@ class V8_EXPORT_PRIVATE BytecodeArrayWriter final {
void SetFunctionEntrySourcePosition(int position);
Handle<BytecodeArray> ToBytecodeArray(Isolate* isolate, int register_count,
int parameter_count,
Handle<ByteArray> handler_table);
template <typename Isolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
HandleFor<Isolate, BytecodeArray> ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count,
HandleFor<Isolate, ByteArray> handler_table);
Handle<ByteArray> ToSourcePositionTable(Isolate* isolate);
template <typename Isolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
HandleFor<Isolate, ByteArray> ToSourcePositionTable(Isolate* isolate);
#ifdef DEBUG
// Returns -1 if they match or the offset of the first mismatching byte.
int CheckBytecodeMatches(Handle<BytecodeArray> bytecode);
int CheckBytecodeMatches(BytecodeArray bytecode);
#endif
bool RemainderOfBlockIsDead() const { return exit_seen_in_block_; }

View File

@ -17,6 +17,7 @@
#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/control-flow-builders.h"
#include "src/logging/log.h"
#include "src/logging/off-thread-logger.h"
#include "src/objects/debug-objects.h"
#include "src/objects/literal-objects-inl.h"
#include "src/objects/objects-inl.h"
@ -728,13 +729,13 @@ class BytecodeGenerator::TestResultScope final : public ExpressionResultScope {
// Used to build a list of toplevel declaration data.
class BytecodeGenerator::TopLevelDeclarationsBuilder final : public ZoneObject {
public:
Handle<FixedArray> AllocateDeclarations(UnoptimizedCompilationInfo* info,
BytecodeGenerator* generator,
Handle<Script> script,
Isolate* isolate) {
template <typename Isolate>
HandleFor<Isolate, FixedArray> AllocateDeclarations(
UnoptimizedCompilationInfo* info, BytecodeGenerator* generator,
HandleFor<Isolate, Script> script, Isolate* isolate) {
DCHECK(has_constant_pool_entry_);
Handle<FixedArray> data =
HandleFor<Isolate, FixedArray> data =
isolate->factory()->NewFixedArray(entry_slots_, AllocationType::kOld);
int array_index = 0;
@ -748,11 +749,11 @@ class BytecodeGenerator::TopLevelDeclarationsBuilder final : public ZoneObject {
#endif
if (decl->IsFunctionDeclaration()) {
FunctionLiteral* f = static_cast<FunctionDeclaration*>(decl)->fun();
Handle<Object> sfi(
HandleFor<Isolate, SharedFunctionInfo> sfi(
Compiler::GetSharedFunctionInfo(f, script, isolate));
// Return a null handle if any initial values can't be created. Caller
// will set stack overflow.
if (sfi.is_null()) return Handle<FixedArray>();
if (sfi.is_null()) return HandleFor<Isolate, FixedArray>();
data->set(array_index++, *sfi);
int literal_index = generator->GetCachedCreateClosureSlot(f);
data->set(array_index++, Smi::FromInt(literal_index));
@ -777,11 +778,11 @@ class BytecodeGenerator::TopLevelDeclarationsBuilder final : public ZoneObject {
DCHECK_EQ(start + kGlobalVariableDeclarationSize, array_index);
} else {
FunctionLiteral* f = static_cast<FunctionDeclaration*>(decl)->fun();
Handle<Object> sfi(
HandleFor<Isolate, SharedFunctionInfo> sfi(
Compiler::GetSharedFunctionInfo(f, script, isolate));
// Return a null handle if any initial values can't be created. Caller
// will set stack overflow.
if (sfi.is_null()) return Handle<FixedArray>();
if (sfi.is_null()) return HandleFor<Isolate, FixedArray>();
data->set(array_index++, *sfi);
int literal_index = generator->GetCachedCreateClosureSlot(f);
data->set(array_index++, Smi::FromInt(literal_index));
@ -1049,29 +1050,55 @@ BytecodeGenerator::BytecodeGenerator(
}
}
Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
Isolate* isolate, Handle<Script> script) {
namespace {
template <typename Isolate>
struct NullContextScopeHelper;
template <>
struct NullContextScopeHelper<Isolate> {
using Type = NullContextScope;
};
template <>
struct NullContextScopeHelper<OffThreadIsolate> {
class DummyNullContextScope {
public:
explicit DummyNullContextScope(OffThreadIsolate*) {}
};
using Type = DummyNullContextScope;
};
template <typename Isolate>
using NullContextScopeFor = typename NullContextScopeHelper<Isolate>::Type;
} // namespace
template <typename Isolate>
HandleFor<Isolate, BytecodeArray> BytecodeGenerator::FinalizeBytecode(
Isolate* isolate, HandleFor<Isolate, Script> script) {
DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
#ifdef DEBUG
// Unoptimized compilation should be context-independent. Verify that we don't
// access the native context by nulling it out during finalization.
NullContextScope null_context_scope(isolate);
NullContextScopeFor<Isolate> null_context_scope(isolate);
#endif
AllocateDeferredConstants(isolate, script);
if (block_coverage_builder_) {
info()->set_coverage_info(
isolate->factory()->NewCoverageInfo(block_coverage_builder_->slots()));
HandleFor<Isolate, CoverageInfo> coverage_info =
isolate->factory()->NewCoverageInfo(block_coverage_builder_->slots());
info()->set_coverage_info(coverage_info);
if (FLAG_trace_block_coverage) {
StdoutStream os;
info()->coverage_info()->CoverageInfoPrint(
os, info()->literal()->GetDebugName());
coverage_info->CoverageInfoPrint(os, info()->literal()->GetDebugName());
}
}
if (HasStackOverflow()) return Handle<BytecodeArray>();
Handle<BytecodeArray> bytecode_array = builder()->ToBytecodeArray(isolate);
if (HasStackOverflow()) return HandleFor<Isolate, BytecodeArray>();
HandleFor<Isolate, BytecodeArray> bytecode_array =
builder()->ToBytecodeArray(isolate);
if (incoming_new_target_or_generator_.is_valid()) {
bytecode_array->set_incoming_new_target_or_generator_register(
@ -1081,38 +1108,51 @@ Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
return bytecode_array;
}
Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
template Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
Isolate* isolate, Handle<Script> script);
template OffThreadHandle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
OffThreadIsolate* isolate, OffThreadHandle<Script> script);
template <typename Isolate>
HandleFor<Isolate, ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
Isolate* isolate) {
DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
#ifdef DEBUG
// Unoptimized compilation should be context-independent. Verify that we don't
// access the native context by nulling it out during finalization.
NullContextScope null_context_scope(isolate);
NullContextScopeFor<Isolate> null_context_scope(isolate);
#endif
Handle<ByteArray> source_position_table =
HandleFor<Isolate, ByteArray> source_position_table =
builder()->ToSourcePositionTable(isolate);
LOG_CODE_EVENT(isolate,
CodeLinePosInfoRecordEvent(
info_->bytecode_array()->GetFirstBytecodeAddress(),
*source_position_table));
LOG_CODE_EVENT(
isolate, CodeLinePosInfoRecordEvent(
info_->bytecode_array<Isolate>()->GetFirstBytecodeAddress(),
*source_position_table));
return source_position_table;
}
template Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
Isolate* isolate);
template OffThreadHandle<ByteArray>
BytecodeGenerator::FinalizeSourcePositionTable(OffThreadIsolate* isolate);
#ifdef DEBUG
int BytecodeGenerator::CheckBytecodeMatches(Handle<BytecodeArray> bytecode) {
int BytecodeGenerator::CheckBytecodeMatches(BytecodeArray bytecode) {
return builder()->CheckBytecodeMatches(bytecode);
}
#endif
void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
Handle<Script> script) {
template <typename Isolate>
void BytecodeGenerator::AllocateDeferredConstants(
Isolate* isolate, HandleFor<Isolate, Script> script) {
if (top_level_builder()->has_top_level_declaration()) {
// Build global declaration pair array.
Handle<FixedArray> declarations = top_level_builder()->AllocateDeclarations(
info(), this, script, isolate);
HandleFor<Isolate, FixedArray> declarations =
top_level_builder()->AllocateDeclarations(info(), this, script,
isolate);
if (declarations.is_null()) return SetStackOverflow();
builder()->SetDeferredConstantPoolEntry(
top_level_builder()->constant_pool_entry(), declarations);
@ -1121,7 +1161,7 @@ void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
// Find or build shared function infos.
for (std::pair<FunctionLiteral*, size_t> literal : function_literals_) {
FunctionLiteral* expr = literal.first;
Handle<SharedFunctionInfo> shared_info =
HandleFor<Isolate, SharedFunctionInfo> shared_info =
Compiler::GetSharedFunctionInfo(expr, script, isolate);
if (shared_info.is_null()) return SetStackOverflow();
builder()->SetDeferredConstantPoolEntry(literal.second, shared_info);
@ -1130,6 +1170,9 @@ void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
// Find or build shared function infos for the native function templates.
for (std::pair<NativeFunctionLiteral*, size_t> literal :
native_function_literals_) {
// This should only happen for main-thread compilations.
DCHECK((std::is_same<Isolate, v8::internal::Isolate>::value));
NativeFunctionLiteral* expr = literal.first;
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
@ -1139,7 +1182,7 @@ void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
v8_isolate, Utils::ToLocal(expr->name()));
DCHECK(!info.IsEmpty());
Handle<SharedFunctionInfo> shared_info =
HandleFor<Isolate, SharedFunctionInfo> shared_info =
FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
isolate, Utils::OpenHandle(*info), expr->name());
DCHECK(!shared_info.is_null());
@ -1152,7 +1195,7 @@ void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
if (object_literal->properties_count() > 0) {
// If constant properties is an empty fixed array, we've already added it
// to the constant pool when visiting the object literal.
Handle<ObjectBoilerplateDescription> constant_properties =
HandleFor<Isolate, ObjectBoilerplateDescription> constant_properties =
object_literal->GetOrBuildBoilerplateDescription(isolate);
builder()->SetDeferredConstantPoolEntry(literal.second,
@ -1163,7 +1206,7 @@ void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
// Build array literal constant elements
for (std::pair<ArrayLiteral*, size_t> literal : array_literals_) {
ArrayLiteral* array_literal = literal.first;
Handle<ArrayBoilerplateDescription> constant_elements =
HandleFor<Isolate, ArrayBoilerplateDescription> constant_elements =
array_literal->GetOrBuildBoilerplateDescription(isolate);
builder()->SetDeferredConstantPoolEntry(literal.second, constant_elements);
}
@ -1171,7 +1214,7 @@ void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
// Build class literal boilerplates.
for (std::pair<ClassLiteral*, size_t> literal : class_literals_) {
ClassLiteral* class_literal = literal.first;
Handle<ClassBoilerplate> class_boilerplate =
HandleFor<Isolate, ClassBoilerplate> class_boilerplate =
ClassBoilerplate::BuildClassBoilerplate(isolate, class_literal);
builder()->SetDeferredConstantPoolEntry(literal.second, class_boilerplate);
}
@ -1179,12 +1222,17 @@ void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
// Build template literals.
for (std::pair<GetTemplateObject*, size_t> literal : template_objects_) {
GetTemplateObject* get_template_object = literal.first;
Handle<TemplateObjectDescription> description =
HandleFor<Isolate, TemplateObjectDescription> description =
get_template_object->GetOrBuildDescription(isolate);
builder()->SetDeferredConstantPoolEntry(literal.second, description);
}
}
template void BytecodeGenerator::AllocateDeferredConstants(
Isolate* isolate, Handle<Script> script);
template void BytecodeGenerator::AllocateDeferredConstants(
OffThreadIsolate* isolate, OffThreadHandle<Script> script);
namespace {
bool NeedsContextInitialization(DeclarationScope* scope) {
return scope->NeedsContext() && !scope->is_script_scope() &&

View File

@ -37,12 +37,14 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
std::vector<FunctionLiteral*>* eager_inner_literals);
void GenerateBytecode(uintptr_t stack_limit);
Handle<BytecodeArray> FinalizeBytecode(Isolate* isolate,
Handle<Script> script);
Handle<ByteArray> FinalizeSourcePositionTable(Isolate* isolate);
template <typename Isolate>
HandleFor<Isolate, BytecodeArray> FinalizeBytecode(
Isolate* isolate, HandleFor<Isolate, Script> script);
template <typename Isolate>
HandleFor<Isolate, ByteArray> FinalizeSourcePositionTable(Isolate* isolate);
#ifdef DEBUG
int CheckBytecodeMatches(Handle<BytecodeArray> bytecode);
int CheckBytecodeMatches(BytecodeArray bytecode);
#endif
#define DECLARE_VISIT(type) void Visit##type(type* node);
@ -161,7 +163,9 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
};
void GenerateBytecodeBody();
void AllocateDeferredConstants(Isolate* isolate, Handle<Script> script);
template <typename Isolate>
void AllocateDeferredConstants(Isolate* isolate,
HandleFor<Isolate, Script> script);
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();

View File

@ -13,6 +13,7 @@
#include "src/ast/scopes.h"
#include "src/base/functional.h"
#include "src/execution/isolate.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/objects/objects-inl.h"
namespace v8 {
@ -64,6 +65,7 @@ const ConstantArrayBuilder::Entry& ConstantArrayBuilder::ConstantArraySlice::At(
}
#if DEBUG
template <typename Isolate>
void ConstantArrayBuilder::ConstantArraySlice::CheckAllElementsAreUnique(
Isolate* isolate) const {
std::set<Smi> smis;
@ -91,7 +93,8 @@ void ConstantArrayBuilder::ConstantArraySlice::CheckAllElementsAreUnique(
duplicate = !scopes.insert(entry.scope_).second;
break;
case Entry::Tag::kHandle:
duplicate = !deferred_objects.insert(*entry.handle_).second;
duplicate =
!deferred_objects.insert(*entry.handle_.get<Isolate>()).second;
break;
case Entry::Tag::kDeferred:
UNREACHABLE(); // Should be kHandle at this point.
@ -166,20 +169,31 @@ ConstantArrayBuilder::ConstantArraySlice* ConstantArrayBuilder::IndexToSlice(
UNREACHABLE();
}
MaybeHandle<Object> ConstantArrayBuilder::At(size_t index,
Isolate* isolate) const {
template <typename Isolate>
MaybeHandleFor<Isolate, Object> ConstantArrayBuilder::At(
size_t index, Isolate* isolate) const {
const ConstantArraySlice* slice = IndexToSlice(index);
DCHECK_LT(index, slice->capacity());
if (index < slice->start_index() + slice->size()) {
const Entry& entry = slice->At(index);
if (!entry.IsDeferred()) return entry.ToHandle(isolate);
}
return MaybeHandle<Object>();
return MaybeHandleFor<Isolate, Object>();
}
Handle<FixedArray> ConstantArrayBuilder::ToFixedArray(Isolate* isolate) {
Handle<FixedArray> fixed_array = isolate->factory()->NewFixedArrayWithHoles(
static_cast<int>(size()), AllocationType::kOld);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
MaybeHandle<Object> ConstantArrayBuilder::At(size_t index,
Isolate* isolate) const;
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
OffThreadHandle<Object> ConstantArrayBuilder::At(
size_t index, OffThreadIsolate* isolate) const;
template <typename Isolate>
HandleFor<Isolate, FixedArray> ConstantArrayBuilder::ToFixedArray(
Isolate* isolate) {
HandleFor<Isolate, FixedArray> fixed_array =
isolate->factory()->NewFixedArrayWithHoles(static_cast<int>(size()),
AllocationType::kOld);
int array_index = 0;
for (const ConstantArraySlice* slice : idx_slice_) {
DCHECK_EQ(slice->reserved(), 0);
@ -192,7 +206,7 @@ Handle<FixedArray> ConstantArrayBuilder::ToFixedArray(Isolate* isolate) {
#endif
// Copy objects from slice into array.
for (size_t i = 0; i < slice->size(); ++i) {
Handle<Object> value =
HandleFor<Isolate, Object> value =
slice->At(slice->start_index() + i).ToHandle(isolate);
fixed_array->set(array_index++, *value);
}
@ -207,6 +221,12 @@ Handle<FixedArray> ConstantArrayBuilder::ToFixedArray(Isolate* isolate) {
return fixed_array;
}
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<FixedArray> ConstantArrayBuilder::ToFixedArray(Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
OffThreadHandle<FixedArray> ConstantArrayBuilder::ToFixedArray(
OffThreadIsolate* isolate);
size_t ConstantArrayBuilder::Insert(Smi smi) {
auto entry = smi_map_.find(smi);
if (entry == smi_map_.end()) {
@ -306,7 +326,8 @@ size_t ConstantArrayBuilder::InsertJumpTable(size_t size) {
return AllocateIndexArray(Entry::UninitializedJumpTableSmi(), size);
}
void ConstantArrayBuilder::SetDeferredAt(size_t index, Handle<Object> object) {
void ConstantArrayBuilder::SetDeferredAt(
size_t index, HandleOrOffThreadHandle<Object> object) {
ConstantArraySlice* slice = IndexToSlice(index);
return slice->At(index).SetDeferred(object);
}
@ -362,7 +383,9 @@ void ConstantArrayBuilder::DiscardReservedEntry(OperandSize operand_size) {
OperandSizeToSlice(operand_size)->Unreserve();
}
Handle<Object> ConstantArrayBuilder::Entry::ToHandle(Isolate* isolate) const {
template <typename Isolate>
HandleFor<Isolate, Object> ConstantArrayBuilder::Entry::ToHandle(
Isolate* isolate) const {
switch (tag_) {
case Tag::kDeferred:
// We shouldn't have any deferred entries by now.
@ -378,7 +401,8 @@ Handle<Object> ConstantArrayBuilder::Entry::ToHandle(Isolate* isolate) const {
case Tag::kRawString:
return raw_string_->string();
case Tag::kHeapNumber:
return isolate->factory()->NewNumber<AllocationType::kOld>(heap_number_);
return isolate->factory()->template NewNumber<AllocationType::kOld>(
heap_number_);
case Tag::kBigInt:
// This should never fail: the parser will never create a BigInt
// literal that cannot be allocated.
@ -394,6 +418,11 @@ Handle<Object> ConstantArrayBuilder::Entry::ToHandle(Isolate* isolate) const {
UNREACHABLE();
}
template Handle<Object> ConstantArrayBuilder::Entry::ToHandle(
Isolate* isolate) const;
template OffThreadHandle<Object> ConstantArrayBuilder::Entry::ToHandle(
OffThreadIsolate* isolate) const;
} // namespace interpreter
} // namespace internal
} // namespace v8

View File

@ -7,6 +7,7 @@
#include "src/ast/ast-value-factory.h"
#include "src/common/globals.h"
#include "src/handles/handles.h"
#include "src/interpreter/bytecodes.h"
#include "src/objects/smi.h"
#include "src/utils/identity-map.h"
@ -52,12 +53,16 @@ class V8_EXPORT_PRIVATE ConstantArrayBuilder final {
explicit ConstantArrayBuilder(Zone* zone);
// Generate a fixed array of constant handles based on inserted objects.
Handle<FixedArray> ToFixedArray(Isolate* isolate);
template <typename Isolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
HandleFor<Isolate, FixedArray> ToFixedArray(Isolate* isolate);
// Returns the object, as a handle in |isolate|, that is in the constant pool
// array at index |index|. Returns null if there is no handle at this index.
// Only expected to be used in tests.
MaybeHandle<Object> At(size_t index, Isolate* isolate) const;
template <typename Isolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
MaybeHandleFor<Isolate, Object> At(size_t index, Isolate* isolate) const;
// Returns the number of elements in the array.
size_t size() const;
@ -84,7 +89,7 @@ class V8_EXPORT_PRIVATE ConstantArrayBuilder final {
size_t InsertJumpTable(size_t size);
// Sets the deferred value at |index| to |object|.
void SetDeferredAt(size_t index, Handle<Object> object);
void SetDeferredAt(size_t index, HandleOrOffThreadHandle<Object> object);
// Sets the jump table entry at |index| to |smi|. Note that |index| is the
// constant pool index, not the switch case value.
@ -138,7 +143,7 @@ class V8_EXPORT_PRIVATE ConstantArrayBuilder final {
tag_ == Tag::kJumpTableSmi;
}
void SetDeferred(Handle<Object> handle) {
void SetDeferred(HandleOrOffThreadHandle<Object> handle) {
DCHECK_EQ(tag_, Tag::kDeferred);
tag_ = Tag::kHandle;
handle_ = handle;
@ -150,13 +155,14 @@ class V8_EXPORT_PRIVATE ConstantArrayBuilder final {
smi_ = smi;
}
Handle<Object> ToHandle(Isolate* isolate) const;
template <typename Isolate>
HandleFor<Isolate, Object> ToHandle(Isolate* isolate) const;
private:
explicit Entry(Tag tag) : tag_(tag) {}
union {
Handle<Object> handle_;
HandleOrOffThreadHandle<Object> handle_;
Smi smi_;
double heap_number_;
const AstRawString* raw_string_;
@ -199,6 +205,7 @@ class V8_EXPORT_PRIVATE ConstantArrayBuilder final {
const Entry& At(size_t index) const;
#if DEBUG
template <typename Isolate>
void CheckAllElementsAreUnique(Isolate* isolate) const;
#endif

View File

@ -15,10 +15,14 @@ namespace interpreter {
HandlerTableBuilder::HandlerTableBuilder(Zone* zone) : entries_(zone) {}
Handle<ByteArray> HandlerTableBuilder::ToHandlerTable(Isolate* isolate) {
template <typename Isolate>
HandleFor<Isolate, ByteArray> HandlerTableBuilder::ToHandlerTable(
Isolate* isolate) {
int handler_table_size = static_cast<int>(entries_.size());
Handle<ByteArray> table_byte_array = isolate->factory()->NewByteArray(
HandlerTable::LengthForRange(handler_table_size), AllocationType::kOld);
HandleFor<Isolate, ByteArray> table_byte_array =
isolate->factory()->NewByteArray(
HandlerTable::LengthForRange(handler_table_size),
AllocationType::kOld);
HandlerTable table(*table_byte_array);
for (int i = 0; i < handler_table_size; ++i) {
Entry& entry = entries_[i];
@ -31,6 +35,10 @@ Handle<ByteArray> HandlerTableBuilder::ToHandlerTable(Isolate* isolate) {
return table_byte_array;
}
template Handle<ByteArray> HandlerTableBuilder::ToHandlerTable(
Isolate* isolate);
template OffThreadHandle<ByteArray> HandlerTableBuilder::ToHandlerTable(
OffThreadIsolate* isolate);
int HandlerTableBuilder::NewHandlerEntry() {
int handler_id = static_cast<int>(entries_.size());

View File

@ -28,7 +28,8 @@ class V8_EXPORT_PRIVATE HandlerTableBuilder final {
// Builds the actual handler table by copying the current values into a heap
// object. Any further mutations to the builder won't be reflected.
Handle<ByteArray> ToHandlerTable(Isolate* isolate);
template <typename Isolate>
HandleFor<Isolate, ByteArray> ToHandlerTable(Isolate* isolate);
// Creates a new handler table entry and returns a {hander_id} identifying the
// entry, so that it can be referenced by below setter functions.

View File

@ -173,7 +173,7 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() {
#ifdef DEBUG
void InterpreterCompilationJob::CheckAndPrintBytecodeMismatch(
Isolate* isolate, Handle<Script> script, Handle<BytecodeArray> bytecode) {
int first_mismatch = generator()->CheckBytecodeMatches(bytecode);
int first_mismatch = generator()->CheckBytecodeMatches(*bytecode);
if (first_mismatch >= 0) {
parse_info()->ast_value_factory()->Internalize(isolate);
DeclarationScope::AllocateScopeInfos(parse_info(), isolate);
@ -214,7 +214,7 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileIgnitionFinalization");
Handle<BytecodeArray> bytecodes = compilation_info_.bytecode_array();
Handle<BytecodeArray> bytecodes = compilation_info_.bytecode_array<Isolate>();
if (bytecodes.is_null()) {
bytecodes = generator()->FinalizeBytecode(
isolate, handle(Script::cast(shared_info->script()), isolate));

View File

@ -11,7 +11,7 @@
namespace v8 {
namespace internal {
// TODO(leszeks): Possibly add support for logging from off-thread.
// TODO(leszeks): Add support for logging from off-thread.
class OffThreadLogger {
public:
bool is_logging() const { return false; }
@ -19,6 +19,10 @@ class OffThreadLogger {
void ScriptEvent(Logger::ScriptEventType type, int script_id) {
UNREACHABLE();
}
void CodeLinePosInfoRecordEvent(Address code_start,
ByteArray source_position_table) {
UNREACHABLE();
}
};
} // namespace internal

View File

@ -5,6 +5,7 @@
#include "src/objects/literal-objects.h"
#include "src/ast/ast.h"
#include "src/base/logging.h"
#include "src/builtins/accessors.h"
#include "src/execution/isolate.h"
#include "src/heap/factory.h"
@ -567,5 +568,11 @@ Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
return scope.CloseAndEscape(class_boilerplate);
}
OffThreadHandle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
OffThreadIsolate* isolate, ClassLiteral* expr) {
// TODO(leszeks): Add class boilerplate support to off-thread finalization.
UNREACHABLE();
}
} // namespace internal
} // namespace v8

View File

@ -130,6 +130,9 @@ class ClassBoilerplate : public FixedArray {
static Handle<ClassBoilerplate> BuildClassBoilerplate(Isolate* isolate,
ClassLiteral* expr);
static OffThreadHandle<ClassBoilerplate> BuildClassBoilerplate(
OffThreadIsolate* isolate, ClassLiteral* expr);
enum {
kFlagsIndex,
kClassPropertiesTemplateIndex,

View File

@ -4895,7 +4895,8 @@ Object Script::GetNameOrSourceURL() {
return name();
}
MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
template <typename Isolate>
MaybeHandleFor<Isolate, SharedFunctionInfo> Script::FindSharedFunctionInfo(
Isolate* isolate, const FunctionLiteral* fun) {
CHECK_NE(fun->function_literal_id(), kFunctionLiteralIdInvalid);
// If this check fails, the problem is most probably the function id
@ -4907,10 +4908,14 @@ MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
HeapObject heap_object;
if (!shared->GetHeapObject(&heap_object) ||
heap_object.IsUndefined(isolate)) {
return MaybeHandle<SharedFunctionInfo>();
return MaybeHandleFor<Isolate, SharedFunctionInfo>();
}
return handle(SharedFunctionInfo::cast(heap_object), isolate);
}
template MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
Isolate* isolate, const FunctionLiteral* fun);
template OffThreadHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
OffThreadIsolate* isolate, const FunctionLiteral* fun);
Script::Iterator::Iterator(Isolate* isolate)
: iterator_(isolate->heap()->script_list()) {}

View File

@ -195,7 +195,8 @@ class Script : public Struct {
// Look through the list of existing shared function infos to find one
// that matches the function literal. Return empty handle if not found.
MaybeHandle<SharedFunctionInfo> FindSharedFunctionInfo(
template <typename Isolate>
MaybeHandleFor<Isolate, SharedFunctionInfo> FindSharedFunctionInfo(
Isolate* isolate, const FunctionLiteral* fun);
// Iterate over all script objects on the heap.

View File

@ -120,6 +120,14 @@ class FunctionTemplateInfo
static Handle<SharedFunctionInfo> GetOrCreateSharedFunctionInfo(
Isolate* isolate, Handle<FunctionTemplateInfo> info,
MaybeHandle<Name> maybe_name);
static OffThreadHandle<SharedFunctionInfo> GetOrCreateSharedFunctionInfo(
OffThreadIsolate* isolate, Handle<FunctionTemplateInfo> info,
Handle<Name> maybe_name) {
// We don't support streaming compilation of scripts with natives, so we
// don't need an off-thread implementation of this.
UNREACHABLE();
}
// Returns parent function template or a null FunctionTemplateInfo.
inline FunctionTemplateInfo GetParent(Isolate* isolate);
// Returns true if |object| is an instance of this function template.