[offthread] Change OffThreadIsolate to LocalIsolate

This patch introduces a new LocalIsolate and LocalFactory, which use
LocalHeap and replace OffThreadIsolate and OffThreadFactory. This allows
us to remove those classes, as well as the related OffThreadSpace,
OffThreadLargeObjectSpace, OffThreadHeap, and OffThreadTransferHandle.
OffThreadLogger becomes LocalLogger.

LocalHeap behaves more like Heap than OffThreadHeap did, so this allows
us to additionally remove the concept of "Finish" and "Publish" that the
OffThreadIsolate had, and allows us to internalize strings directly with
the newly-concurrent string table (where the implementation can now move
to FactoryBase).

This patch also removes the off-thread support from the deserializer
entirely, as well as removing the LocalIsolateWrapper which allowed
run-time distinction between Isolate and OffThreadIsolate. LocalHeap
doesn't support the reservation model used by the deserializer, and we
will likely move the deserializer to use LocalIsolate unconditionally
once we figure out the details of how to do this.

Bug: chromium:1011762

Change-Id: I1a1a0a72952b19a8a4c167c11a863c153a1252fc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2315990
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69397}
This commit is contained in:
Leszek Swirski 2020-08-13 14:12:17 +02:00 committed by Commit Bot
parent 4d58cf7642
commit f1589bbe11
106 changed files with 961 additions and 2495 deletions

View File

@ -2448,13 +2448,13 @@ v8_source_set("v8_base_without_compiler") {
"src/execution/isolate-utils.h",
"src/execution/isolate.cc",
"src/execution/isolate.h",
"src/execution/local-isolate-inl.h",
"src/execution/local-isolate.cc",
"src/execution/local-isolate.h",
"src/execution/messages.cc",
"src/execution/messages.h",
"src/execution/microtask-queue.cc",
"src/execution/microtask-queue.h",
"src/execution/off-thread-isolate-inl.h",
"src/execution/off-thread-isolate.cc",
"src/execution/off-thread-isolate.h",
"src/execution/pointer-authentication.h",
"src/execution/protectors-inl.h",
"src/execution/protectors.cc",
@ -2566,6 +2566,8 @@ v8_source_set("v8_base_without_compiler") {
"src/heap/list.h",
"src/heap/local-allocator-inl.h",
"src/heap/local-allocator.h",
"src/heap/local-factory.cc",
"src/heap/local-factory.h",
"src/heap/local-heap-inl.h",
"src/heap/local-heap.cc",
"src/heap/local-heap.h",
@ -2601,10 +2603,6 @@ v8_source_set("v8_base_without_compiler") {
"src/heap/objects-visiting-inl.h",
"src/heap/objects-visiting.cc",
"src/heap/objects-visiting.h",
"src/heap/off-thread-factory.cc",
"src/heap/off-thread-factory.h",
"src/heap/off-thread-heap.cc",
"src/heap/off-thread-heap.h",
"src/heap/paged-spaces-inl.h",
"src/heap/paged-spaces.cc",
"src/heap/paged-spaces.h",
@ -2712,6 +2710,7 @@ v8_source_set("v8_base_without_compiler") {
"src/logging/counters-inl.h",
"src/logging/counters.cc",
"src/logging/counters.h",
"src/logging/local-logger.h",
"src/logging/log-inl.h",
"src/logging/log-utils.cc",
"src/logging/log-utils.h",
@ -2719,7 +2718,6 @@ v8_source_set("v8_base_without_compiler") {
"src/logging/log.h",
"src/logging/metrics.cc",
"src/logging/metrics.h",
"src/logging/off-thread-logger.h",
"src/logging/tracing-flags.cc",
"src/logging/tracing-flags.h",
"src/numbers/bignum-dtoa.cc",

View File

@ -18,14 +18,13 @@ include_rules = [
"+src/heap/heap-inl.h",
"+src/heap/heap-write-barrier-inl.h",
"+src/heap/heap-write-barrier.h",
"+src/heap/local-factory-inl.h",
"+src/heap/local-factory.h",
"+src/heap/local-heap.h",
"+src/heap/local-heap-inl.h",
# TODO(v8:10496): Don't expose memory chunk outside of heap/.
"+src/heap/memory-chunk.h",
"+src/heap/memory-chunk-inl.h",
"+src/heap/off-thread-factory-inl.h",
"+src/heap/off-thread-factory.h",
"+src/heap/off-thread-heap.h",
"+src/heap/read-only-heap-inl.h",
"+src/heap/read-only-heap.h",
"+src/heap/safepoint.h",

View File

@ -201,7 +201,7 @@ class AsmJsCompilationJob final : public UnoptimizedCompilationJob {
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
OffThreadIsolate* isolate) final {
LocalIsolate* isolate) final {
return CompilationJob::RETRY_ON_MAIN_THREAD;
}

View File

@ -29,9 +29,8 @@
#include "src/base/logging.h"
#include "src/common/globals.h"
#include "src/execution/off-thread-isolate.h"
#include "src/heap/factory-inl.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/strings/char-predicates-inl.h"
@ -46,8 +45,8 @@ namespace {
// For using StringToIndex.
class OneByteStringStream {
public:
explicit OneByteStringStream(Vector<const byte> lb) :
literal_bytes_(lb), pos_(0) {}
explicit OneByteStringStream(Vector<const byte> lb)
: literal_bytes_(lb), pos_(0) {}
bool HasMore() { return pos_ < literal_bytes_.length(); }
uint16_t GetNext() { return literal_bytes_[pos_++]; }
@ -59,7 +58,8 @@ class OneByteStringStream {
} // namespace
void AstRawString::Internalize(Isolate* isolate) {
template <typename LocalIsolate>
void AstRawString::Internalize(LocalIsolate* isolate) {
DCHECK(!has_string_);
if (literal_bytes_.length() == 0) {
set_string(isolate->factory()->empty_string());
@ -73,27 +73,10 @@ void AstRawString::Internalize(Isolate* isolate) {
}
}
void AstRawString::Internalize(OffThreadIsolate* isolate) {
DCHECK(!has_string_);
if (literal_bytes_.length() == 0) {
set_string(isolate->factory()->empty_string());
return;
}
// For the off-thread case, we already de-duplicated the AstRawStrings during
// construction and don't have access to the main thread string table yet, so
// we just unconditionally create strings and will internalize them properly
// during merging.
Handle<SeqString> string;
if (is_one_byte()) {
string = isolate->factory()->NewOneByteInternalizedString(
Vector<const uint8_t>::cast(literal_bytes_), hash_field());
} else {
string = isolate->factory()->NewTwoByteInternalizedString(
Vector<const uc16>::cast(literal_bytes_), hash_field());
}
set_string(string);
}
template EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) void AstRawString::Internalize(Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) void AstRawString::Internalize(LocalIsolate* isolate);
bool AstRawString::AsArrayIndex(uint32_t* index) const {
// The StringHasher will set up the hash. Bail out early if we know it
@ -185,8 +168,8 @@ Handle<String> AstConsString::Allocate(LocalIsolate* isolate) const {
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> AstConsString::Allocate<Isolate>(Isolate* isolate) const;
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> AstConsString::Allocate<OffThreadIsolate>(
OffThreadIsolate* isolate) const;
Handle<String> AstConsString::Allocate<LocalIsolate>(
LocalIsolate* isolate) const;
template <typename LocalIsolate>
Handle<String> AstConsString::AllocateFlat(LocalIsolate* isolate) const {
@ -246,8 +229,8 @@ Handle<String> AstConsString::AllocateFlat(LocalIsolate* isolate) const {
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> AstConsString::AllocateFlat<Isolate>(Isolate* isolate) const;
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> AstConsString::AllocateFlat<OffThreadIsolate>(
OffThreadIsolate* isolate) const;
Handle<String> AstConsString::AllocateFlat<LocalIsolate>(
LocalIsolate* isolate) const;
std::forward_list<const AstRawString*> AstConsString::ToRawStrings() const {
std::forward_list<const AstRawString*> result;
@ -361,10 +344,9 @@ void AstValueFactory::Internalize(LocalIsolate* isolate) {
zone_ = nullptr;
}
template EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) void AstValueFactory::Internalize<Isolate>(Isolate*
isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void AstValueFactory::
Internalize<OffThreadIsolate>(OffThreadIsolate* isolate);
V8_EXPORT_PRIVATE) void AstValueFactory::Internalize(Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) void AstValueFactory::Internalize(LocalIsolate* isolate);
AstRawString* AstValueFactory::GetString(uint32_t hash_field, bool is_one_byte,
Vector<const byte> literal_bytes) {

View File

@ -45,7 +45,6 @@ namespace v8 {
namespace internal {
class Isolate;
class OffThreadIsolate;
class AstRawString final : public ZoneObject {
public:
@ -59,8 +58,8 @@ class AstRawString final : public ZoneObject {
V8_EXPORT_PRIVATE bool IsOneByteEqualTo(const char* data) const;
uint16_t FirstCharacter() const;
void Internalize(Isolate* isolate);
void Internalize(OffThreadIsolate* isolate);
template <typename LocalIsolate>
void Internalize(LocalIsolate* isolate);
// Access the physical representation:
bool is_one_byte() const { return is_one_byte_; }
@ -127,6 +126,11 @@ class AstRawString final : public ZoneObject {
#endif
};
extern template EXPORT_TEMPLATE_DECLARE(
V8_EXPORT_PRIVATE) void AstRawString::Internalize(Isolate* isolate);
extern template EXPORT_TEMPLATE_DECLARE(
V8_EXPORT_PRIVATE) void AstRawString::Internalize(LocalIsolate* isolate);
class AstConsString final : public ZoneObject {
public:
AstConsString* AddString(Zone* zone, const AstRawString* s) {
@ -381,7 +385,7 @@ extern template EXPORT_TEMPLATE_DECLARE(
extern template EXPORT_TEMPLATE_DECLARE(
V8_EXPORT_PRIVATE) void AstValueFactory::
Internalize<OffThreadIsolate>(OffThreadIsolate* isolate);
Internalize<LocalIsolate>(LocalIsolate* isolate);
} // namespace internal
} // namespace v8

View File

@ -14,8 +14,7 @@
#include "src/builtins/builtins-constructor.h"
#include "src/builtins/builtins.h"
#include "src/common/assert-scope.h"
#include "src/execution/off-thread-isolate.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/numbers/conversions-inl.h"
#include "src/numbers/double.h"
#include "src/objects/contexts.h"
@ -521,7 +520,7 @@ void ObjectLiteral::BuildBoilerplateDescription(LocalIsolate* isolate) {
template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) void ObjectLiteral::
BuildBoilerplateDescription(Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) void ObjectLiteral::
BuildBoilerplateDescription(OffThreadIsolate* isolate);
BuildBoilerplateDescription(LocalIsolate* isolate);
bool ObjectLiteral::IsFastCloningSupported() const {
// The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
@ -695,8 +694,9 @@ void ArrayLiteral::BuildBoilerplateDescription(LocalIsolate* isolate) {
template EXPORT_TEMPLATE_DEFINE(
V8_BASE_EXPORT) void ArrayLiteral::BuildBoilerplateDescription(Isolate*
isolate);
template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) void ArrayLiteral::
BuildBoilerplateDescription(OffThreadIsolate* isolate);
template EXPORT_TEMPLATE_DEFINE(
V8_BASE_EXPORT) void ArrayLiteral::BuildBoilerplateDescription(LocalIsolate*
isolate);
bool ArrayLiteral::IsFastCloningSupported() const {
return depth() <= 1 &&
@ -736,7 +736,7 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Expression* expression, Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<Object> MaterializedLiteral::GetBoilerplateValue(
Expression* expression, OffThreadIsolate* isolate);
Expression* expression, LocalIsolate* isolate);
int MaterializedLiteral::InitDepthAndFlags() {
if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
@ -771,7 +771,7 @@ void MaterializedLiteral::BuildConstants(LocalIsolate* isolate) {
template EXPORT_TEMPLATE_DEFINE(
V8_BASE_EXPORT) void MaterializedLiteral::BuildConstants(Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(
V8_BASE_EXPORT) void MaterializedLiteral::BuildConstants(OffThreadIsolate*
V8_BASE_EXPORT) void MaterializedLiteral::BuildConstants(LocalIsolate*
isolate);
template <typename LocalIsolate>
@ -813,7 +813,7 @@ template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT)
Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT)
Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
// Add is not commutative due to potential for string addition.
@ -1006,7 +1006,7 @@ Handle<Object> Literal::BuildValue(LocalIsolate* isolate) const {
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<Object> Literal::BuildValue(Isolate* isolate) const;
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<Object> Literal::BuildValue(OffThreadIsolate* isolate) const;
Handle<Object> Literal::BuildValue(LocalIsolate* isolate) const;
bool Literal::ToBooleanIsTrue() const {
switch (type()) {

View File

@ -117,7 +117,6 @@ namespace internal {
// Forward declarations
class Isolate;
class OffThreadIsolate;
class AstNode;
class AstNodeFactory;
@ -2186,7 +2185,7 @@ class FunctionLiteral final : public Expression {
}
UNREACHABLE();
}
Handle<String> GetInferredName(OffThreadIsolate* isolate) const {
Handle<String> GetInferredName(LocalIsolate* isolate) const {
DCHECK(inferred_name_.is_null());
DCHECK_NOT_NULL(raw_inferred_name_);
return raw_inferred_name_->GetString(isolate);

View File

@ -3,9 +3,10 @@
// found in the LICENSE file.
#include "src/ast/modules.h"
#include "src/ast/ast-value-factory.h"
#include "src/ast/scopes.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/objects-inl.h"
#include "src/parsing/pending-compilation-error-handler.h"
@ -106,7 +107,7 @@ Handle<SourceTextModuleInfoEntry> SourceTextModuleDescriptor::Entry::Serialize(
template Handle<SourceTextModuleInfoEntry>
SourceTextModuleDescriptor::Entry::Serialize(Isolate* isolate) const;
template Handle<SourceTextModuleInfoEntry>
SourceTextModuleDescriptor::Entry::Serialize(OffThreadIsolate* isolate) const;
SourceTextModuleDescriptor::Entry::Serialize(LocalIsolate* isolate) const;
template <typename LocalIsolate>
Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
@ -164,7 +165,7 @@ Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
template Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
Isolate* isolate, Zone* zone) const;
template Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
OffThreadIsolate* isolate, Zone* zone) const;
LocalIsolate* isolate, Zone* zone) const;
void SourceTextModuleDescriptor::MakeIndirectExportsExplicit(Zone* zone) {
for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {

View File

@ -11,7 +11,7 @@
#include "src/base/optional.h"
#include "src/builtins/accessors.h"
#include "src/common/message-template.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/init/bootstrapper.h"
#include "src/logging/counters.h"
#include "src/objects/module-inl.h"
@ -2477,8 +2477,8 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope::
AllocateScopeInfosRecursively<Isolate>(Isolate* isolate,
MaybeHandle<ScopeInfo> outer_scope);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope::
AllocateScopeInfosRecursively<OffThreadIsolate>(
OffThreadIsolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
AllocateScopeInfosRecursively<LocalIsolate>(
LocalIsolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
void DeclarationScope::RecalcPrivateNameContextChain() {
// The outermost scope in a class heritage expression is marked to skip the
@ -2557,10 +2557,10 @@ void DeclarationScope::AllocateScopeInfos(ParseInfo* info,
}
}
template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos<Isolate>(
template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos(
ParseInfo* info, Isolate* isolate);
template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos<
OffThreadIsolate>(ParseInfo* info, OffThreadIsolate* isolate);
template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos(
ParseInfo* info, LocalIsolate* isolate);
int Scope::ContextLocalCount() const {
if (num_heap_slots() == 0) return 0;

View File

@ -30,12 +30,12 @@
#include "src/execution/frames-inl.h"
#include "src/execution/isolate-inl.h"
#include "src/execution/isolate.h"
#include "src/execution/off-thread-isolate.h"
#include "src/execution/runtime-profiler.h"
#include "src/execution/vm-state-inl.h"
#include "src/handles/maybe-handles.h"
#include "src/heap/heap-inl.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/heap/local-heap-inl.h"
#include "src/init/bootstrapper.h"
#include "src/interpreter/interpreter.h"
#include "src/logging/log-inl.h"
@ -253,9 +253,7 @@ CompilationJob::Status UnoptimizedCompilationJob::FinalizeJob(
}
CompilationJob::Status UnoptimizedCompilationJob::FinalizeJob(
Handle<SharedFunctionInfo> shared_info, OffThreadIsolate* isolate) {
DisallowHeapAccess no_heap_access;
Handle<SharedFunctionInfo> shared_info, LocalIsolate* isolate) {
// Delegate to the underlying implementation.
DCHECK_EQ(state(), State::kReadyToFinalize);
ScopedTimer t(&time_taken_to_finalize_);
@ -502,7 +500,7 @@ void InstallCoverageInfo(Isolate* isolate, Handle<SharedFunctionInfo> shared,
isolate->debug()->InstallCoverageInfo(shared, coverage_info);
}
void InstallCoverageInfo(OffThreadIsolate* isolate,
void InstallCoverageInfo(LocalIsolate* isolate,
Handle<SharedFunctionInfo> shared,
Handle<CoverageInfo> coverage_info) {
// We should only have coverage info when finalizing on the main thread.
@ -620,7 +618,7 @@ CompilationJob::Status FinalizeSingleUnoptimizedCompilationJob(
job->time_taken_to_finalize());
}
DCHECK_IMPLIES(status == CompilationJob::RETRY_ON_MAIN_THREAD,
(std::is_same<LocalIsolate, OffThreadIsolate>::value));
(std::is_same<LocalIsolate, LocalIsolate>::value));
return status;
}
@ -1284,12 +1282,11 @@ RuntimeCallCounterId RuntimeCallCounterIdForCompileBackground(
MaybeHandle<SharedFunctionInfo> CompileAndFinalizeOnBackgroundThread(
ParseInfo* parse_info, AccountingAllocator* allocator,
Handle<Script> script, OffThreadIsolate* isolate,
Handle<Script> script, LocalIsolate* isolate,
FinalizeUnoptimizedCompilationDataList*
finalize_unoptimized_compilation_data_list,
DeferredFinalizationJobDataList*
jobs_to_retry_finalization_on_main_thread) {
DisallowHeapAccess no_heap_access;
DeferredFinalizationJobDataList* jobs_to_retry_finalization_on_main_thread,
IsCompiledScope* is_compiled_scope) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileCodeBackground");
RuntimeCallTimerScope runtimeTimer(
@ -1299,13 +1296,9 @@ MaybeHandle<SharedFunctionInfo> CompileAndFinalizeOnBackgroundThread(
Handle<SharedFunctionInfo> shared_info =
CreateTopLevelSharedFunctionInfo(parse_info, script, isolate);
// TODO(leszeks): Consider persisting the is_compiled_scope across the
// off-thread publish.
IsCompiledScope is_compiled_scope;
if (!IterativelyExecuteAndFinalizeUnoptimizedCompilationJobs(
isolate, shared_info, script, parse_info, allocator,
&is_compiled_scope, finalize_unoptimized_compilation_data_list,
is_compiled_scope, finalize_unoptimized_compilation_data_list,
jobs_to_retry_finalization_on_main_thread)) {
return kNullMaybeHandle;
}
@ -1353,6 +1346,20 @@ CompilationHandleScope::~CompilationHandleScope() {
info_->set_persistent_handles(persistent_.Detach());
}
FinalizeUnoptimizedCompilationData::FinalizeUnoptimizedCompilationData(
LocalIsolate* isolate, Handle<SharedFunctionInfo> function_handle,
base::TimeDelta time_taken_to_execute,
base::TimeDelta time_taken_to_finalize)
: time_taken_to_execute_(time_taken_to_execute),
time_taken_to_finalize_(time_taken_to_finalize),
function_handle_(isolate->heap()->NewPersistentHandle(function_handle)) {}
DeferredFinalizationJobData::DeferredFinalizationJobData(
LocalIsolate* isolate, Handle<SharedFunctionInfo> function_handle,
std::unique_ptr<UnoptimizedCompilationJob> job)
: function_handle_(isolate->heap()->NewPersistentHandle(function_handle)),
job_(std::move(job)) {}
BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
Isolate* isolate)
: flags_(UnoptimizedCompileFlags::ForToplevelCompile(
@ -1360,6 +1367,7 @@ BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
REPLMode::kNo)),
compile_state_(isolate),
info_(std::make_unique<ParseInfo>(isolate, flags_, &compile_state_)),
isolate_for_local_isolate_(nullptr),
start_position_(0),
end_position_(0),
function_literal_id_(kFunctionLiteralIdTopLevel),
@ -1384,8 +1392,7 @@ BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
finalize_on_background_thread_ =
FLAG_finalize_streaming_on_background && !flags_.block_coverage_enabled();
if (finalize_on_background_thread()) {
off_thread_isolate_ =
std::make_unique<OffThreadIsolate>(isolate, info_->zone());
isolate_for_local_isolate_ = isolate;
}
}
@ -1399,6 +1406,7 @@ BackgroundCompileTask::BackgroundCompileTask(
compile_state_(*outer_parse_info->state()),
info_(ParseInfo::ForToplevelFunction(flags_, &compile_state_,
function_literal, function_name)),
isolate_for_local_isolate_(nullptr),
start_position_(function_literal->start_position()),
end_position_(function_literal->end_position()),
function_literal_id_(function_literal->function_literal_id()),
@ -1465,10 +1473,6 @@ class OffThreadParseInfoScope {
} // namespace
void BackgroundCompileTask::Run() {
DisallowHeapAllocation no_allocation;
DisallowHandleAllocation no_handles;
DisallowHeapAccess no_heap_access;
TimedHistogramScope timer(timer_);
base::Optional<OffThreadParseInfoScope> off_thread_scope(
base::in_place, info_.get(), worker_thread_runtime_call_stats_,
@ -1502,40 +1506,35 @@ void BackgroundCompileTask::Run() {
} else {
DCHECK(info_->flags().is_toplevel());
OffThreadIsolate* isolate = off_thread_isolate();
isolate->PinToCurrentThread();
LocalIsolate isolate(isolate_for_local_isolate_);
LocalHandleScope handle_scope(&isolate);
OffThreadHandleScope handle_scope(isolate);
info_->ast_value_factory()->Internalize(isolate);
info_->ast_value_factory()->Internalize(&isolate);
// We don't have the script source, origin, or details yet, so use default
// values for them. These will be fixed up during the main-thread merge.
Handle<Script> script =
info_->CreateScript(isolate, isolate->factory()->empty_string(),
info_->CreateScript(&isolate, isolate.factory()->empty_string(),
kNullMaybeHandle, ScriptOriginOptions());
parser_->HandleSourceURLComments(isolate, script);
parser_->HandleSourceURLComments(&isolate, script);
MaybeHandle<SharedFunctionInfo> maybe_result;
if (info_->literal() != nullptr) {
maybe_result = CompileAndFinalizeOnBackgroundThread(
info_.get(), compile_state_.allocator(), script, isolate,
info_.get(), compile_state_.allocator(), script, &isolate,
&finalize_unoptimized_compilation_data_,
&jobs_to_retry_finalization_on_main_thread_);
&jobs_to_retry_finalization_on_main_thread_, &is_compiled_scope_);
} else {
DCHECK(compile_state_.pending_error_handler()->has_pending_error());
PreparePendingException(isolate, info_.get());
PreparePendingException(&isolate, info_.get());
}
outer_function_sfi_ = isolate->TransferHandle(maybe_result);
script_ = isolate->TransferHandle(script);
outer_function_sfi_ =
isolate.heap()->NewPersistentMaybeHandle(maybe_result);
script_ = isolate.heap()->NewPersistentHandle(script);
{
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.FinalizeCodeBackground.Finish");
isolate->FinishOffThread();
}
persistent_handles_ = isolate.heap()->DetachPersistentHandles();
{
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
@ -1548,6 +1547,25 @@ void BackgroundCompileTask::Run() {
}
}
MaybeHandle<SharedFunctionInfo> BackgroundCompileTask::GetOuterFunctionSfi(
Isolate* isolate) {
// outer_function_sfi_ is a persistent Handle, tied to the lifetime of the
// persistent_handles_ member, so create a new Handle to let it outlive
// the BackgroundCompileTask.
Handle<SharedFunctionInfo> result;
if (outer_function_sfi_.ToHandle(&result)) {
return handle(*result, isolate);
}
return kNullMaybeHandle;
}
Handle<Script> BackgroundCompileTask::GetScript(Isolate* isolate) {
// script_ is a persistent Handle, tied to the lifetime of the
// persistent_handles_ member, so create a new Handle to let it outlive
// the BackgroundCompileTask.
return handle(*script_, isolate);
}
// ----------------------------------------------------------------------------
// Implementation of Compiler
@ -2500,6 +2518,9 @@ MaybeHandle<SharedFunctionInfo> CompileScriptOnBothBackgroundAndMainThread(
Handle<SharedFunctionInfo> result;
if (maybe_result.ToHandle(&result)) {
// The BackgroundCompileTask's IsCompiledScope will keep the result alive
// until it dies at the end of this function, after which this new
// IsCompiledScope can take over.
*is_compiled_scope = result->is_compiled_scope(isolate);
}
@ -2751,9 +2772,7 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.OffThreadFinalization.Publish");
task->off_thread_isolate()->Publish(isolate);
script = task->script();
script = task->GetScript(isolate);
// We might not have been able to finalize all jobs on the background
// thread (e.g. asm.js jobs), so finalize those deferred jobs now.
@ -2762,11 +2781,17 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
task->jobs_to_retry_finalization_on_main_thread(),
task->compile_state()->pending_error_handler(),
task->finalize_unoptimized_compilation_data())) {
maybe_result = task->outer_function_sfi();
maybe_result = task->GetOuterFunctionSfi(isolate);
}
script->set_source(*source);
script->set_origin_options(origin_options);
// The one post-hoc fix-up: Add the script to the script list.
Handle<WeakArrayList> scripts = isolate->factory()->script_list();
scripts = WeakArrayList::Append(isolate, scripts,
MaybeObjectHandle::Weak(script));
isolate->heap()->SetRootScriptList(*scripts);
} else {
ParseInfo* parse_info = task->info();
DCHECK(parse_info->flags().is_toplevel());
@ -2880,7 +2905,7 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
template Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
FunctionLiteral* literal, Handle<Script> script, Isolate* isolate);
template Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
FunctionLiteral* literal, Handle<Script> script, OffThreadIsolate* isolate);
FunctionLiteral* literal, Handle<Script> script, LocalIsolate* isolate);
// static
MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,

View File

@ -12,7 +12,7 @@
#include "src/codegen/bailout-reason.h"
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/execution/off-thread-isolate.h"
#include "src/execution/local-isolate.h"
#include "src/handles/persistent-handles.h"
#include "src/logging/code-events.h"
#include "src/objects/contexts.h"
@ -270,8 +270,8 @@ class UnoptimizedCompilationJob : public CompilationJob {
// Finalizes the compile job. Can be called on a background thread, and might
// return RETRY_ON_MAIN_THREAD if the finalization can't be run on the
// background thread, and should instead be retried on the foreground thread.
V8_WARN_UNUSED_RESULT Status FinalizeJob(
Handle<SharedFunctionInfo> shared_info, OffThreadIsolate* isolate);
V8_WARN_UNUSED_RESULT Status
FinalizeJob(Handle<SharedFunctionInfo> shared_info, LocalIsolate* isolate);
void RecordCompilationStats(Isolate* isolate) const;
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
@ -303,7 +303,7 @@ class UnoptimizedCompilationJob : public CompilationJob {
virtual Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) = 0;
virtual Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
OffThreadIsolate* isolate) = 0;
LocalIsolate* isolate) = 0;
private:
uintptr_t stack_limit_;
@ -380,25 +380,15 @@ class FinalizeUnoptimizedCompilationData {
base::TimeDelta time_taken_to_finalize)
: time_taken_to_execute_(time_taken_to_execute),
time_taken_to_finalize_(time_taken_to_finalize),
function_handle_(function_handle),
handle_state_(kHandle) {}
function_handle_(function_handle) {}
FinalizeUnoptimizedCompilationData(OffThreadIsolate* isolate,
FinalizeUnoptimizedCompilationData(LocalIsolate* isolate,
Handle<SharedFunctionInfo> function_handle,
base::TimeDelta time_taken_to_execute,
base::TimeDelta time_taken_to_finalize)
: time_taken_to_execute_(time_taken_to_execute),
time_taken_to_finalize_(time_taken_to_finalize),
function_transfer_handle_(isolate->TransferHandle(function_handle)),
handle_state_(kTransferHandle) {}
base::TimeDelta time_taken_to_finalize);
Handle<SharedFunctionInfo> function_handle() const {
switch (handle_state_) {
case kHandle:
return function_handle_;
case kTransferHandle:
return function_transfer_handle_.ToHandle();
}
return function_handle_;
}
base::TimeDelta time_taken_to_execute() const {
@ -411,11 +401,7 @@ class FinalizeUnoptimizedCompilationData {
private:
base::TimeDelta time_taken_to_execute_;
base::TimeDelta time_taken_to_finalize_;
union {
Handle<SharedFunctionInfo> function_handle_;
OffThreadTransferHandle<SharedFunctionInfo> function_transfer_handle_;
};
enum { kHandle, kTransferHandle } handle_state_;
Handle<SharedFunctionInfo> function_handle_;
};
using FinalizeUnoptimizedCompilationDataList =
@ -428,20 +414,18 @@ class DeferredFinalizationJobData {
std::unique_ptr<UnoptimizedCompilationJob> job) {
UNREACHABLE();
}
DeferredFinalizationJobData(OffThreadIsolate* isolate,
DeferredFinalizationJobData(LocalIsolate* isolate,
Handle<SharedFunctionInfo> function_handle,
std::unique_ptr<UnoptimizedCompilationJob> job)
: function_transfer_handle_(isolate->TransferHandle(function_handle)),
job_(std::move(job)) {}
std::unique_ptr<UnoptimizedCompilationJob> job);
Handle<SharedFunctionInfo> function_handle() const {
return function_transfer_handle_.ToHandle();
return function_handle_;
}
UnoptimizedCompilationJob* job() const { return job_.get(); }
private:
OffThreadTransferHandle<SharedFunctionInfo> function_transfer_handle_;
Handle<SharedFunctionInfo> function_handle_;
std::unique_ptr<UnoptimizedCompilationJob> job_;
};
@ -497,15 +481,6 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
bool finalize_on_background_thread() {
return finalize_on_background_thread_;
}
OffThreadIsolate* off_thread_isolate() { return off_thread_isolate_.get(); }
MaybeHandle<SharedFunctionInfo> outer_function_sfi() {
DCHECK_NOT_NULL(off_thread_isolate_);
return outer_function_sfi_.ToHandle();
}
Handle<Script> script() {
DCHECK_NOT_NULL(off_thread_isolate_);
return script_.ToHandle();
}
FinalizeUnoptimizedCompilationDataList*
finalize_unoptimized_compilation_data() {
return &finalize_unoptimized_compilation_data_;
@ -517,6 +492,11 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
return &jobs_to_retry_finalization_on_main_thread_;
}
// Getters for the off-thread finalization results, that create main-thread
// handles to the objects.
MaybeHandle<SharedFunctionInfo> GetOuterFunctionSfi(Isolate* isolate);
Handle<Script> GetScript(Isolate* isolate);
private:
// Data needed for parsing, and data needed to to be passed between thread
// between parsing and compilation. These need to be initialized before the
@ -533,9 +513,11 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
// 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_;
OffThreadTransferMaybeHandle<SharedFunctionInfo> outer_function_sfi_;
OffThreadTransferHandle<Script> script_;
Isolate* isolate_for_local_isolate_;
std::unique_ptr<PersistentHandles> persistent_handles_;
MaybeHandle<SharedFunctionInfo> outer_function_sfi_;
Handle<Script> script_;
IsCompiledScope is_compiled_scope_;
FinalizeUnoptimizedCompilationDataList finalize_unoptimized_compilation_data_;
DeferredFinalizationJobDataList jobs_to_retry_finalization_on_main_thread_;

View File

@ -5,7 +5,7 @@
#include "src/codegen/source-position-table.h"
#include "src/base/export-template.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
@ -189,7 +189,7 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
OwnedVector<byte> SourcePositionTableBuilder::ToSourcePositionTableVector() {
if (bytes_.empty()) return OwnedVector<byte>();

View File

@ -655,6 +655,7 @@ class JSReceiver;
class JSArray;
class JSFunction;
class JSObject;
class LocalIsolate;
class MacroAssembler;
class Map;
class MapSpace;
@ -672,7 +673,6 @@ class NewSpace;
class NewLargeObjectSpace;
class NumberDictionary;
class Object;
class OffThreadIsolate;
class OldLargeObjectSpace;
template <HeapObjectReferenceType kRefType, typename StorageType>
class TaggedImpl;
@ -816,7 +816,6 @@ enum GarbageCollector { SCAVENGER, MARK_COMPACTOR, MINOR_MARK_COMPACTOR };
enum class LocalSpaceKind {
kNone,
kOffThreadSpace,
kCompactionSpaceForScavenge,
kCompactionSpaceForMarkCompact,
kCompactionSpaceForMinorMarkCompact,

View File

@ -8,7 +8,6 @@
#include "include/v8-internal.h"
#include "src/common/ptr-compr.h"
#include "src/execution/isolate.h"
#include "src/execution/off-thread-isolate-inl.h"
namespace v8 {
namespace internal {
@ -37,15 +36,6 @@ V8_INLINE Address GetIsolateRoot(const Isolate* isolate) {
return isolate_root;
}
V8_INLINE Address GetIsolateRoot(const OffThreadIsolate* isolate) {
Address isolate_root = isolate->isolate_root();
#ifdef V8_COMPRESS_POINTERS
isolate_root = reinterpret_cast<Address>(V8_ASSUME_ALIGNED(
reinterpret_cast<void*>(isolate_root), kPtrComprIsolateRootAlignment));
#endif
return isolate_root;
}
// Decompresses smi value.
V8_INLINE Address DecompressTaggedSigned(Tagged_t raw_value) {
// For runtime code the upper 32-bits of the Smi value do not matter.

View File

@ -810,12 +810,12 @@ void JSFunction::JSFunctionVerify(Isolate* isolate) {
}
void SharedFunctionInfo::SharedFunctionInfoVerify(Isolate* isolate) {
// TODO(leszeks): Add a TorqueGeneratedClassVerifier for OffThreadIsolate.
// TODO(leszeks): Add a TorqueGeneratedClassVerifier for LocalIsolate.
TorqueGeneratedClassVerifiers::SharedFunctionInfoVerify(*this, isolate);
this->SharedFunctionInfoVerify(ReadOnlyRoots(isolate));
}
void SharedFunctionInfo::SharedFunctionInfoVerify(OffThreadIsolate* isolate) {
void SharedFunctionInfo::SharedFunctionInfoVerify(LocalIsolate* isolate) {
this->SharedFunctionInfoVerify(ReadOnlyRoots(isolate));
}

View File

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/objects/objects.h"
#include <iomanip>
#include <memory>
@ -27,6 +25,7 @@
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/snapshot/embedded/embedded-data.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-break-iterator-inl.h"
@ -1370,11 +1369,7 @@ void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) { // NOLINT
os << "\n - language_mode: " << language_mode();
os << "\n - data: " << Brief(function_data());
os << "\n - code (from data): ";
if (Heap::InOffThreadSpace(*this)) {
os << "<not available off-thread>";
} else {
os << Brief(GetCode());
}
PrintSourceCode(os);
// Script files are often large, thus only print their {Brief} representation.
os << "\n - script: " << Brief(script());

View File

@ -8,7 +8,6 @@
#include "src/common/ptr-compr-inl.h"
#include "src/execution/isolate-utils.h"
#include "src/execution/isolate.h"
#include "src/execution/local-isolate-wrapper.h"
#include "src/heap/heap-write-barrier-inl.h"
namespace v8 {
@ -34,7 +33,7 @@ inline const Isolate* GetIsolateForPtrCompr(const Isolate* isolate) {
#endif // V8_COMPRESS_POINTERS
}
inline const Isolate* GetIsolateForPtrCompr(const OffThreadIsolate* isolate) {
inline const Isolate* GetIsolateForPtrCompr(const LocalIsolate* isolate) {
#ifdef V8_COMPRESS_POINTERS
return isolate->GetIsolateForPtrCompr();
#else
@ -42,15 +41,6 @@ inline const Isolate* GetIsolateForPtrCompr(const OffThreadIsolate* isolate) {
#endif // V8_COMPRESS_POINTERS
}
inline const Isolate* GetIsolateForPtrCompr(LocalIsolateWrapper isolate) {
#ifdef V8_COMPRESS_POINTERS
return isolate.is_main_thread() ? isolate.main_thread()
: GetIsolateForPtrCompr(isolate.off_thread());
#else
return nullptr;
#endif // V8_COMPRESS_POINTERS
}
V8_INLINE Heap* GetHeapFromWritableObject(HeapObject object) {
// Avoid using the below GetIsolateFromWritableObject because we want to be
// able to get the heap, but not the isolate, for off-thread objects.
@ -69,9 +59,6 @@ V8_INLINE Heap* GetHeapFromWritableObject(HeapObject object) {
}
V8_INLINE Isolate* GetIsolateFromWritableObject(HeapObject object) {
// We don't want to allow accessing the isolate off-thread.
DCHECK(!Heap::InOffThreadSpace(object));
#ifdef V8_ENABLE_THIRD_PARTY_HEAP
return Heap::GetIsolateFromWritableObject(object);
#elif defined V8_COMPRESS_POINTERS

View File

@ -2,24 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_EXECUTION_OFF_THREAD_ISOLATE_INL_H_
#define V8_EXECUTION_OFF_THREAD_ISOLATE_INL_H_
#ifndef V8_EXECUTION_LOCAL_ISOLATE_INL_H_
#define V8_EXECUTION_LOCAL_ISOLATE_INL_H_
#include "src/execution/isolate.h"
#include "src/execution/off-thread-isolate.h"
#include "src/execution/local-isolate.h"
#include "src/roots/roots-inl.h"
namespace v8 {
namespace internal {
Address OffThreadIsolate::isolate_root() const {
return isolate_->isolate_root();
}
ReadOnlyHeap* OffThreadIsolate::read_only_heap() {
Address LocalIsolate::isolate_root() const { return isolate_->isolate_root(); }
ReadOnlyHeap* LocalIsolate::read_only_heap() {
return isolate_->read_only_heap();
}
Object OffThreadIsolate::root(RootIndex index) {
Object LocalIsolate::root(RootIndex index) {
DCHECK(RootsTable::IsImmortalImmovable(index));
return isolate_->root(index);
}
@ -27,4 +25,4 @@ Object OffThreadIsolate::root(RootIndex index) {
} // namespace internal
} // namespace v8
#endif // V8_EXECUTION_OFF_THREAD_ISOLATE_INL_H_
#endif // V8_EXECUTION_LOCAL_ISOLATE_INL_H_

View File

@ -1,148 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_EXECUTION_LOCAL_ISOLATE_WRAPPER_INL_H_
#define V8_EXECUTION_LOCAL_ISOLATE_WRAPPER_INL_H_
#include "src/execution/isolate.h"
#include "src/execution/local-isolate-wrapper.h"
#include "src/execution/off-thread-isolate.h"
#include "src/heap/heap-inl.h"
#include "src/heap/off-thread-heap.h"
#include "src/logging/log.h"
#include "src/logging/off-thread-logger.h"
namespace v8 {
namespace internal {
class HeapMethodCaller {
public:
explicit HeapMethodCaller(LocalHeapWrapper* heap) : heap_(heap) {}
ReadOnlySpace* read_only_space() {
return heap_->is_off_thread() ? heap_->off_thread()->read_only_space()
: heap_->main_thread()->read_only_space();
}
void OnAllocationEvent(HeapObject obj, int size) {
return heap_->is_off_thread()
? heap_->off_thread()->OnAllocationEvent(obj, size)
: heap_->main_thread()->OnAllocationEvent(obj, size);
}
bool Contains(HeapObject obj) {
return heap_->is_off_thread() ? heap_->off_thread()->Contains(obj)
: heap_->main_thread()->Contains(obj);
}
private:
LocalHeapWrapper* heap_;
};
class LoggerMethodCaller {
public:
explicit LoggerMethodCaller(LocalLoggerWrapper* logger) : logger_(logger) {}
bool is_logging() const {
return logger_->is_off_thread() ? logger_->off_thread()->is_logging()
: logger_->main_thread()->is_logging();
}
void ScriptEvent(Logger::ScriptEventType type, int script_id) {
return logger_->is_off_thread()
? logger_->off_thread()->ScriptEvent(type, script_id)
: logger_->main_thread()->ScriptEvent(type, script_id);
}
void ScriptDetails(Script script) {
return logger_->is_off_thread()
? logger_->off_thread()->ScriptDetails(script)
: logger_->main_thread()->ScriptDetails(script);
}
private:
LocalLoggerWrapper* logger_;
};
class IsolateMethodCaller {
public:
explicit IsolateMethodCaller(LocalIsolateWrapper* isolate)
: isolate_(isolate) {}
LocalLoggerWrapper logger() {
return isolate_->is_off_thread()
? LocalLoggerWrapper(isolate_->off_thread()->logger())
: LocalLoggerWrapper(isolate_->main_thread()->logger());
}
LocalHeapWrapper heap() {
return isolate_->is_off_thread()
? LocalHeapWrapper(isolate_->off_thread()->heap())
: LocalHeapWrapper(isolate_->main_thread()->heap());
}
ReadOnlyHeap* read_only_heap() {
return isolate_->is_off_thread()
? isolate_->off_thread()->read_only_heap()
: isolate_->main_thread()->read_only_heap();
}
Object root(RootIndex index) {
return isolate_->is_off_thread() ? isolate_->off_thread()->root(index)
: isolate_->main_thread()->root(index);
}
int GetNextScriptId() {
return isolate_->is_off_thread()
? isolate_->off_thread()->GetNextScriptId()
: isolate_->main_thread()->GetNextScriptId();
}
private:
LocalIsolateWrapper* isolate_;
};
// Helper wrapper for HandleScope behaviour with a LocalIsolateWrapper.
class LocalHandleScopeWrapper {
public:
explicit LocalHandleScopeWrapper(LocalIsolateWrapper local_isolate)
: is_off_thread_(local_isolate.is_off_thread()) {
if (is_off_thread_) {
new (off_thread()) OffThreadHandleScope(local_isolate.off_thread());
} else {
new (main_thread()) HandleScope(local_isolate.main_thread());
}
}
~LocalHandleScopeWrapper() {
if (is_off_thread_) {
off_thread()->~OffThreadHandleScope();
} else {
main_thread()->~HandleScope();
}
}
template <typename T>
Handle<T> CloseAndEscape(Handle<T> handle) {
if (is_off_thread_) {
return off_thread()->CloseAndEscape(handle);
} else {
return main_thread()->CloseAndEscape(handle);
}
}
private:
HandleScope* main_thread() {
return reinterpret_cast<HandleScope*>(&scope_storage_);
}
OffThreadHandleScope* off_thread() {
return reinterpret_cast<OffThreadHandleScope*>(&scope_storage_);
}
std::aligned_union_t<0, HandleScope, OffThreadHandleScope> scope_storage_;
bool is_off_thread_;
};
} // namespace internal
} // namespace v8
#endif // V8_EXECUTION_LOCAL_ISOLATE_WRAPPER_INL_H_

View File

@ -1,85 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_EXECUTION_LOCAL_ISOLATE_WRAPPER_H_
#define V8_EXECUTION_LOCAL_ISOLATE_WRAPPER_H_
#include "src/utils/pointer-with-payload.h"
namespace v8 {
namespace internal {
// LocalWrapperBase is the base-class for wrapper classes around a main-thread
// and off-thread type, e.g. Isolate and OffThreadIsolate, and a bit stating
// which of the two the wrapper wraps.
//
// The shared methods are defined on MethodCaller, which will dispatch to the
// right type depending on the state of the wrapper. The reason for a separate
// MethodCaller is to
//
// a) Move the method definitions into an -inl.h so that this header can have
// minimal dependencies, and
// b) To allow the type methods to be called with operator-> (e.g.
// isolate_wrapper->heap()), while forcing the wrapper methods to be called
// with a dot (e.g. isolate_wrapper.is_main_thread()).
template <typename MainThreadType, typename OffThreadType,
typename MethodCaller>
class LocalWrapperBase {
public:
// Helper for returning a MethodCaller* by value from operator->.
class MethodCallerRef {
public:
MethodCaller* operator->() { return &caller_; }
private:
friend class LocalWrapperBase;
explicit MethodCallerRef(LocalWrapperBase* wrapper) : caller_(wrapper) {}
MethodCaller caller_;
};
explicit LocalWrapperBase(std::nullptr_t) : pointer_and_tag_(nullptr) {}
explicit LocalWrapperBase(MainThreadType* pointer)
: pointer_and_tag_(pointer, false) {}
explicit LocalWrapperBase(OffThreadType* pointer)
: pointer_and_tag_(pointer, true) {}
MainThreadType* main_thread() {
DCHECK(is_main_thread());
return static_cast<MainThreadType*>(
pointer_and_tag_.GetPointerWithKnownPayload(false));
}
OffThreadType* off_thread() {
DCHECK(is_off_thread());
return static_cast<OffThreadType*>(
pointer_and_tag_.GetPointerWithKnownPayload(true));
}
bool is_main_thread() const {
return !is_null() && !pointer_and_tag_.GetPayload();
}
bool is_off_thread() const {
return !is_null() && pointer_and_tag_.GetPayload();
}
bool is_null() const { return pointer_and_tag_.GetPointer() == nullptr; }
// Access the methods via wrapper->Method.
MethodCallerRef operator->() { return MethodCallerRef(this); }
private:
PointerWithPayload<void, bool, 1> pointer_and_tag_;
};
using LocalHeapWrapper =
LocalWrapperBase<class Heap, class OffThreadHeap, class HeapMethodCaller>;
using LocalLoggerWrapper = LocalWrapperBase<class Logger, class OffThreadLogger,
class LoggerMethodCaller>;
using LocalIsolateWrapper =
LocalWrapperBase<class Isolate, class OffThreadIsolate,
class IsolateMethodCaller>;
} // namespace internal
} // namespace v8
#endif // V8_EXECUTION_LOCAL_ISOLATE_WRAPPER_H_

View File

@ -0,0 +1,38 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/execution/local-isolate.h"
#include "src/execution/isolate.h"
#include "src/execution/thread-id.h"
#include "src/handles/handles-inl.h"
#include "src/logging/local-logger.h"
namespace v8 {
namespace internal {
LocalIsolate::LocalIsolate(Isolate* isolate)
: HiddenLocalFactory(isolate),
heap_(isolate->heap()),
isolate_(isolate),
logger_(new LocalLogger()),
thread_id_(ThreadId::Current()) {}
LocalIsolate::~LocalIsolate() = default;
int LocalIsolate::GetNextScriptId() { return isolate_->GetNextScriptId(); }
#if V8_SFI_HAS_UNIQUE_ID
int LocalIsolate::GetNextUniqueSharedFunctionInfoId() {
return isolate_->GetNextUniqueSharedFunctionInfoId();
}
#endif // V8_SFI_HAS_UNIQUE_ID
bool LocalIsolate::is_collecting_type_profile() {
// TODO(leszeks): Figure out if it makes sense to check this asynchronously.
return isolate_->is_collecting_type_profile();
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,101 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_EXECUTION_LOCAL_ISOLATE_H_
#define V8_EXECUTION_LOCAL_ISOLATE_H_
#include "src/base/macros.h"
#include "src/execution/thread-id.h"
#include "src/handles/handles.h"
#include "src/handles/local-handles.h"
#include "src/handles/maybe-handles.h"
#include "src/heap/local-factory.h"
#include "src/heap/local-heap.h"
namespace v8 {
namespace internal {
class Isolate;
class LocalLogger;
// HiddenLocalFactory parallels Isolate's HiddenFactory
class V8_EXPORT_PRIVATE HiddenLocalFactory : private LocalFactory {
public:
// Forward constructors.
using LocalFactory::LocalFactory;
};
// And Isolate-like class that can be passed in to templated methods that need
// an isolate syntactically, but are usable off-thread.
//
// This class holds an LocalFactory, but is otherwise effectively a stub
// implementation of an Isolate. In particular, it doesn't allow throwing
// exceptions, and hard crashes if you try.
class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
public:
using HandleScopeType = LocalHandleScope;
explicit LocalIsolate(Isolate* isolate);
~LocalIsolate();
// Kinda sketchy.
static LocalIsolate* FromHeap(LocalHeap* heap) {
return reinterpret_cast<LocalIsolate*>(reinterpret_cast<Address>(heap) -
OFFSET_OF(LocalIsolate, heap_));
}
LocalHeap* heap() { return &heap_; }
inline Address isolate_root() const;
inline ReadOnlyHeap* read_only_heap();
inline Object root(RootIndex index);
StringTable* string_table() { return isolate_->string_table(); }
const Isolate* GetIsolateForPtrCompr() const { return isolate_; }
v8::internal::LocalFactory* factory() {
// Upcast to the privately inherited base-class using c-style casts to avoid
// undefined behavior (as static_cast cannot cast across private bases).
// NOLINTNEXTLINE (google-readability-casting)
return (v8::internal::LocalFactory*)this; // NOLINT(readability/casting)
}
bool has_pending_exception() const { return false; }
template <typename T>
Handle<T> Throw(Handle<Object> exception) {
UNREACHABLE();
}
[[noreturn]] void FatalProcessOutOfHeapMemory(const char* location) {
UNREACHABLE();
}
int GetNextScriptId();
#if V8_SFI_HAS_UNIQUE_ID
int GetNextUniqueSharedFunctionInfoId();
#endif // V8_SFI_HAS_UNIQUE_ID
bool is_collecting_type_profile();
LocalLogger* logger() { return logger_.get(); }
ThreadId thread_id() { return thread_id_; }
private:
friend class v8::internal::LocalFactory;
LocalHeap heap_;
// TODO(leszeks): Extract out the fields of the Isolate we want and store
// those instead of the whole thing.
Isolate* isolate_;
std::unique_ptr<LocalLogger> logger_;
ThreadId thread_id_;
};
} // namespace internal
} // namespace v8
#endif // V8_EXECUTION_LOCAL_ISOLATE_H_

View File

@ -1,57 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/execution/off-thread-isolate.h"
#include "src/execution/isolate.h"
#include "src/execution/thread-id.h"
#include "src/handles/handles-inl.h"
#include "src/handles/off-thread-transfer-handle-storage-inl.h"
#include "src/logging/off-thread-logger.h"
namespace v8 {
namespace internal {
Address* OffThreadTransferHandleBase::ToHandleLocation() const {
return storage_ == nullptr ? nullptr : storage_->handle_location();
}
OffThreadIsolate::OffThreadIsolate(Isolate* isolate, Zone* zone)
: HiddenOffThreadFactory(isolate),
heap_(isolate->heap()),
isolate_(isolate),
logger_(new OffThreadLogger()),
handle_zone_(zone) {}
OffThreadIsolate::~OffThreadIsolate() = default;
void OffThreadIsolate::FinishOffThread() {
heap()->FinishOffThread();
handle_zone_ = nullptr;
}
void OffThreadIsolate::Publish(Isolate* isolate) {
heap()->Publish(isolate->heap());
}
int OffThreadIsolate::GetNextScriptId() { return isolate_->GetNextScriptId(); }
#if V8_SFI_HAS_UNIQUE_ID
int OffThreadIsolate::GetNextUniqueSharedFunctionInfoId() {
return isolate_->GetNextUniqueSharedFunctionInfoId();
}
#endif // V8_SFI_HAS_UNIQUE_ID
bool OffThreadIsolate::is_collecting_type_profile() {
// TODO(leszeks): Figure out if it makes sense to check this asynchronously.
return isolate_->is_collecting_type_profile();
}
void OffThreadIsolate::PinToCurrentThread() {
DCHECK(!thread_id_.IsValid());
thread_id_ = ThreadId::Current();
}
} // namespace internal
} // namespace v8

View File

@ -1,177 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_EXECUTION_OFF_THREAD_ISOLATE_H_
#define V8_EXECUTION_OFF_THREAD_ISOLATE_H_
#include "src/base/macros.h"
#include "src/execution/thread-id.h"
#include "src/handles/handles.h"
#include "src/handles/maybe-handles.h"
#include "src/heap/off-thread-factory.h"
#include "src/heap/off-thread-heap.h"
namespace v8 {
namespace internal {
class Isolate;
class OffThreadLogger;
class OffThreadTransferHandleStorage;
class OffThreadTransferHandleBase {
protected:
explicit OffThreadTransferHandleBase(OffThreadTransferHandleStorage* storage)
: storage_(storage) {}
V8_EXPORT_PRIVATE Address* ToHandleLocation() const;
private:
OffThreadTransferHandleStorage* storage_;
};
// Helper class for transferring ownership of an off-thread allocated object's
// handler to the main thread. OffThreadTransferHandles should be created before
// the OffThreadIsolate is finished, and can be accessed as a Handle after the
// OffThreadIsolate is published.
template <typename T>
class OffThreadTransferHandle : public OffThreadTransferHandleBase {
public:
OffThreadTransferHandle() : OffThreadTransferHandleBase(nullptr) {}
explicit OffThreadTransferHandle(OffThreadTransferHandleStorage* storage)
: OffThreadTransferHandleBase(storage) {}
Handle<T> ToHandle() const { return Handle<T>(ToHandleLocation()); }
};
template <typename T>
class OffThreadTransferMaybeHandle : public OffThreadTransferHandleBase {
public:
OffThreadTransferMaybeHandle() : OffThreadTransferHandleBase(nullptr) {}
explicit OffThreadTransferMaybeHandle(OffThreadTransferHandleStorage* storage)
: OffThreadTransferHandleBase(storage) {}
MaybeHandle<T> ToHandle() const {
Address* location = ToHandleLocation();
return location ? Handle<T>(location) : MaybeHandle<T>();
}
};
// HiddenOffThreadFactory parallels Isolate's HiddenFactory
class V8_EXPORT_PRIVATE HiddenOffThreadFactory : private OffThreadFactory {
public:
// Forward constructors.
using OffThreadFactory::OffThreadFactory;
};
// And Isolate-like class that can be passed in to templated methods that need
// an isolate syntactically, but are usable off-thread.
//
// This class holds an OffThreadFactory, but is otherwise effectively a stub
// implementation of an Isolate. In particular, it doesn't allow throwing
// exceptions, and hard crashes if you try.
class V8_EXPORT_PRIVATE OffThreadIsolate final
: private HiddenOffThreadFactory {
public:
using HandleScopeType = OffThreadHandleScope;
explicit OffThreadIsolate(Isolate* isolate, Zone* zone);
~OffThreadIsolate();
static OffThreadIsolate* FromHeap(OffThreadHeap* heap) {
return reinterpret_cast<OffThreadIsolate*>(
reinterpret_cast<Address>(heap) - OFFSET_OF(OffThreadIsolate, heap_));
}
OffThreadHeap* heap() { return &heap_; }
inline Address isolate_root() const;
inline ReadOnlyHeap* read_only_heap();
inline Object root(RootIndex index);
const Isolate* GetIsolateForPtrCompr() const { return isolate_; }
v8::internal::OffThreadFactory* factory() {
// Upcast to the privately inherited base-class using c-style casts to avoid
// undefined behavior (as static_cast cannot cast across private bases).
// NOLINTNEXTLINE (google-readability-casting)
return (
v8::internal::OffThreadFactory*)this; // NOLINT(readability/casting)
}
// This method finishes the use of the off-thread Isolate, and can be safely
// called off-thread.
void FinishOffThread();
// This method publishes the off-thread Isolate to the main-thread Isolate,
// moving all off-thread allocated objects to be visible to the GC, and fixing
// up any other state (e.g. internalized strings). This method must be called
// on the main thread.
void Publish(Isolate* isolate);
bool has_pending_exception() const { return false; }
template <typename T>
Handle<T> Throw(Handle<Object> exception) {
UNREACHABLE();
}
[[noreturn]] void FatalProcessOutOfHeapMemory(const char* location) {
UNREACHABLE();
}
Address* NewHandle(Address object) {
DCHECK_NOT_NULL(handle_zone_);
Address* location = handle_zone_->New<Address>(object);
return location;
}
template <typename T>
OffThreadTransferHandle<T> TransferHandle(Handle<T> handle) {
DCHECK_NOT_NULL(handle_zone_);
if (handle.is_null()) {
return OffThreadTransferHandle<T>();
}
return OffThreadTransferHandle<T>(heap()->AddTransferHandleStorage(handle));
}
template <typename T>
OffThreadTransferMaybeHandle<T> TransferHandle(MaybeHandle<T> maybe_handle) {
DCHECK_NOT_NULL(handle_zone_);
Handle<T> handle;
if (!maybe_handle.ToHandle(&handle)) {
return OffThreadTransferMaybeHandle<T>();
}
return OffThreadTransferMaybeHandle<T>(
heap()->AddTransferHandleStorage(handle));
}
int GetNextScriptId();
#if V8_SFI_HAS_UNIQUE_ID
int GetNextUniqueSharedFunctionInfoId();
#endif // V8_SFI_HAS_UNIQUE_ID
bool is_collecting_type_profile();
OffThreadLogger* logger() { return logger_.get(); }
void PinToCurrentThread();
ThreadId thread_id() { return thread_id_; }
private:
friend class v8::internal::OffThreadFactory;
OffThreadHeap heap_;
// TODO(leszeks): Extract out the fields of the Isolate we want and store
// those instead of the whole thing.
Isolate* isolate_;
std::unique_ptr<OffThreadLogger> logger_;
ThreadId thread_id_;
Zone* handle_zone_;
};
} // namespace internal
} // namespace v8
#endif // V8_EXECUTION_OFF_THREAD_ISOLATE_H_

View File

@ -378,7 +378,6 @@ DEFINE_BOOL(future, FUTURE_BOOL,
"not-too-far future")
DEFINE_IMPLICATION(future, write_protect_code_memory)
DEFINE_IMPLICATION(future, finalize_streaming_on_background)
DEFINE_BOOL(assert_types, false,
"generate runtime type assertions to test the typer")
@ -1149,6 +1148,8 @@ DEFINE_BOOL(stress_background_compile, false,
DEFINE_BOOL(
finalize_streaming_on_background, false,
"perform the script streaming finalization on the background thread")
DEFINE_IMPLICATION(finalize_streaming_on_background, concurrent_allocation)
DEFINE_IMPLICATION(finalize_streaming_on_background, local_heaps)
DEFINE_BOOL(disable_old_api_accessors, false,
"Disable old-style API accessors whose setters trigger through the "
"prototype chain")

View File

@ -6,8 +6,7 @@
#define V8_HANDLES_HANDLES_INL_H_
#include "src/execution/isolate.h"
#include "src/execution/local-isolate-wrapper.h"
#include "src/execution/off-thread-isolate.h"
#include "src/execution/local-isolate.h"
#include "src/handles/handles.h"
#include "src/handles/local-handles-inl.h"
#include "src/sanitizer/msan.h"
@ -20,8 +19,8 @@ class LocalHeap;
HandleBase::HandleBase(Address object, Isolate* isolate)
: location_(HandleScope::GetHandle(isolate, object)) {}
HandleBase::HandleBase(Address object, OffThreadIsolate* isolate)
: location_(isolate->NewHandle(object)) {}
HandleBase::HandleBase(Address object, LocalIsolate* isolate)
: location_(LocalHandleScope::GetHandle(isolate->heap(), object)) {}
HandleBase::HandleBase(Address object, LocalHeap* local_heap)
: location_(LocalHandleScope::GetHandle(local_heap, object)) {}
@ -45,7 +44,7 @@ Handle<T>::Handle(T object, Isolate* isolate)
: HandleBase(object.ptr(), isolate) {}
template <typename T>
Handle<T>::Handle(T object, OffThreadIsolate* isolate)
Handle<T>::Handle(T object, LocalIsolate* isolate)
: HandleBase(object.ptr(), isolate) {}
template <typename T>
@ -58,7 +57,7 @@ V8_INLINE Handle<T> handle(T object, Isolate* isolate) {
}
template <typename T>
V8_INLINE Handle<T> handle(T object, OffThreadIsolate* isolate) {
V8_INLINE Handle<T> handle(T object, LocalIsolate* isolate) {
return Handle<T>(object, isolate);
}
@ -67,13 +66,6 @@ V8_INLINE Handle<T> handle(T object, LocalHeap* local_heap) {
return Handle<T>(object, local_heap);
}
template <typename T>
V8_INLINE Handle<T> handle(T object, LocalIsolateWrapper local_isolate) {
return local_isolate.is_off_thread()
? handle(object, local_isolate.off_thread())
: handle(object, local_isolate.main_thread());
}
template <typename T>
inline std::ostream& operator<<(std::ostream& os, Handle<T> handle) {
return os << Brief(*handle);
@ -208,13 +200,6 @@ inline SealHandleScope::~SealHandleScope() {
#endif
template <typename T>
Handle<T> OffThreadHandleScope::CloseAndEscape(Handle<T> handle_value) {
// At the moment, off-thread handle scopes do nothing on close, so we can
// safely return the same handle value.
return handle_value;
}
} // namespace internal
} // namespace v8

View File

@ -35,7 +35,6 @@ 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)) return true;
Isolate* isolate = GetIsolateFromWritableObject(heap_object);
RootIndex root_index;
if (isolate->roots_table().IsRootHandleLocation(location_, &root_index) &&

View File

@ -21,7 +21,7 @@ namespace internal {
class HandleScopeImplementer;
class Isolate;
class LocalHeap;
class OffThreadIsolate;
class LocalIsolate;
template <typename T>
class MaybeHandle;
class Object;
@ -40,7 +40,7 @@ class HandleBase {
public:
V8_INLINE explicit HandleBase(Address* location) : location_(location) {}
V8_INLINE explicit HandleBase(Address object, Isolate* isolate);
V8_INLINE explicit HandleBase(Address object, OffThreadIsolate* isolate);
V8_INLINE explicit HandleBase(Address object, LocalIsolate* isolate);
V8_INLINE explicit HandleBase(Address object, LocalHeap* local_heap);
// Check if this handle refers to the exact same object as the other handle.
@ -122,7 +122,7 @@ class Handle final : public HandleBase {
}
V8_INLINE Handle(T object, Isolate* isolate);
V8_INLINE Handle(T object, OffThreadIsolate* isolate);
V8_INLINE Handle(T object, LocalIsolate* isolate);
V8_INLINE Handle(T object, LocalHeap* local_heap);
// Allocate a new handle for the object, do not canonicalize.
@ -343,16 +343,6 @@ struct HandleScopeData final {
}
};
class OffThreadHandleScope {
public:
// Off-thread Handles are allocated in the parse/compile zone, and not
// cleared out, so the scope doesn't have to do anything
explicit OffThreadHandleScope(OffThreadIsolate* isolate) {}
template <typename T>
inline Handle<T> CloseAndEscape(Handle<T> handle_value);
};
} // namespace internal
} // namespace v8

View File

@ -5,8 +5,8 @@
#ifndef V8_HANDLES_LOCAL_HANDLES_INL_H_
#define V8_HANDLES_LOCAL_HANDLES_INL_H_
#include "src/execution/local-isolate.h"
#include "src/handles/local-handles.h"
#include "src/sanitizer/msan.h"
namespace v8 {
@ -26,6 +26,9 @@ V8_INLINE Address* LocalHandleScope::GetHandle(LocalHeap* local_heap,
return result;
}
LocalHandleScope::LocalHandleScope(LocalIsolate* local_isolate)
: LocalHandleScope(local_isolate->heap()) {}
LocalHandleScope::LocalHandleScope(LocalHeap* local_heap) {
LocalHandles* handles = local_heap->handles();
local_heap_ = local_heap;
@ -35,11 +38,34 @@ LocalHandleScope::LocalHandleScope(LocalHeap* local_heap) {
}
LocalHandleScope::~LocalHandleScope() {
LocalHandles* handles = local_heap_->handles();
if (local_heap_ == nullptr) return;
CloseScope(local_heap_, prev_next_, prev_limit_);
}
template <typename T>
Handle<T> LocalHandleScope::CloseAndEscape(Handle<T> handle_value) {
HandleScopeData* current = &local_heap_->handles()->scope_;
T value = *handle_value;
// Throw away all handles in the current scope.
CloseScope(local_heap_, prev_next_, prev_limit_);
// Allocate one handle in the parent scope.
DCHECK(current->level > current->sealed_level);
Handle<T> result(value, local_heap_);
// Reinitialize the current scope (so that it's ready
// to be used or closed again).
prev_next_ = current->next;
prev_limit_ = current->limit;
current->level++;
return result;
}
void LocalHandleScope::CloseScope(LocalHeap* local_heap, Address* prev_next,
Address* prev_limit) {
LocalHandles* handles = local_heap->handles();
Address* old_limit = handles->scope_.limit;
handles->scope_.next = prev_next_;
handles->scope_.limit = prev_limit_;
handles->scope_.next = prev_next;
handles->scope_.limit = prev_limit;
handles->scope_.level--;
if (old_limit != handles->scope_.limit) {

View File

@ -43,15 +43,23 @@ class LocalHandles {
class LocalHandleScope {
public:
explicit inline LocalHandleScope(LocalIsolate* local_isolate);
explicit inline LocalHandleScope(LocalHeap* local_heap);
inline ~LocalHandleScope();
template <typename T>
Handle<T> CloseAndEscape(Handle<T> handle_value);
V8_INLINE static Address* GetHandle(LocalHeap* local_heap, Address value);
private:
// Prevent heap allocation or illegal handle scopes.
void* operator new(size_t size);
void operator delete(void* size_t);
void* operator new(size_t size) = delete;
void operator delete(void* size_t) = delete;
// Close the handle scope resetting limits to a previous state.
static inline void CloseScope(LocalHeap* local_heap, Address* prev_next,
Address* prev_limit);
LocalHeap* local_heap_;
Address* prev_limit_;

View File

@ -1,77 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HANDLES_OFF_THREAD_TRANSFER_HANDLE_STORAGE_INL_H_
#define V8_HANDLES_OFF_THREAD_TRANSFER_HANDLE_STORAGE_INL_H_
#include "src/handles/handles-inl.h"
#include "src/handles/off-thread-transfer-handle-storage.h"
namespace v8 {
namespace internal {
OffThreadTransferHandleStorage::OffThreadTransferHandleStorage(
Address* off_thread_handle_location,
std::unique_ptr<OffThreadTransferHandleStorage> next)
: handle_location_(off_thread_handle_location),
next_(std::move(next)),
state_(kOffThreadHandle) {
CheckValid();
}
void OffThreadTransferHandleStorage::ConvertFromOffThreadHandleOnFinish() {
CheckValid();
DCHECK_EQ(state_, kOffThreadHandle);
raw_obj_ptr_ = *handle_location_;
state_ = kRawObject;
CheckValid();
}
void OffThreadTransferHandleStorage::ConvertToHandleOnPublish(
Isolate* isolate, DisallowHeapAllocation* no_gc) {
CheckValid();
DCHECK_EQ(state_, kRawObject);
handle_location_ = handle(Object(raw_obj_ptr_), isolate).location();
state_ = kHandle;
CheckValid();
}
Address* OffThreadTransferHandleStorage::handle_location() const {
CheckValid();
DCHECK_EQ(state_, kHandle);
return handle_location_;
}
void OffThreadTransferHandleStorage::CheckValid() const {
#ifdef DEBUG
Object obj;
switch (state_) {
case kHandle:
case kOffThreadHandle:
DCHECK_NOT_NULL(handle_location_);
obj = Object(*handle_location_);
break;
case kRawObject:
obj = Object(raw_obj_ptr_);
break;
}
// Smis are always fine.
if (obj.IsSmi()) return;
// The main-thread handle should not be in off-thread space, and vice verse.
// Raw object pointers can point to the main-thread heap during Publish, so
// we don't check that.
DCHECK_IMPLIES(state_ == kOffThreadHandle,
Heap::InOffThreadSpace(HeapObject::cast(obj)));
DCHECK_IMPLIES(state_ == kHandle,
!Heap::InOffThreadSpace(HeapObject::cast(obj)));
#endif
}
} // namespace internal
} // namespace v8
#endif // V8_HANDLES_OFF_THREAD_TRANSFER_HANDLE_STORAGE_INL_H_

View File

@ -1,47 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HANDLES_OFF_THREAD_TRANSFER_HANDLE_STORAGE_H_
#define V8_HANDLES_OFF_THREAD_TRANSFER_HANDLE_STORAGE_H_
#include "src/common/assert-scope.h"
#include "src/handles/handles.h"
namespace v8 {
namespace internal {
class OffThreadTransferHandleStorage {
public:
enum State { kOffThreadHandle, kRawObject, kHandle };
inline explicit OffThreadTransferHandleStorage(
Address* off_thread_handle_location,
std::unique_ptr<OffThreadTransferHandleStorage> next);
inline void ConvertFromOffThreadHandleOnFinish();
inline void ConvertToHandleOnPublish(Isolate* isolate,
DisallowHeapAllocation* no_gc);
inline Address* handle_location() const;
OffThreadTransferHandleStorage* next() { return next_.get(); }
State state() const { return state_; }
private:
inline void CheckValid() const;
union {
Address* handle_location_;
Address raw_obj_ptr_;
};
std::unique_ptr<OffThreadTransferHandleStorage> next_;
State state_;
};
} // namespace internal
} // namespace v8
#endif // V8_HANDLES_OFF_THREAD_TRANSFER_HANDLE_STORAGE_H_

View File

@ -6,20 +6,21 @@
#include "src/ast/ast-source-ranges.h"
#include "src/ast/ast.h"
#include "src/execution/off-thread-isolate.h"
#include "src/execution/local-isolate.h"
#include "src/handles/handles-inl.h"
#include "src/heap/factory.h"
#include "src/heap/heap-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/heap/memory-chunk.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/read-only-heap.h"
#include "src/logging/local-logger.h"
#include "src/logging/log.h"
#include "src/logging/off-thread-logger.h"
#include "src/objects/literal-objects-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/oddball.h"
#include "src/objects/shared-function-info-inl.h"
#include "src/objects/source-text-module.h"
#include "src/objects/string-inl.h"
#include "src/objects/template-objects-inl.h"
namespace v8 {
@ -43,7 +44,7 @@ template V8_EXPORT_PRIVATE Handle<HeapNumber>
FactoryBase<Factory>::NewHeapNumber<AllocationType::kReadOnly>();
template V8_EXPORT_PRIVATE Handle<HeapNumber>
FactoryBase<OffThreadFactory>::NewHeapNumber<AllocationType::kOld>();
FactoryBase<LocalFactory>::NewHeapNumber<AllocationType::kOld>();
template <typename Impl>
Handle<Struct> FactoryBase<Impl>::NewStruct(InstanceType type,
@ -445,6 +446,60 @@ Handle<CoverageInfo> FactoryBase<Impl>::NewCoverageInfo(
return info;
}
template <typename Impl>
Handle<String> FactoryBase<Impl>::MakeOrFindTwoCharacterString(uint16_t c1,
uint16_t c2) {
if ((c1 | c2) <= unibrow::Latin1::kMaxChar) {
uint8_t buffer[] = {static_cast<uint8_t>(c1), static_cast<uint8_t>(c2)};
return InternalizeString(Vector<const uint8_t>(buffer, 2));
}
uint16_t buffer[] = {c1, c2};
return InternalizeString(Vector<const uint16_t>(buffer, 2));
}
template <typename Impl>
template <class StringTableKey>
Handle<String> FactoryBase<Impl>::InternalizeStringWithKey(
StringTableKey* key) {
return isolate()->string_table()->LookupKey(isolate(), key);
}
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
OneByteStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
TwoByteStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
SeqOneByteSubStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
SeqTwoByteSubStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> FactoryBase<LocalFactory>::InternalizeStringWithKey(
OneByteStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> FactoryBase<LocalFactory>::InternalizeStringWithKey(
TwoByteStringKey* key);
template <typename Impl>
Handle<String> FactoryBase<Impl>::InternalizeString(
const Vector<const uint8_t>& string, bool convert_encoding) {
SequentialStringKey<uint8_t> key(string, HashSeed(read_only_roots()),
convert_encoding);
return InternalizeStringWithKey(&key);
}
template <typename Impl>
Handle<String> FactoryBase<Impl>::InternalizeString(
const Vector<const uint16_t>& string, bool convert_encoding) {
SequentialStringKey<uint16_t> key(string, HashSeed(read_only_roots()),
convert_encoding);
return InternalizeStringWithKey(&key);
}
template <typename Impl>
Handle<SeqOneByteString> FactoryBase<Impl>::NewOneByteInternalizedString(
const Vector<const uint8_t>& str, uint32_t hash_field) {
@ -524,7 +579,7 @@ MaybeHandle<String> FactoryBase<Impl>::NewConsString(
if (length == 2) {
uint16_t c1 = left->Get(0);
uint16_t c2 = right->Get(0);
return impl()->MakeOrFindTwoCharacterString(c1, c2);
return MakeOrFindTwoCharacterString(c1, c2);
}
// Make sure that an out of memory exception is thrown if the length
@ -774,7 +829,7 @@ HeapObject FactoryBase<Impl>::AllocateRaw(int size, AllocationType allocation,
// Instantiate FactoryBase for the two variants we want.
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) FactoryBase<Factory>;
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
FactoryBase<OffThreadFactory>;
FactoryBase<LocalFactory>;
} // namespace internal
} // namespace v8

View File

@ -142,6 +142,14 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase {
Handle<CoverageInfo> NewCoverageInfo(const ZoneVector<SourceRange>& slots);
Handle<String> InternalizeString(const Vector<const uint8_t>& string,
bool convert_encoding = false);
Handle<String> InternalizeString(const Vector<const uint16_t>& string,
bool convert_encoding = false);
template <class StringTableKey>
Handle<String> InternalizeStringWithKey(StringTableKey* key);
Handle<SeqOneByteString> NewOneByteInternalizedString(
const Vector<const uint8_t>& str, uint32_t hash_field);
Handle<SeqTwoByteString> NewTwoByteInternalizedString(
@ -206,6 +214,8 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase {
MaybeHandle<HeapObject> maybe_function_data, int maybe_builtin_index,
FunctionKind kind = kNormalFunction);
Handle<String> MakeOrFindTwoCharacterString(uint16_t c1, uint16_t c2);
private:
Impl* impl() { return static_cast<Impl*>(this); }
auto isolate() { return impl()->isolate(); }

View File

@ -582,20 +582,6 @@ Handle<String> Factory::InternalizeUtf8String(
Vector<const uc16>(buffer.get(), decoder.utf16_length()));
}
Handle<String> Factory::InternalizeString(Vector<const uint8_t> string,
bool convert_encoding) {
SequentialStringKey<uint8_t> key(string, HashSeed(isolate()),
convert_encoding);
return InternalizeStringWithKey(&key);
}
Handle<String> Factory::InternalizeString(Vector<const uint16_t> string,
bool convert_encoding) {
SequentialStringKey<uint16_t> key(string, HashSeed(isolate()),
convert_encoding);
return InternalizeStringWithKey(&key);
}
template <typename SeqString>
Handle<String> Factory::InternalizeString(Handle<SeqString> string, int from,
int length, bool convert_encoding) {
@ -611,15 +597,6 @@ template Handle<String> Factory::InternalizeString(
Handle<SeqTwoByteString> string, int from, int length,
bool convert_encoding);
template <class StringTableKey>
Handle<String> Factory::InternalizeStringWithKey(StringTableKey* key) {
return isolate()->string_table()->LookupKey(isolate(), key);
}
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> Factory::InternalizeStringWithKey(OneByteStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> Factory::InternalizeStringWithKey(TwoByteStringKey* key);
MaybeHandle<String> Factory::NewStringFromOneByte(
const Vector<const uint8_t>& string, AllocationType allocation) {
DCHECK_NE(allocation, AllocationType::kReadOnly);
@ -887,15 +864,6 @@ Handle<String> Factory::LookupSingleCharacterStringFromCode(uint16_t code) {
return InternalizeString(Vector<const uint16_t>(buffer, 1));
}
Handle<String> Factory::MakeOrFindTwoCharacterString(uint16_t c1, uint16_t c2) {
if ((c1 | c2) <= unibrow::Latin1::kMaxChar) {
uint8_t buffer[] = {static_cast<uint8_t>(c1), static_cast<uint8_t>(c2)};
return InternalizeString(Vector<const uint8_t>(buffer, 2));
}
uint16_t buffer[] = {c1, c2};
return InternalizeString(Vector<const uint16_t>(buffer, 2));
}
Handle<String> Factory::NewSurrogatePairString(uint16_t lead, uint16_t trail) {
DCHECK_GE(lead, 0xD800);
DCHECK_LE(lead, 0xDBFF);

View File

@ -192,10 +192,9 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
return InternalizeUtf8String(CStrVector(str));
}
Handle<String> InternalizeString(Vector<const uint8_t> str,
bool convert_encoding = false);
Handle<String> InternalizeString(Vector<const uint16_t> str,
bool convert_encoding = false);
// Import InternalizeString overloads from base class.
using FactoryBase::InternalizeString;
Handle<String> InternalizeString(Vector<const char> str,
bool convert_encoding = false) {
return InternalizeString(Vector<const uint8_t>::cast(str));
@ -205,9 +204,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
Handle<String> InternalizeString(Handle<SeqString>, int from, int length,
bool convert_encoding = false);
template <class StringTableKey>
Handle<String> InternalizeStringWithKey(StringTableKey* key);
// Internalized strings are created in the old generation (data space).
inline Handle<String> InternalizeString(Handle<String> string);
@ -911,8 +907,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
bool CanAllocateInReadOnlySpace();
bool EmptyStringRootIsInitialized();
Handle<String> MakeOrFindTwoCharacterString(uint16_t c1, uint16_t c2);
void AddToScriptList(Handle<Script> shared);
// ------

View File

@ -23,6 +23,7 @@
#include "src/execution/isolate-data.h"
#include "src/execution/isolate.h"
#include "src/heap/code-object-registry.h"
#include "src/heap/large-spaces.h"
#include "src/heap/memory-allocator.h"
#include "src/heap/memory-chunk.h"
#include "src/heap/new-spaces-inl.h"

View File

@ -2977,7 +2977,6 @@ void VerifyNoNeedToClearSlots(Address start, Address end) {
// TODO(ulan): Support verification of large pages.
if (chunk->InYoungGeneration() || chunk->IsLargePage()) return;
BaseSpace* space = chunk->owner();
if (static_cast<PagedSpace*>(space)->is_off_thread_space()) return;
space->heap()->VerifySlotRangeHasNoRecordedSlots(start, end);
}
#else
@ -3034,25 +3033,6 @@ bool Heap::CanMoveObjectStart(HeapObject object) {
return Page::FromHeapObject(object)->SweepingDone();
}
// static
bool Heap::InOffThreadSpace(HeapObject heap_object) {
#ifdef V8_ENABLE_THIRD_PARTY_HEAP
return false; // currently unsupported
#else
BaseSpace* owner = BasicMemoryChunk::FromHeapObject(heap_object)->owner();
// Detached RO_SPACE chunks have no owner set.
if (owner == nullptr) return false;
if (owner->identity() == OLD_SPACE) {
// TODO(leszeks): Should we exclude compaction spaces here?
return static_cast<PagedSpace*>(owner)->is_off_thread_space();
}
if (owner->identity() == LO_SPACE) {
return static_cast<LargeObjectSpace*>(owner)->is_off_thread();
}
return false;
#endif
}
bool Heap::IsImmovable(HeapObject object) {
if (V8_ENABLE_THIRD_PARTY_HEAP_BOOL) {
// TODO(steveblackburn): For now all objects are immovable.
@ -6777,7 +6757,7 @@ bool Heap::PageFlagsAreConsistent(HeapObject object) {
CHECK_EQ(chunk->InReadOnlySpace(), slim_chunk->InReadOnlySpace());
// Marking consistency.
if (chunk->IsWritable() && !Heap::InOffThreadSpace(object)) {
if (chunk->IsWritable()) {
// RO_SPACE can be shared between heaps, so we can't use RO_SPACE objects to
// find a heap. The exception is when the ReadOnlySpace is writeable, during
// bootstrapping, so explicitly allow this case.

View File

@ -86,7 +86,6 @@ class MemoryReducer;
class MinorMarkCompactCollector;
class ObjectIterator;
class ObjectStats;
class OffThreadHeap;
class Page;
class PagedSpace;
class ReadOnlyHeap;
@ -1149,8 +1148,6 @@ class Heap {
static inline bool InToPage(MaybeObject object);
static inline bool InToPage(HeapObject heap_object);
V8_EXPORT_PRIVATE static bool InOffThreadSpace(HeapObject heap_object);
// Returns whether the object resides in old space.
inline bool InOldSpace(Object object);
@ -2308,8 +2305,6 @@ class Heap {
friend class ScavengeTaskObserver;
friend class IncrementalMarking;
friend class IncrementalMarkingJob;
friend class OffThreadHeap;
friend class OffThreadSpace;
friend class OldLargeObjectSpace;
template <typename ConcreteVisitor, typename MarkingState>
friend class MarkingVisitorBase;
@ -2330,7 +2325,6 @@ class Heap {
// The allocator interface.
friend class Factory;
friend class OffThreadFactory;
// The Isolate constructs us.
friend class Isolate;

View File

@ -439,29 +439,6 @@ OldLargeObjectSpace::OldLargeObjectSpace(Heap* heap)
OldLargeObjectSpace::OldLargeObjectSpace(Heap* heap, AllocationSpace id)
: LargeObjectSpace(heap, id) {}
void OldLargeObjectSpace::MergeOffThreadSpace(
OffThreadLargeObjectSpace* other) {
DCHECK(identity() == other->identity());
while (!other->memory_chunk_list().Empty()) {
LargePage* page = other->first_page();
HeapObject object = page->GetObject();
int size = object.Size();
other->RemovePage(page, size);
AddPage(page, size);
// TODO(leszeks): Here we should AllocationStep, see the TODO in
// PagedSpace::MergeOffThreadSpace.
if (heap()->incremental_marking()->black_allocation()) {
heap()->incremental_marking()->marking_state()->WhiteToBlack(object);
}
DCHECK_IMPLIES(
heap()->incremental_marking()->black_allocation(),
heap()->incremental_marking()->marking_state()->IsBlack(object));
}
}
NewLargeObjectSpace::NewLargeObjectSpace(Heap* heap, size_t capacity)
: LargeObjectSpace(heap, NEW_LO_SPACE),
pending_object_(0),
@ -568,25 +545,5 @@ void CodeLargeObjectSpace::RemovePage(LargePage* page, size_t object_size) {
OldLargeObjectSpace::RemovePage(page, object_size);
}
OffThreadLargeObjectSpace::OffThreadLargeObjectSpace(Heap* heap)
: LargeObjectSpace(heap, LO_SPACE) {
#ifdef V8_ENABLE_THIRD_PARTY_HEAP
// OffThreadLargeObjectSpace doesn't work with third-party heap.
UNREACHABLE();
#endif
}
AllocationResult OffThreadLargeObjectSpace::AllocateRaw(int object_size) {
LargePage* page = AllocateLargePage(object_size, NOT_EXECUTABLE);
if (page == nullptr) return AllocationResult::Retry(identity());
return page->GetObject();
}
void OffThreadLargeObjectSpace::FreeUnmarkedObjects() {
// We should never try to free objects in this space.
UNREACHABLE();
}
} // namespace internal
} // namespace v8

View File

@ -128,8 +128,6 @@ class V8_EXPORT_PRIVATE LargeObjectSpace : public Space {
friend class LargeObjectSpaceObjectIterator;
};
class OffThreadLargeObjectSpace;
class OldLargeObjectSpace : public LargeObjectSpace {
public:
explicit OldLargeObjectSpace(Heap* heap);
@ -145,8 +143,6 @@ class OldLargeObjectSpace : public LargeObjectSpace {
void PromoteNewLargeObject(LargePage* page);
V8_EXPORT_PRIVATE void MergeOffThreadSpace(OffThreadLargeObjectSpace* other);
protected:
explicit OldLargeObjectSpace(Heap* heap, AllocationSpace id);
V8_WARN_UNUSED_RESULT AllocationResult AllocateRaw(int object_size,
@ -206,24 +202,6 @@ class CodeLargeObjectSpace : public OldLargeObjectSpace {
std::unordered_map<Address, LargePage*> chunk_map_;
};
class V8_EXPORT_PRIVATE OffThreadLargeObjectSpace : public LargeObjectSpace {
public:
explicit OffThreadLargeObjectSpace(Heap* heap);
V8_WARN_UNUSED_RESULT AllocationResult AllocateRaw(int object_size);
void FreeUnmarkedObjects() override;
bool is_off_thread() const override { return true; }
protected:
// OldLargeObjectSpace can mess with OffThreadLargeObjectSpace during merging.
friend class OldLargeObjectSpace;
V8_WARN_UNUSED_RESULT AllocationResult AllocateRaw(int object_size,
Executability executable);
};
class LargeObjectSpaceObjectIterator : public ObjectIterator {
public:
explicit LargeObjectSpaceObjectIterator(LargeObjectSpace* space);

View File

@ -2,26 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_OFF_THREAD_FACTORY_INL_H_
#define V8_HEAP_OFF_THREAD_FACTORY_INL_H_
#include "src/heap/off-thread-factory.h"
#ifndef V8_HEAP_LOCAL_FACTORY_INL_H_
#define V8_HEAP_LOCAL_FACTORY_INL_H_
#include "src/heap/factory-base-inl.h"
#include "src/heap/local-factory.h"
#include "src/roots/roots-inl.h"
namespace v8 {
namespace internal {
#define ROOT_ACCESSOR(Type, name, CamelName) \
Handle<Type> OffThreadFactory::name() { \
Handle<Type> LocalFactory::name() { \
return read_only_roots().name##_handle(); \
}
READ_ONLY_ROOT_LIST(ROOT_ACCESSOR)
#undef ROOT_ACCESSOR
#define ACCESSOR_INFO_ACCESSOR(Type, name, CamelName) \
Handle<Type> OffThreadFactory::name() { \
Handle<Type> LocalFactory::name() { \
/* Do a bit of handle location magic to cast the Handle without having */ \
/* to pull in Type::cast. We know the type is right by construction. */ \
return Handle<Type>( \
@ -30,7 +29,7 @@ READ_ONLY_ROOT_LIST(ROOT_ACCESSOR)
ACCESSOR_INFO_ROOT_LIST(ACCESSOR_INFO_ACCESSOR)
#undef ACCESSOR_INFO_ACCESSOR
#endif // V8_HEAP_OFF_THREAD_FACTORY_INL_H_
#endif // V8_HEAP_LOCAL_FACTORY_INL_H_
} // namespace internal
} // namespace v8

48
src/heap/local-factory.cc Normal file
View File

@ -0,0 +1,48 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/local-factory.h"
#include "src/common/globals.h"
#include "src/execution/local-isolate.h"
#include "src/handles/handles.h"
#include "src/heap/concurrent-allocator-inl.h"
#include "src/numbers/hash-seed-inl.h"
#include "src/objects/fixed-array.h"
#include "src/objects/heap-object.h"
#include "src/objects/string.h"
#include "src/roots/roots-inl.h"
#include "src/strings/string-hasher.h"
namespace v8 {
namespace internal {
LocalFactory::LocalFactory(Isolate* isolate) : roots_(isolate) {}
void LocalFactory::AddToScriptList(Handle<Script> shared) {
// TODO(leszeks): Actually add the script to the main Isolate's script list,
// in a thread-safe way.
//
// At the moment, we have to do one final fix-up during off-thread
// finalization, where we add the created script to the script list, but this
// relies on there being exactly one script created during the lifetime of
// this LocalFactory.
//
// For now, prevent accidentaly creating more scripts that don't get added to
// the script list with a simple DCHECK.
#ifdef DEBUG
DCHECK(!a_script_was_added_to_the_script_list_);
a_script_was_added_to_the_script_list_ = true;
#endif
}
HeapObject LocalFactory::AllocateRaw(int size, AllocationType allocation,
AllocationAlignment alignment) {
DCHECK_EQ(allocation, AllocationType::kOld);
return HeapObject::FromAddress(isolate()->heap()->AllocateRawOrFail(
size, allocation, AllocationOrigin::kRuntime, alignment));
}
} // namespace internal
} // namespace v8

View File

@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_OFF_THREAD_FACTORY_H_
#define V8_HEAP_OFF_THREAD_FACTORY_H_
#ifndef V8_HEAP_LOCAL_FACTORY_H_
#define V8_HEAP_LOCAL_FACTORY_H_
#include <map>
#include <vector>
#include "src/base/logging.h"
#include "src/common/globals.h"
#include "src/handles/handles.h"
@ -26,12 +27,11 @@ namespace internal {
class AstValueFactory;
class AstRawString;
class AstConsString;
class OffThreadIsolate;
class LocalIsolate;
class V8_EXPORT_PRIVATE OffThreadFactory
: public FactoryBase<OffThreadFactory> {
class V8_EXPORT_PRIVATE LocalFactory : public FactoryBase<LocalFactory> {
public:
explicit OffThreadFactory(Isolate* isolate);
explicit LocalFactory(Isolate* isolate);
ReadOnlyRoots read_only_roots() const { return roots_; }
@ -44,46 +44,42 @@ 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);
// The parser shouldn't allow the OffThreadFactory to get into a state where
// The parser shouldn't allow the LocalFactory to get into a state where
// it generates errors.
Handle<Object> NewInvalidStringLengthError() { UNREACHABLE(); }
Handle<Object> NewRangeError(MessageTemplate template_index) {
UNREACHABLE();
}
Handle<FixedArray> StringWrapperForTest(Handle<String> string);
private:
friend class FactoryBase<OffThreadFactory>;
friend class FactoryBase<LocalFactory>;
// ------
// Customization points for FactoryBase.
HeapObject AllocateRaw(int size, AllocationType allocation,
AllocationAlignment alignment = kWordAligned);
OffThreadIsolate* isolate() {
LocalIsolate* isolate() {
// Downcast to the privately inherited sub-class using c-style casts to
// avoid undefined behavior (as static_cast cannot cast across private
// bases).
// NOLINTNEXTLINE (google-readability-casting)
return (OffThreadIsolate*)this; // NOLINT(readability/casting)
return (LocalIsolate*)this; // NOLINT(readability/casting)
}
inline bool CanAllocateInReadOnlySpace() { return false; }
inline bool EmptyStringRootIsInitialized() { return true; }
// ------
Handle<String> MakeOrFindTwoCharacterString(uint16_t c1, uint16_t c2);
void AddToScriptList(Handle<Script> shared);
// ------
ReadOnlyRoots roots_;
#ifdef DEBUG
bool a_script_was_added_to_the_script_list_ = false;
#endif
};
} // namespace internal
} // namespace v8
#endif // V8_HEAP_OFF_THREAD_FACTORY_H_
#endif // V8_HEAP_LOCAL_FACTORY_H_

View File

@ -56,6 +56,15 @@ class V8_EXPORT_PRIVATE LocalHeap {
return NewPersistentHandle(*object);
}
template <typename T>
MaybeHandle<T> NewPersistentMaybeHandle(MaybeHandle<T> maybe_handle) {
Handle<T> handle;
if (maybe_handle.ToHandle(&handle)) {
return NewPersistentHandle(handle);
}
return kNullMaybeHandle;
}
std::unique_ptr<PersistentHandles> DetachPersistentHandles();
#ifdef DEBUG
bool ContainsPersistentHandle(Address* location);

View File

@ -1,76 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/off-thread-factory.h"
#include "src/common/globals.h"
#include "src/handles/handles.h"
#include "src/numbers/hash-seed-inl.h"
#include "src/objects/fixed-array.h"
#include "src/objects/heap-object.h"
#include "src/objects/string.h"
#include "src/roots/roots-inl.h"
#include "src/strings/string-hasher.h"
namespace v8 {
namespace internal {
OffThreadFactory::OffThreadFactory(Isolate* isolate) : roots_(isolate) {}
// Hacky method for creating a simple object with a slot pointing to a string.
// TODO(leszeks): Remove once we have full FixedArray support.
Handle<FixedArray> OffThreadFactory::StringWrapperForTest(
Handle<String> string) {
HeapObject wrapper =
AllocateRaw(FixedArray::SizeFor(1), AllocationType::kOld);
wrapper.set_map_after_allocation(read_only_roots().fixed_array_map());
FixedArray array = FixedArray::cast(wrapper);
array.set_length(1);
array.data_start().Relaxed_Store(*string);
return handle(array, isolate());
}
Handle<String> OffThreadFactory::MakeOrFindTwoCharacterString(uint16_t c1,
uint16_t c2) {
// TODO(leszeks): Do some real caching here. Also, these strings should be
// internalized.
if ((c1 | c2) <= unibrow::Latin1::kMaxChar) {
Handle<SeqOneByteString> ret =
NewRawOneByteString(2, AllocationType::kOld).ToHandleChecked();
ret->SeqOneByteStringSet(0, c1);
ret->SeqOneByteStringSet(1, c2);
return ret;
}
Handle<SeqTwoByteString> ret =
NewRawTwoByteString(2, AllocationType::kOld).ToHandleChecked();
ret->SeqTwoByteStringSet(0, c1);
ret->SeqTwoByteStringSet(1, c2);
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) {
isolate()->heap()->AddToScriptList(shared);
}
HeapObject OffThreadFactory::AllocateRaw(int size, AllocationType allocation,
AllocationAlignment alignment) {
return isolate()->heap()->AllocateRaw(size, allocation, alignment);
}
} // namespace internal
} // namespace v8

View File

@ -1,328 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/off-thread-heap.h"
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
#include "src/handles/off-thread-transfer-handle-storage-inl.h"
#include "src/heap/paged-spaces-inl.h"
#include "src/heap/spaces-inl.h"
#include "src/objects/objects-body-descriptors-inl.h"
#include "src/roots/roots.h"
#include "src/snapshot/references.h"
// Has to be the last include (doesn't have include guards)
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
OffThreadHeap::~OffThreadHeap() = default;
OffThreadHeap::OffThreadHeap(Heap* heap)
: space_(heap),
lo_space_(heap),
off_thread_transfer_handles_head_(nullptr) {}
bool OffThreadHeap::Contains(HeapObject obj) {
return space_.Contains(obj) || lo_space_.Contains(obj);
}
class OffThreadHeap::StringSlotCollectingVisitor : public ObjectVisitor {
public:
void VisitPointers(HeapObject host, ObjectSlot start,
ObjectSlot end) override {
for (ObjectSlot slot = start; slot != end; ++slot) {
Object obj = *slot;
if (obj.IsInternalizedString() &&
!ReadOnlyHeap::Contains(HeapObject::cast(obj))) {
string_slots.emplace_back(host.address(),
slot.address() - host.address());
}
}
}
void VisitPointers(HeapObject host, MaybeObjectSlot start,
MaybeObjectSlot end) override {
for (MaybeObjectSlot slot = start; slot != end; ++slot) {
MaybeObject maybe_obj = *slot;
HeapObject obj;
if (maybe_obj.GetHeapObjectIfStrong(&obj)) {
if (obj.IsInternalizedString() && !ReadOnlyHeap::Contains(obj)) {
string_slots.emplace_back(host.address(),
slot.address() - host.address());
}
}
}
}
void VisitCodeTarget(Code host, RelocInfo* rinfo) override { UNREACHABLE(); }
void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) override {
UNREACHABLE();
}
std::vector<RelativeSlot> string_slots;
};
void OffThreadHeap::FinishOffThread() {
DCHECK(!is_finished);
StringSlotCollectingVisitor string_slot_collector;
// First iterate all objects in the spaces to find string slots. At this point
// all string slots have to point to off-thread strings or read-only strings.
{
PagedSpaceObjectIterator it(&space_);
for (HeapObject obj = it.Next(); !obj.is_null(); obj = it.Next()) {
obj.IterateBodyFast(&string_slot_collector);
}
}
{
LargeObjectSpaceObjectIterator it(&lo_space_);
for (HeapObject obj = it.Next(); !obj.is_null(); obj = it.Next()) {
obj.IterateBodyFast(&string_slot_collector);
}
}
string_slots_ = std::move(string_slot_collector.string_slots);
OffThreadTransferHandleStorage* storage =
off_thread_transfer_handles_head_.get();
while (storage != nullptr) {
storage->ConvertFromOffThreadHandleOnFinish();
storage = storage->next();
}
is_finished = true;
}
void OffThreadHeap::Publish(Heap* heap) {
DCHECK(is_finished);
Isolate* isolate = heap->isolate();
ReadOnlyRoots roots(isolate);
// Before we do anything else, ensure that the old-space can expand to the
// size needed for the off-thread objects. Use capacity rather than size since
// we're adding entire pages.
size_t off_thread_size = space_.Capacity() + lo_space_.Size();
if (!heap->CanExpandOldGeneration(off_thread_size)) {
heap->CollectAllAvailableGarbage(GarbageCollectionReason::kLastResort);
if (!heap->CanExpandOldGeneration(off_thread_size)) {
heap->FatalProcessOutOfMemory(
"Can't expand old-space enough to merge off-thread pages.");
}
}
// Merging and transferring handles should be atomic from the point of view
// of the GC, since we neither want the GC to walk main-thread handles that
// point into off-thread pages, nor do we want the GC to move the raw
// pointers we have into off-thread pages before we've had a chance to turn
// them into real handles.
// TODO(leszeks): This could be a stronger assertion, that we don't GC at
// all.
DisallowHeapAllocation no_gc;
// Merge the spaces.
{
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.OffThreadFinalization.Publish.Merge");
heap->old_space()->MergeLocalSpace(&space_);
heap->lo_space()->MergeOffThreadSpace(&lo_space_);
DCHECK(heap->CanExpandOldGeneration(0));
}
// Transfer all the transfer handles to be real handles. Make sure to do this
// before creating any handle scopes, to allow these handles to live in the
// caller's handle scope.
OffThreadTransferHandleStorage* storage =
off_thread_transfer_handles_head_.get();
while (storage != nullptr) {
storage->ConvertToHandleOnPublish(isolate, &no_gc);
storage = storage->next();
}
// Create a new handle scope after transferring handles, for the slot holder
// handles below.
HandleScope handle_scope(isolate);
// Handlify all the string slot holder objects, so that we can keep track of
// them if they move.
//
// TODO(leszeks): We might be able to create a HandleScope-compatible
// structure off-thread and merge it into the current handle scope all in
// one go (PersistentHandles maybe?).
std::vector<std::pair<Handle<HeapObject>, Handle<Map>>> heap_object_handles;
std::vector<Handle<Script>> script_handles;
{
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.
HeapObject obj = HeapObject::FromAddress(relative_slot.object_address);
heap_object_handles.push_back(
{handle(obj, isolate), handle(obj.map(), isolate)});
// De-internalize the string so that we can re-internalize it later.
String string =
String::cast(RELAXED_READ_FIELD(obj, relative_slot.slot_offset));
bool one_byte = string.IsOneByteRepresentation();
Map map = one_byte ? roots.one_byte_string_map() : 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));
}
}
// After this point, all objects are transferred and all handles are valid,
// so we can GC again.
no_gc.Release();
// Possibly trigger a GC if we're close to exhausting the old generation.
// TODO(leszeks): Adjust the heuristics here.
heap->StartIncrementalMarkingIfAllocationLimitIsReached(
heap->GCFlagsForIncrementalMarking(),
kGCCallbackScheduleIdleGarbageCollection);
if (!heap->ShouldExpandOldGenerationOnSlowAllocation() ||
!heap->CanExpandOldGeneration(1 * MB)) {
heap->CollectGarbage(OLD_SPACE,
GarbageCollectionReason::kAllocationFailure);
}
// Iterate the string slots, as an offset from the holders we have handles to.
{
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.OffThreadFinalization.Publish.UpdateHandles");
for (size_t i = 0; i < string_slots_.size(); ++i) {
HeapObject obj = *heap_object_handles[i].first;
int slot_offset = string_slots_[i].slot_offset;
// There's currently no cases where the holder object could have been
// resized.
CHECK_EQ(obj.map(), *heap_object_handles[i].second);
CHECK_LT(slot_offset, obj.Size());
String string = String::cast(RELAXED_READ_FIELD(obj, slot_offset));
if (string.IsThinString()) {
// We may have already internalized this string via another slot.
String value = ThinString::cast(string).GetUnderlying();
RELAXED_WRITE_FIELD(obj, slot_offset, value);
WRITE_BARRIER(obj, slot_offset, value);
} else {
HandleScope handle_scope(isolate);
Handle<String> string_handle = handle(string, isolate);
Handle<String> internalized_string =
isolate->factory()->InternalizeString(string_handle);
DCHECK(string_handle->IsThinString() ||
string_handle->IsInternalizedString());
if (*string_handle != *internalized_string) {
// Re-read the object from the handle in case there was GC during
// internalization and it moved.
HeapObject obj = *heap_object_handles[i].first;
String value = *internalized_string;
// Sanity checks that the object or string slot value hasn't changed.
CHECK_EQ(obj.map(), *heap_object_handles[i].second);
CHECK_LT(slot_offset, obj.Size());
CHECK_EQ(RELAXED_READ_FIELD(obj, slot_offset), *string_handle);
RELAXED_WRITE_FIELD(obj, slot_offset, value);
WRITE_BARRIER(obj, slot_offset, value);
}
}
}
// 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));
}
heap->SetRootScriptList(*scripts);
}
}
void OffThreadHeap::AddToScriptList(Handle<Script> shared) {
script_list_.push_back(*shared);
}
HeapObject OffThreadHeap::AllocateRaw(int size, AllocationType allocation,
AllocationAlignment alignment) {
DCHECK(!is_finished);
DCHECK_EQ(allocation, AllocationType::kOld);
AllocationResult result;
if (size > kMaxRegularHeapObjectSize) {
result = lo_space_.AllocateRaw(size);
} else {
result = space_.AllocateRaw(size, alignment);
}
HeapObject obj = result.ToObjectChecked();
OnAllocationEvent(obj, size);
return obj;
}
bool OffThreadHeap::ReserveSpace(Heap::Reservation* reservations) {
#ifdef DEBUG
for (int space = FIRST_SPACE;
space < static_cast<int>(SnapshotSpace::kNumberOfHeapSpaces); space++) {
if (space == OLD_SPACE || space == LO_SPACE) continue;
Heap::Reservation* reservation = &reservations[space];
DCHECK_EQ(reservation->size(), 1);
DCHECK_EQ(reservation->at(0).size, 0);
}
#endif
for (auto& chunk : reservations[OLD_SPACE]) {
int size = chunk.size;
AllocationResult allocation = space_.AllocateRawUnaligned(size);
HeapObject free_space = allocation.ToObjectChecked();
// Mark with a free list node, in case we have a GC before
// deserializing.
Address free_space_address = free_space.address();
CreateFillerObjectAt(free_space_address, size,
ClearFreedMemoryMode::kDontClearFreedMemory);
chunk.start = free_space_address;
chunk.end = free_space_address + size;
}
return true;
}
HeapObject OffThreadHeap::CreateFillerObjectAt(
Address addr, int size, ClearFreedMemoryMode clear_memory_mode) {
ReadOnlyRoots roots(this);
HeapObject filler =
Heap::CreateFillerObjectAt(roots, addr, size, clear_memory_mode);
return filler;
}
OffThreadTransferHandleStorage* OffThreadHeap::AddTransferHandleStorage(
HandleBase handle) {
DCHECK_IMPLIES(off_thread_transfer_handles_head_ != nullptr,
off_thread_transfer_handles_head_->state() ==
OffThreadTransferHandleStorage::kOffThreadHandle);
off_thread_transfer_handles_head_ =
std::make_unique<OffThreadTransferHandleStorage>(
handle.location(), std::move(off_thread_transfer_handles_head_));
return off_thread_transfer_handles_head_.get();
}
} // namespace internal
} // namespace v8
// Undefine the heap manipulation macros.
#include "src/objects/object-macros-undef.h"

View File

@ -1,77 +0,0 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_OFF_THREAD_HEAP_H_
#define V8_HEAP_OFF_THREAD_HEAP_H_
#include <vector>
#include "src/common/globals.h"
#include "src/heap/large-spaces.h"
#include "src/heap/paged-spaces.h"
#include "src/heap/spaces.h"
#include "src/objects/heap-object.h"
namespace v8 {
namespace internal {
class OffThreadTransferHandleStorage;
class V8_EXPORT_PRIVATE OffThreadHeap {
public:
explicit OffThreadHeap(Heap* heap);
~OffThreadHeap();
HeapObject AllocateRaw(int size, AllocationType allocation,
AllocationAlignment alignment = kWordAligned);
void AddToScriptList(Handle<Script> shared);
void OnAllocationEvent(HeapObject obj, int size) {
// TODO(leszeks): Do something here.
}
ReadOnlySpace* read_only_space() const {
// Access the main-thread heap via the spaces.
return space_.heap()->read_only_space();
}
bool Contains(HeapObject obj);
bool ReserveSpace(Heap::Reservation* reservations);
HeapObject CreateFillerObjectAt(Address addr, int size,
ClearFreedMemoryMode clear_memory_mode);
OffThreadTransferHandleStorage* AddTransferHandleStorage(HandleBase handle);
void FinishOffThread();
void Publish(Heap* heap);
private:
friend class DeserializerAllocator;
class StringSlotCollectingVisitor;
struct RelativeSlot {
RelativeSlot() = default;
RelativeSlot(Address object_address, int slot_offset)
: object_address(object_address), slot_offset(slot_offset) {}
Address object_address;
int slot_offset;
};
OffThreadSpace space_;
OffThreadLargeObjectSpace lo_space_;
std::vector<RelativeSlot> string_slots_;
std::vector<Script> script_list_;
std::unique_ptr<OffThreadTransferHandleStorage>
off_thread_transfer_handles_head_;
bool is_finished = false;
};
} // namespace internal
} // namespace v8
#endif // V8_HEAP_OFF_THREAD_HEAP_H_

View File

@ -52,15 +52,6 @@ PagedSpaceObjectIterator::PagedSpaceObjectIterator(Heap* heap,
#endif // DEBUG
}
PagedSpaceObjectIterator::PagedSpaceObjectIterator(OffThreadSpace* space)
: cur_addr_(kNullAddress),
cur_end_(kNullAddress),
space_(space),
page_range_(space->first_page(), nullptr),
current_page_(page_range_.begin()) {
space_->MakeLinearAllocationAreaIterable();
}
// We have hit the end of the page and should advance to the next block of
// objects. This happens at the end of the page.
bool PagedSpaceObjectIterator::AdvanceToNextPage() {
@ -80,8 +71,7 @@ Page* PagedSpace::InitializePage(MemoryChunk* chunk) {
page->area_size());
// Make sure that categories are initialized before freeing the area.
page->ResetAllocationStatistics();
page->SetOldGenerationPageFlags(!is_off_thread_space() &&
heap()->incremental_marking()->IsMarking());
page->SetOldGenerationPageFlags(heap()->incremental_marking()->IsMarking());
page->AllocateFreeListCategories();
page->InitializeFreeListCategories();
page->list_node().Initialize();
@ -115,7 +105,6 @@ void PagedSpace::RefillFreeList() {
identity() != MAP_SPACE) {
return;
}
DCHECK_NE(local_space_kind(), LocalSpaceKind::kOffThreadSpace);
DCHECK_IMPLIES(is_local_space(), is_compaction_space());
MarkCompactCollector* collector = heap()->mark_compact_collector();
size_t added = 0;
@ -160,12 +149,6 @@ void PagedSpace::RefillFreeList() {
}
}
void OffThreadSpace::RefillFreeList() {
// We should never try to refill the free list in off-thread space, because
// we know it will always be fully linear.
UNREACHABLE();
}
void PagedSpace::MergeLocalSpace(LocalSpace* other) {
base::MutexGuard guard(mutex());
@ -184,29 +167,11 @@ void PagedSpace::MergeLocalSpace(LocalSpace* other) {
DCHECK_EQ(kNullAddress, other->top());
DCHECK_EQ(kNullAddress, other->limit());
bool merging_from_off_thread = other->is_off_thread_space();
// Move over pages.
for (auto it = other->begin(); it != other->end();) {
Page* p = *(it++);
if (merging_from_off_thread) {
DCHECK_NULL(p->sweeping_slot_set());
// Make sure the page is entirely white.
CHECK(heap()
->incremental_marking()
->non_atomic_marking_state()
->bitmap(p)
->IsClean());
p->SetOldGenerationPageFlags(heap()->incremental_marking()->IsMarking());
if (heap()->incremental_marking()->black_allocation()) {
p->CreateBlackArea(p->area_start(), p->HighWaterMark());
}
} else {
p->MergeOldToNewRememberedSets();
}
// Ensure that pages are initialized before objects on it are discovered by
// concurrent markers.
@ -369,7 +334,7 @@ int PagedSpace::CountTotalPages() {
void PagedSpace::SetLinearAllocationArea(Address top, Address limit) {
SetTopAndLimit(top, limit);
if (top != kNullAddress && top != limit && !is_off_thread_space() &&
if (top != kNullAddress && top != limit &&
heap()->incremental_marking()->black_allocation()) {
Page::FromAllocationAreaAddress(top)->CreateBlackArea(top, limit);
}
@ -450,7 +415,7 @@ void PagedSpace::FreeLinearAllocationArea() {
AdvanceAllocationObservers();
if (current_top != current_limit && !is_off_thread_space() &&
if (current_top != current_limit &&
heap()->incremental_marking()->black_allocation()) {
Page::FromAddress(current_top)
->DestroyBlackArea(current_top, current_limit);
@ -867,19 +832,6 @@ bool CompactionSpace::RefillLabMain(int size_in_bytes,
return RawRefillLabMain(size_in_bytes, origin);
}
bool OffThreadSpace::RefillLabMain(int size_in_bytes, AllocationOrigin origin) {
if (TryAllocationFromFreeListMain(size_in_bytes, origin)) return true;
if (heap()->CanExpandOldGenerationBackground(size_in_bytes) && Expand()) {
DCHECK((CountTotalPages() > 1) ||
(static_cast<size_t>(size_in_bytes) <= free_list_->Available()));
return TryAllocationFromFreeListMain(static_cast<size_t>(size_in_bytes),
origin);
}
return false;
}
bool PagedSpace::RawRefillLabMain(int size_in_bytes, AllocationOrigin origin) {
// Non-compaction local spaces are not supported.
DCHECK_IMPLIES(is_local_space(), is_compaction_space());

View File

@ -25,7 +25,6 @@ class Heap;
class HeapObject;
class Isolate;
class LocalSpace;
class OffThreadSpace;
class ObjectVisitor;
// -----------------------------------------------------------------------------
@ -43,9 +42,6 @@ class V8_EXPORT_PRIVATE PagedSpaceObjectIterator : public ObjectIterator {
PagedSpaceObjectIterator(Heap* heap, PagedSpace* space);
PagedSpaceObjectIterator(Heap* heap, PagedSpace* space, Page* page);
// Creates a new object iterator in a given off-thread space.
explicit PagedSpaceObjectIterator(OffThreadSpace* space);
// Advance to the next object, skipping free spaces and other fillers and
// skipping the special garbage section of which there is one per space.
// Returns nullptr when the iteration has ended.
@ -262,10 +258,6 @@ class V8_EXPORT_PRIVATE PagedSpace
bool is_local_space() { return local_space_kind_ != LocalSpaceKind::kNone; }
bool is_off_thread_space() {
return local_space_kind_ == LocalSpaceKind::kOffThreadSpace;
}
bool is_compaction_space() {
return base::IsInRange(local_space_kind_,
LocalSpaceKind::kFirstCompactionSpace,
@ -531,27 +523,6 @@ class MapSpace : public PagedSpace {
#endif
};
// -----------------------------------------------------------------------------
// Off-thread space that is used for folded allocation on a different thread.
class V8_EXPORT_PRIVATE OffThreadSpace : public LocalSpace {
public:
explicit OffThreadSpace(Heap* heap)
: LocalSpace(heap, OLD_SPACE, NOT_EXECUTABLE,
LocalSpaceKind::kOffThreadSpace) {
#ifdef V8_ENABLE_THIRD_PARTY_HEAP
// OffThreadSpace doesn't work with third-party heap.
UNREACHABLE();
#endif
}
protected:
V8_WARN_UNUSED_RESULT bool RefillLabMain(int size_in_bytes,
AllocationOrigin origin) override;
void RefillFreeList() override;
};
// Iterates over the chunks (pages and large object pages) that can contain
// pointers to new space or to evacuation candidates.
class OldGenerationMemoryChunkIterator {

View File

@ -10,6 +10,7 @@
#include "src/common/globals.h"
#include "src/heap/heap-inl.h"
#include "src/heap/incremental-marking.h"
#include "src/heap/large-spaces.h"
#include "src/heap/memory-chunk-inl.h"
#include "src/heap/new-spaces.h"
#include "src/heap/paged-spaces.h"

View File

@ -107,7 +107,7 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
#ifdef DEBUG
int BytecodeArrayBuilder::CheckBytecodeMatches(BytecodeArray bytecode) {
@ -129,7 +129,7 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
Bytecode bytecode) {

View File

@ -5,7 +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/heap/local-factory-inl.h"
#include "src/interpreter/bytecode-jump-table.h"
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-node.h"
@ -60,7 +60,7 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<ByteArray> handler_table);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
OffThreadIsolate* isolate, int register_count, int parameter_count,
LocalIsolate* isolate, int register_count, int parameter_count,
Handle<ByteArray> handler_table);
template <typename LocalIsolate>
@ -79,7 +79,7 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<ByteArray> BytecodeArrayWriter::ToSourcePositionTable(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
#ifdef DEBUG
int BytecodeArrayWriter::CheckBytecodeMatches(BytecodeArray bytecode) {

View File

@ -16,8 +16,8 @@
#include "src/interpreter/bytecode-register-allocator.h"
#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/control-flow-builders.h"
#include "src/logging/local-logger.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"
@ -1090,10 +1090,10 @@ struct NullContextScopeHelper<Isolate> {
};
template <>
struct NullContextScopeHelper<OffThreadIsolate> {
struct NullContextScopeHelper<LocalIsolate> {
class DummyNullContextScope {
public:
explicit DummyNullContextScope(OffThreadIsolate*) {}
explicit DummyNullContextScope(LocalIsolate*) {}
};
using Type = DummyNullContextScope;
};
@ -1139,7 +1139,7 @@ Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
template Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
Isolate* isolate, Handle<Script> script);
template Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
OffThreadIsolate* isolate, Handle<Script> script);
LocalIsolate* isolate, Handle<Script> script);
template <typename LocalIsolate>
Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
@ -1165,7 +1165,7 @@ Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
template Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
Isolate* isolate);
template Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
#ifdef DEBUG
int BytecodeGenerator::CheckBytecodeMatches(BytecodeArray bytecode) {
@ -1258,7 +1258,7 @@ void BytecodeGenerator::AllocateDeferredConstants(LocalIsolate* isolate,
template void BytecodeGenerator::AllocateDeferredConstants(
Isolate* isolate, Handle<Script> script);
template void BytecodeGenerator::AllocateDeferredConstants(
OffThreadIsolate* isolate, Handle<Script> script);
LocalIsolate* isolate, Handle<Script> script);
namespace {
bool NeedsContextInitialization(DeclarationScope* scope) {

View File

@ -13,7 +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/heap/local-factory-inl.h"
#include "src/objects/objects-inl.h"
namespace v8 {
@ -180,8 +180,8 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
MaybeHandle<Object> ConstantArrayBuilder::At(size_t index,
Isolate* isolate) const;
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
MaybeHandle<Object> ConstantArrayBuilder::At(
size_t index, OffThreadIsolate* isolate) const;
MaybeHandle<Object> ConstantArrayBuilder::At(size_t index,
LocalIsolate* isolate) const;
template <typename LocalIsolate>
Handle<FixedArray> ConstantArrayBuilder::ToFixedArray(LocalIsolate* isolate) {
@ -218,7 +218,7 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<FixedArray> ConstantArrayBuilder::ToFixedArray(Isolate* isolate);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<FixedArray> ConstantArrayBuilder::ToFixedArray(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
size_t ConstantArrayBuilder::Insert(Smi smi) {
auto entry = smi_map_.find(smi);
@ -410,7 +410,7 @@ Handle<Object> ConstantArrayBuilder::Entry::ToHandle(
template Handle<Object> ConstantArrayBuilder::Entry::ToHandle(
Isolate* isolate) const;
template Handle<Object> ConstantArrayBuilder::Entry::ToHandle(
OffThreadIsolate* isolate) const;
LocalIsolate* isolate) const;
} // namespace interpreter
} // namespace internal

View File

@ -35,7 +35,7 @@ Handle<ByteArray> HandlerTableBuilder::ToHandlerTable(LocalIsolate* isolate) {
template Handle<ByteArray> HandlerTableBuilder::ToHandlerTable(
Isolate* isolate);
template Handle<ByteArray> HandlerTableBuilder::ToHandlerTable(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
int HandlerTableBuilder::NewHandlerEntry() {
int handler_id = static_cast<int>(entries_.size());

View File

@ -12,7 +12,6 @@
#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"
@ -42,7 +41,7 @@ class InterpreterCompilationJob final : public UnoptimizedCompilationJob {
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) final;
Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
OffThreadIsolate* isolate) final;
LocalIsolate* isolate) final;
private:
BytecodeGenerator* generator() { return &generator_; }
@ -225,7 +224,7 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
}
InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
Handle<SharedFunctionInfo> shared_info, OffThreadIsolate* isolate) {
Handle<SharedFunctionInfo> shared_info, LocalIsolate* isolate) {
RuntimeCallTimerScope runtimeTimerScope(
parse_info()->runtime_call_stats(),
RuntimeCallCounterId::kCompileBackgroundIgnitionFinalization);

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_LOGGING_OFF_THREAD_LOGGER_H_
#define V8_LOGGING_OFF_THREAD_LOGGER_H_
#ifndef V8_LOGGING_LOCAL_LOGGER_H_
#define V8_LOGGING_LOCAL_LOGGER_H_
#include "src/base/logging.h"
#include "src/logging/log.h"
@ -12,7 +12,7 @@ namespace v8 {
namespace internal {
// TODO(leszeks): Add support for logging from off-thread.
class OffThreadLogger {
class LocalLogger {
public:
bool is_logging() const { return false; }
bool is_listening_to_code_events() const { return false; }
@ -29,4 +29,4 @@ class OffThreadLogger {
} // namespace internal
} // namespace v8
#endif // V8_LOGGING_OFF_THREAD_LOGGER_H_
#endif // V8_LOGGING_LOCAL_LOGGER_H_

View File

@ -21,6 +21,7 @@
#include "src/execution/vm-state-inl.h"
#include "src/handles/global-handles.h"
#include "src/heap/combined-heap.h"
#include "src/heap/heap-inl.h"
#include "src/init/bootstrapper.h"
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/interpreter.h"
@ -1767,14 +1768,12 @@ static int EnumerateCompiledFunctions(Heap* heap,
DisallowHeapAllocation no_gc;
int compiled_funcs_count = 0;
// Iterate the heap to find shared function info objects and record
// the unoptimized code for them.
// Iterate the heap to find JSFunctions and record their optimized code.
for (HeapObject obj = iterator.Next(); !obj.is_null();
obj = iterator.Next()) {
if (obj.IsSharedFunctionInfo()) {
SharedFunctionInfo sfi = SharedFunctionInfo::cast(obj);
if (sfi.is_compiled() && (!sfi.script().IsScript() ||
Script::cast(sfi.script()).HasValidSource())) {
if (sfi.is_compiled() && !sfi.IsInterpreted()) {
AddFunctionAndCode(sfi, AbstractCode::cast(sfi.abstract_code()), sfis,
code_objects, compiled_funcs_count);
++compiled_funcs_count;
@ -1783,22 +1782,35 @@ static int EnumerateCompiledFunctions(Heap* heap,
// Given that we no longer iterate over all optimized JSFunctions, we need
// to take care of this here.
JSFunction function = JSFunction::cast(obj);
SharedFunctionInfo sfi = SharedFunctionInfo::cast(function.shared());
Object maybe_script = sfi.script();
if (maybe_script.IsScript() &&
!Script::cast(maybe_script).HasValidSource()) {
continue;
}
// TODO(jarin) This leaves out deoptimized code that might still be on the
// stack. Also note that we will not log optimized code objects that are
// only on a type feedback vector. We should make this more precise.
if (function.HasAttachedOptimizedCode()) {
AddFunctionAndCode(sfi, AbstractCode::cast(function.code()), sfis,
// only on a type feedback vector. We should make this mroe precise.
if (function.HasAttachedOptimizedCode() &&
Script::cast(function.shared().script()).HasValidSource()) {
AddFunctionAndCode(function.shared(),
AbstractCode::cast(function.code()), sfis,
code_objects, compiled_funcs_count);
++compiled_funcs_count;
}
}
}
Script::Iterator script_iterator(heap->isolate());
for (Script script = script_iterator.Next(); !script.is_null();
script = script_iterator.Next()) {
if (!script.HasValidSource()) continue;
SharedFunctionInfo::ScriptIterator sfi_iterator(heap->isolate(), script);
for (SharedFunctionInfo sfi = sfi_iterator.Next(); !sfi.is_null();
sfi = sfi_iterator.Next()) {
if (sfi.is_compiled()) {
AddFunctionAndCode(sfi, AbstractCode::cast(sfi.abstract_code()), sfis,
code_objects, compiled_funcs_count);
++compiled_funcs_count;
}
}
}
return compiled_funcs_count;
}

View File

@ -6,10 +6,10 @@
#include <limits.h>
#include <stdarg.h>
#include <cmath>
#include "src/common/assert-scope.h"
#include "src/execution/off-thread-isolate.h"
#include "src/handles/handles.h"
#include "src/heap/factory.h"
#include "src/numbers/dtoa.h"
@ -932,7 +932,7 @@ MaybeHandle<BigInt> BigIntLiteral(LocalIsolate* isolate, const char* string) {
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate, const char* string);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
MaybeHandle<BigInt> BigIntLiteral(OffThreadIsolate* isolate,
MaybeHandle<BigInt> BigIntLiteral(LocalIsolate* isolate,
const char* string);
const char* DoubleToCString(double v, Vector<char> buffer) {

View File

@ -20,7 +20,6 @@
#include "src/objects/bigint.h"
#include "src/execution/isolate-inl.h"
#include "src/execution/off-thread-isolate.h"
#include "src/heap/factory.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/numbers/conversions.h"
@ -418,10 +417,10 @@ template <typename LocalIsolate>
Handle<BigInt> BigInt::Zero(LocalIsolate* isolate, AllocationType allocation) {
return MutableBigInt::Zero(isolate, allocation);
}
template Handle<BigInt> BigInt::Zero<Isolate>(Isolate* isolate,
AllocationType allocation);
template Handle<BigInt> BigInt::Zero<OffThreadIsolate>(
OffThreadIsolate* isolate, AllocationType allocation);
template Handle<BigInt> BigInt::Zero(Isolate* isolate,
AllocationType allocation);
template Handle<BigInt> BigInt::Zero(LocalIsolate* isolate,
AllocationType allocation);
Handle<BigInt> BigInt::UnaryMinus(Isolate* isolate, Handle<BigInt> x) {
// Special case: There is no -0n.
@ -1952,13 +1951,12 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
return MaybeHandle<FreshlyAllocatedBigInt>();
}
}
template MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor<Isolate>(
template MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
Isolate* isolate, int radix, int charcount, ShouldThrow should_throw,
AllocationType allocation);
template MaybeHandle<FreshlyAllocatedBigInt>
BigInt::AllocateFor<OffThreadIsolate>(OffThreadIsolate* isolate, int radix,
int charcount, ShouldThrow should_throw,
AllocationType allocation);
template MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
LocalIsolate* isolate, int radix, int charcount, ShouldThrow should_throw,
AllocationType allocation);
template <typename LocalIsolate>
Handle<BigInt> BigInt::Finalize(Handle<FreshlyAllocatedBigInt> x, bool sign) {
@ -1969,7 +1967,7 @@ Handle<BigInt> BigInt::Finalize(Handle<FreshlyAllocatedBigInt> x, bool sign) {
template Handle<BigInt> BigInt::Finalize<Isolate>(
Handle<FreshlyAllocatedBigInt>, bool);
template Handle<BigInt> BigInt::Finalize<OffThreadIsolate>(
template Handle<BigInt> BigInt::Finalize<LocalIsolate>(
Handle<FreshlyAllocatedBigInt>, bool);
// The serialization format MUST NOT CHANGE without updating the format

View File

@ -5,10 +5,9 @@
#ifndef V8_OBJECTS_DICTIONARY_INL_H_
#define V8_OBJECTS_DICTIONARY_INL_H_
#include "src/objects/dictionary.h"
#include "src/execution/isolate-utils-inl.h"
#include "src/numbers/hash-seed-inl.h"
#include "src/objects/dictionary.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/oddball.h"
@ -260,7 +259,7 @@ Handle<Object> NumberDictionaryBaseShape::AsHandle(Isolate* isolate,
return isolate->factory()->NewNumberFromUint(key);
}
Handle<Object> NumberDictionaryBaseShape::AsHandle(OffThreadIsolate* isolate,
Handle<Object> NumberDictionaryBaseShape::AsHandle(LocalIsolate* isolate,
uint32_t key) {
return isolate->factory()->NewNumberFromUint<AllocationType::kOld>(key);
}
@ -303,7 +302,7 @@ Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
return key;
}
Handle<Object> NameDictionaryShape::AsHandle(OffThreadIsolate* isolate,
Handle<Object> NameDictionaryShape::AsHandle(LocalIsolate* isolate,
Handle<Name> key) {
DCHECK(key->IsUniqueName());
return key;

View File

@ -112,7 +112,7 @@ class NameDictionaryShape : public BaseDictionaryShape<Handle<Name>> {
static inline uint32_t Hash(ReadOnlyRoots roots, Handle<Name> key);
static inline uint32_t HashForObject(ReadOnlyRoots roots, Object object);
static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key);
static inline Handle<Object> AsHandle(OffThreadIsolate* isolate,
static inline Handle<Object> AsHandle(LocalIsolate* isolate,
Handle<Name> key);
static const int kPrefixSize = 2;
static const int kEntrySize = 3;
@ -253,8 +253,7 @@ class NumberDictionaryBaseShape : public BaseDictionaryShape<uint32_t> {
public:
static inline bool IsMatch(uint32_t key, Object other);
static inline Handle<Object> AsHandle(Isolate* isolate, uint32_t key);
static inline Handle<Object> AsHandle(OffThreadIsolate* isolate,
uint32_t key);
static inline Handle<Object> AsHandle(LocalIsolate* isolate, uint32_t key);
static inline uint32_t Hash(ReadOnlyRoots roots, uint32_t key);
static inline uint32_t HashForObject(ReadOnlyRoots roots, Object object);

View File

@ -3,8 +3,9 @@
// found in the LICENSE file.
#include "src/objects/feedback-vector.h"
#include "src/diagnostics/code-tracer.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/ic/ic-inl.h"
#include "src/objects/data-handler-inl.h"
@ -117,7 +118,7 @@ Handle<FeedbackMetadata> FeedbackMetadata::New(LocalIsolate* isolate,
template Handle<FeedbackMetadata> FeedbackMetadata::New(
Isolate* isolate, const FeedbackVectorSpec* spec);
template Handle<FeedbackMetadata> FeedbackMetadata::New(
OffThreadIsolate* isolate, const FeedbackVectorSpec* spec);
LocalIsolate* isolate, const FeedbackVectorSpec* spec);
bool FeedbackMetadata::SpecDiffersFrom(
const FeedbackVectorSpec* other_spec) const {

View File

@ -5,11 +5,10 @@
#ifndef V8_OBJECTS_FREE_SPACE_INL_H_
#define V8_OBJECTS_FREE_SPACE_INL_H_
#include "src/objects/free-space.h"
#include "src/execution/isolate.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/heap.h"
#include "src/objects/free-space.h"
#include "src/objects/objects-inl.h"
// Has to be the last include (doesn't have include guards):
@ -36,8 +35,7 @@ void FreeSpace::set_next(FreeSpace next) {
}
FreeSpace FreeSpace::cast(HeapObject o) {
SLOW_DCHECK((!Heap::InOffThreadSpace(o) &&
!GetHeapFromWritableObject(o)->deserialization_complete()) ||
SLOW_DCHECK((!GetHeapFromWritableObject(o)->deserialization_complete()) ||
o.IsFreeSpace());
return bit_cast<FreeSpace>(o);
}

View File

@ -271,15 +271,15 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable
HashTable<DERIVED, SHAPE>::New(Isolate*, int, AllocationType, \
MinimumCapacity); \
extern template EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) Handle<DERIVED> \
HashTable<DERIVED, SHAPE>::New(OffThreadIsolate*, int, AllocationType, \
HashTable<DERIVED, SHAPE>::New(LocalIsolate*, int, AllocationType, \
MinimumCapacity); \
\
extern template EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) Handle<DERIVED> \
HashTable<DERIVED, SHAPE>::EnsureCapacity(Isolate*, Handle<DERIVED>, int, \
AllocationType); \
extern template EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) Handle<DERIVED> \
HashTable<DERIVED, SHAPE>::EnsureCapacity( \
OffThreadIsolate*, Handle<DERIVED>, int, AllocationType);
HashTable<DERIVED, SHAPE>::EnsureCapacity(LocalIsolate*, Handle<DERIVED>, \
int, AllocationType);
// HashTableKey is an abstract superclass for virtual key behavior.
class HashTableKey {

View File

@ -84,10 +84,10 @@ class HeapObject : public Object {
// Oddball checks are faster when they are raw pointer comparisons, so the
// isolate/read-only roots overloads should be preferred where possible.
#define IS_TYPE_FUNCTION_DECL(Type, Value) \
V8_INLINE bool Is##Type(Isolate* isolate) const; \
V8_INLINE bool Is##Type(OffThreadIsolate* isolate) const; \
V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \
#define IS_TYPE_FUNCTION_DECL(Type, Value) \
V8_INLINE bool Is##Type(Isolate* isolate) const; \
V8_INLINE bool Is##Type(LocalIsolate* isolate) const; \
V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \
V8_INLINE bool Is##Type() const;
ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(NullOrUndefined, /* unused */)
@ -191,7 +191,7 @@ class HeapObject : public Object {
bool CanBeRehashed() const;
// Rehash the object based on the layout inferred from its map.
void RehashBasedOnMap(LocalIsolateWrapper isolate);
void RehashBasedOnMap(Isolate* isolate);
// Layout description.
#define HEAP_OBJECT_FIELDS(V) \

View File

@ -10,7 +10,7 @@
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/heap/factory.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/objects/dictionary.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/literal-objects-inl.h"
@ -412,9 +412,8 @@ template void ClassBoilerplate::AddToPropertiesTemplate(
Isolate* isolate, Handle<NameDictionary> dictionary, Handle<Name> name,
int key_index, ClassBoilerplate::ValueKind value_kind, Smi value);
template void ClassBoilerplate::AddToPropertiesTemplate(
OffThreadIsolate* isolate, Handle<NameDictionary> dictionary,
Handle<Name> name, int key_index, ClassBoilerplate::ValueKind value_kind,
Smi value);
LocalIsolate* isolate, Handle<NameDictionary> dictionary, Handle<Name> name,
int key_index, ClassBoilerplate::ValueKind value_kind, Smi value);
template <typename LocalIsolate>
void ClassBoilerplate::AddToElementsTemplate(
@ -427,9 +426,8 @@ template void ClassBoilerplate::AddToElementsTemplate(
Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t key,
int key_index, ClassBoilerplate::ValueKind value_kind, Smi value);
template void ClassBoilerplate::AddToElementsTemplate(
OffThreadIsolate* isolate, Handle<NumberDictionary> dictionary,
uint32_t key, int key_index, ClassBoilerplate::ValueKind value_kind,
Smi value);
LocalIsolate* isolate, Handle<NumberDictionary> dictionary, uint32_t key,
int key_index, ClassBoilerplate::ValueKind value_kind, Smi value);
template <typename LocalIsolate>
Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
@ -601,7 +599,7 @@ Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
template Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
Isolate* isolate, ClassLiteral* expr);
template Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
OffThreadIsolate* isolate, ClassLiteral* expr);
LocalIsolate* isolate, ClassLiteral* expr);
} // namespace internal
} // namespace v8

View File

@ -6,7 +6,6 @@
#define V8_OBJECTS_MAYBE_OBJECT_INL_H_
#include "src/common/ptr-compr-inl.h"
#include "src/execution/local-isolate-wrapper.h"
#include "src/objects/maybe-object.h"
#include "src/objects/smi-inl.h"
#include "src/objects/tagged-impl-inl.h"
@ -72,30 +71,6 @@ HeapObjectReference HeapObjectReference::ClearedValue(const Isolate* isolate) {
return HeapObjectReference(raw_value);
}
// static
HeapObjectReference HeapObjectReference::ClearedValue(
const OffThreadIsolate* isolate) {
// Construct cleared weak ref value.
#ifdef V8_COMPRESS_POINTERS
// This is necessary to make pointer decompression computation also
// suitable for cleared weak references.
Address raw_value =
DecompressTaggedPointer(isolate, kClearedWeakHeapObjectLower32);
#else
Address raw_value = kClearedWeakHeapObjectLower32;
#endif
// The rest of the code will check only the lower 32-bits.
DCHECK_EQ(kClearedWeakHeapObjectLower32, static_cast<uint32_t>(raw_value));
return HeapObjectReference(raw_value);
}
// static
HeapObjectReference HeapObjectReference::ClearedValue(
LocalIsolateWrapper isolate) {
return isolate.is_off_thread() ? ClearedValue(isolate.off_thread())
: ClearedValue(isolate.main_thread());
}
template <typename THeapObjectSlot>
void HeapObjectReference::Update(THeapObjectSlot slot, HeapObject value) {
static_assert(std::is_same<THeapObjectSlot, FullHeapObjectSlot>::value ||

View File

@ -5,7 +5,6 @@
#ifndef V8_OBJECTS_MAYBE_OBJECT_H_
#define V8_OBJECTS_MAYBE_OBJECT_H_
#include "src/execution/local-isolate-wrapper.h"
#include "src/objects/tagged-impl.h"
namespace v8 {
@ -50,12 +49,6 @@ class HeapObjectReference : public MaybeObject {
V8_INLINE static HeapObjectReference ClearedValue(const Isolate* isolate);
V8_INLINE static HeapObjectReference ClearedValue(
const OffThreadIsolate* isolate);
V8_INLINE static HeapObjectReference ClearedValue(
LocalIsolateWrapper isolate);
template <typename THeapObjectSlot>
V8_INLINE static void Update(THeapObjectSlot slot, HeapObject value);
};

View File

@ -12,8 +12,6 @@
#ifndef V8_OBJECTS_OBJECTS_INL_H_
#define V8_OBJECTS_OBJECTS_INL_H_
#include "src/objects/objects.h"
#include "src/base/bits.h"
#include "src/base/memory.h"
#include "src/builtins/builtins.h"
@ -30,6 +28,7 @@
#include "src/objects/keys.h"
#include "src/objects/literal-objects.h"
#include "src/objects/lookup-inl.h" // TODO(jkummerow): Drop.
#include "src/objects/objects.h"
#include "src/objects/oddball.h"
#include "src/objects/property-details.h"
#include "src/objects/property.h"
@ -91,7 +90,7 @@ IS_TYPE_FUNCTION_DEF(SmallOrderedHashTable)
bool Object::Is##Type(Isolate* isolate) const { \
return Is##Type(ReadOnlyRoots(isolate)); \
} \
bool Object::Is##Type(OffThreadIsolate* isolate) const { \
bool Object::Is##Type(LocalIsolate* isolate) const { \
return Is##Type(ReadOnlyRoots(isolate)); \
} \
bool Object::Is##Type(ReadOnlyRoots roots) const { \
@ -103,7 +102,7 @@ IS_TYPE_FUNCTION_DEF(SmallOrderedHashTable)
bool HeapObject::Is##Type(Isolate* isolate) const { \
return Object::Is##Type(isolate); \
} \
bool HeapObject::Is##Type(OffThreadIsolate* isolate) const { \
bool HeapObject::Is##Type(LocalIsolate* isolate) const { \
return Object::Is##Type(isolate); \
} \
bool HeapObject::Is##Type(ReadOnlyRoots roots) const { \

View File

@ -34,11 +34,10 @@
#include "src/execution/isolate-utils-inl.h"
#include "src/execution/isolate-utils.h"
#include "src/execution/microtask-queue.h"
#include "src/execution/off-thread-isolate.h"
#include "src/execution/protectors-inl.h"
#include "src/heap/factory-inl.h"
#include "src/heap/heap-inl.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/heap/read-only-heap.h"
#include "src/ic/ic.h"
#include "src/init/bootstrapper.h"
@ -72,6 +71,7 @@
#include "src/objects/objects-inl.h"
#include "src/objects/property-details.h"
#include "src/roots/roots.h"
#include "src/snapshot/deserializer.h"
#include "src/utils/identity-map.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-break-iterator.h"
@ -2354,22 +2354,21 @@ bool HeapObject::CanBeRehashed() const {
return false;
}
void HeapObject::RehashBasedOnMap(LocalIsolateWrapper isolate) {
const Isolate* ptr_cmp_isolate = GetIsolateForPtrCompr(isolate);
void HeapObject::RehashBasedOnMap(Isolate* isolate) {
switch (map().instance_type()) {
case HASH_TABLE_TYPE:
UNREACHABLE();
case NAME_DICTIONARY_TYPE:
NameDictionary::cast(*this).Rehash(ptr_cmp_isolate);
NameDictionary::cast(*this).Rehash(isolate);
break;
case GLOBAL_DICTIONARY_TYPE:
GlobalDictionary::cast(*this).Rehash(ptr_cmp_isolate);
GlobalDictionary::cast(*this).Rehash(isolate);
break;
case NUMBER_DICTIONARY_TYPE:
NumberDictionary::cast(*this).Rehash(ptr_cmp_isolate);
NumberDictionary::cast(*this).Rehash(isolate);
break;
case SIMPLE_NUMBER_DICTIONARY_TYPE:
SimpleNumberDictionary::cast(*this).Rehash(ptr_cmp_isolate);
SimpleNumberDictionary::cast(*this).Rehash(isolate);
break;
case DESCRIPTOR_ARRAY_TYPE:
DCHECK_LE(1, DescriptorArray::cast(*this).number_of_descriptors());
@ -2388,13 +2387,11 @@ void HeapObject::RehashBasedOnMap(LocalIsolateWrapper isolate) {
case ORDERED_HASH_SET_TYPE:
UNREACHABLE(); // We'll rehash from the JSMap or JSSet referencing them.
case JS_MAP_TYPE: {
DCHECK(isolate.is_main_thread());
JSMap::cast(*this).Rehash(isolate.main_thread());
JSMap::cast(*this).Rehash(isolate);
break;
}
case JS_SET_TYPE: {
DCHECK(isolate.is_main_thread());
JSSet::cast(*this).Rehash(isolate.main_thread());
JSSet::cast(*this).Rehash(isolate);
break;
}
case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
@ -4298,7 +4295,7 @@ template Handle<DescriptorArray> DescriptorArray::Allocate(
Isolate* isolate, int nof_descriptors, int slack,
AllocationType allocation);
template Handle<DescriptorArray> DescriptorArray::Allocate(
OffThreadIsolate* isolate, int nof_descriptors, int slack,
LocalIsolate* isolate, int nof_descriptors, int slack,
AllocationType allocation);
void DescriptorArray::Initialize(EnumCache enum_cache,
@ -4754,7 +4751,7 @@ void Script::InitLineEnds(LocalIsolate* isolate, Handle<Script> script) {
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Script::InitLineEnds(
Isolate* isolate, Handle<Script> script);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Script::InitLineEnds(
OffThreadIsolate* isolate, Handle<Script> script);
LocalIsolate* isolate, Handle<Script> script);
bool Script::GetPositionInfo(Handle<Script> script, int position,
PositionInfo* info, OffsetFlag offset_flag) {
@ -4939,7 +4936,7 @@ MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
template MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
Isolate* isolate, int function_literal_id);
template MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
OffThreadIsolate* isolate, int function_literal_id);
LocalIsolate* isolate, int function_literal_id);
Script::Iterator::Iterator(Isolate* isolate)
: iterator_(isolate->heap()->script_list()) {}
@ -7153,15 +7150,15 @@ Address Smi::LexicographicCompare(Isolate* isolate, Smi x, Smi y) {
HashTable<DERIVED, SHAPE>::New(Isolate*, int, AllocationType, \
MinimumCapacity); \
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) Handle<DERIVED> \
HashTable<DERIVED, SHAPE>::New(OffThreadIsolate*, int, AllocationType, \
HashTable<DERIVED, SHAPE>::New(LocalIsolate*, int, AllocationType, \
MinimumCapacity); \
\
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) Handle<DERIVED> \
HashTable<DERIVED, SHAPE>::EnsureCapacity(Isolate*, Handle<DERIVED>, int, \
AllocationType); \
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) Handle<DERIVED> \
HashTable<DERIVED, SHAPE>::EnsureCapacity( \
OffThreadIsolate*, Handle<DERIVED>, int, AllocationType);
HashTable<DERIVED, SHAPE>::EnsureCapacity(LocalIsolate*, Handle<DERIVED>, \
int, AllocationType);
#define EXTERN_DEFINE_OBJECT_BASE_HASH_TABLE(DERIVED, SHAPE) \
EXTERN_DEFINE_HASH_TABLE(DERIVED, SHAPE) \
@ -7177,7 +7174,7 @@ Address Smi::LexicographicCompare(Isolate* isolate, Smi x, Smi y) {
Isolate* isolate, Handle<DERIVED>, Key, Handle<Object>, PropertyDetails, \
InternalIndex*); \
template V8_EXPORT_PRIVATE Handle<DERIVED> Dictionary<DERIVED, SHAPE>::Add( \
OffThreadIsolate* isolate, Handle<DERIVED>, Key, Handle<Object>, \
LocalIsolate* isolate, Handle<DERIVED>, Key, Handle<Object>, \
PropertyDetails, InternalIndex*);
#define EXTERN_DEFINE_BASE_NAME_DICTIONARY(DERIVED, SHAPE) \
@ -7189,8 +7186,8 @@ Address Smi::LexicographicCompare(Isolate* isolate, Smi x, Smi y) {
BaseNameDictionary<DERIVED, SHAPE>::New(Isolate*, int, AllocationType, \
MinimumCapacity); \
template V8_EXPORT_PRIVATE Handle<DERIVED> \
BaseNameDictionary<DERIVED, SHAPE>::New(OffThreadIsolate*, int, \
AllocationType, MinimumCapacity); \
BaseNameDictionary<DERIVED, SHAPE>::New(LocalIsolate*, int, AllocationType, \
MinimumCapacity); \
\
template Handle<DERIVED> \
BaseNameDictionary<DERIVED, SHAPE>::AddNoUpdateNextEnumerationIndex( \
@ -7198,7 +7195,7 @@ Address Smi::LexicographicCompare(Isolate* isolate, Smi x, Smi y) {
InternalIndex*); \
template Handle<DERIVED> \
BaseNameDictionary<DERIVED, SHAPE>::AddNoUpdateNextEnumerationIndex( \
OffThreadIsolate* isolate, Handle<DERIVED>, Key, Handle<Object>, \
LocalIsolate* isolate, Handle<DERIVED>, Key, Handle<Object>, \
PropertyDetails, InternalIndex*);
EXTERN_DEFINE_HASH_TABLE(StringSet, StringSetShape)

View File

@ -197,7 +197,6 @@
namespace v8 {
namespace internal {
class OffThreadIsolate;
struct InliningPosition;
class PropertyDescriptorObject;
@ -292,10 +291,10 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
// Oddball checks are faster when they are raw pointer comparisons, so the
// isolate/read-only roots overloads should be preferred where possible.
#define IS_TYPE_FUNCTION_DECL(Type, Value) \
V8_INLINE bool Is##Type(Isolate* isolate) const; \
V8_INLINE bool Is##Type(OffThreadIsolate* isolate) const; \
V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \
#define IS_TYPE_FUNCTION_DECL(Type, Value) \
V8_INLINE bool Is##Type(Isolate* isolate) const; \
V8_INLINE bool Is##Type(LocalIsolate* isolate) const; \
V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \
V8_INLINE bool Is##Type() const;
ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(NullOrUndefined, /* unused */)

View File

@ -380,13 +380,13 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
}
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<ScopeInfo> ScopeInfo::Create<Isolate>(
Isolate* isolate, Zone* zone, Scope* scope,
MaybeHandle<ScopeInfo> outer_scope);
Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
Scope* scope,
MaybeHandle<ScopeInfo> outer_scope);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<ScopeInfo> ScopeInfo::Create<OffThreadIsolate>(
OffThreadIsolate* isolate, Zone* zone, Scope* scope,
MaybeHandle<ScopeInfo> outer_scope);
Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
Scope* scope,
MaybeHandle<ScopeInfo> outer_scope);
// static
Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
@ -1068,7 +1068,7 @@ template Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
int beg_pos, int end_pos);
template Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
OffThreadIsolate* isolate, Handle<PrimitiveHeapObject> export_name,
LocalIsolate* isolate, Handle<PrimitiveHeapObject> export_name,
Handle<PrimitiveHeapObject> local_name,
Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
int beg_pos, int end_pos);
@ -1140,7 +1140,7 @@ Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
template Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
Isolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr);
template Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
OffThreadIsolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr);
LocalIsolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr);
int SourceTextModuleInfo::RegularExportCount() const {
DCHECK_EQ(regular_exports().length() % kRegularExportLength, 0);

View File

@ -6,13 +6,13 @@
#define V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_
#include "src/base/macros.h"
#include "src/objects/shared-function-info.h"
#include "src/handles/handles-inl.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/local-heap-inl.h"
#include "src/objects/debug-objects-inl.h"
#include "src/objects/feedback-vector-inl.h"
#include "src/objects/scope-info.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/templates.h"
#include "src/wasm/wasm-objects-inl.h"
@ -423,9 +423,8 @@ IsCompiledScope SharedFunctionInfo::is_compiled_scope(
return IsCompiledScope(*this, isolate);
}
template <typename LocalIsolate>
IsCompiledScope::IsCompiledScope(const SharedFunctionInfo shared,
LocalIsolate* isolate)
Isolate* isolate)
: retain_bytecode_(shared.HasBytecodeArray()
? handle(shared.GetBytecodeArray(), isolate)
: MaybeHandle<BytecodeArray>()),
@ -433,6 +432,16 @@ IsCompiledScope::IsCompiledScope(const SharedFunctionInfo shared,
DCHECK_IMPLIES(!retain_bytecode_.is_null(), is_compiled());
}
IsCompiledScope::IsCompiledScope(const SharedFunctionInfo shared,
LocalIsolate* isolate)
: retain_bytecode_(
shared.HasBytecodeArray()
? isolate->heap()->NewPersistentHandle(shared.GetBytecodeArray())
: MaybeHandle<BytecodeArray>()),
is_compiled_(shared.is_compiled()) {
DCHECK_IMPLIES(!retain_bytecode_.is_null(), is_compiled());
}
bool SharedFunctionInfo::has_simple_parameters() {
return scope_info().HasSimpleParameters();
}

View File

@ -532,8 +532,8 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void SharedFunctionInfo::
Handle<SharedFunctionInfo> shared_info,
FunctionLiteral* lit, bool is_toplevel);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void SharedFunctionInfo::
InitFromFunctionLiteral<OffThreadIsolate>(
OffThreadIsolate* isolate, Handle<SharedFunctionInfo> shared_info,
InitFromFunctionLiteral<LocalIsolate>(
LocalIsolate* isolate, Handle<SharedFunctionInfo> shared_info,
FunctionLiteral* lit, bool is_toplevel);
uint16_t SharedFunctionInfo::get_property_estimate_from_literal(

View File

@ -604,7 +604,7 @@ class SharedFunctionInfo : public HeapObject {
DECL_PRINTER(SharedFunctionInfo)
DECL_VERIFIER(SharedFunctionInfo)
#ifdef VERIFY_HEAP
void SharedFunctionInfoVerify(OffThreadIsolate* isolate);
void SharedFunctionInfoVerify(LocalIsolate* isolate);
#endif
#ifdef OBJECT_PRINT
void PrintSourceCode(std::ostream& os);
@ -702,7 +702,7 @@ struct SourceCodeOf {
// the scope is retained.
class IsCompiledScope {
public:
template <typename LocalIsolate>
inline IsCompiledScope(const SharedFunctionInfo shared, Isolate* isolate);
inline IsCompiledScope(const SharedFunctionInfo shared,
LocalIsolate* isolate);
inline IsCompiledScope() : retain_bytecode_(), is_compiled_(false) {}

View File

@ -270,7 +270,16 @@ class SequentialStringKey final : public StringTableKey {
return CompareChars(chars, chars_.begin(), chars_.length()) == 0;
}
Handle<String> AsHandle(Isolate* isolate) override {
Handle<String> AsHandle(Isolate* isolate) {
if (sizeof(Char) == 1) {
return isolate->factory()->NewOneByteInternalizedString(
Vector<const uint8_t>::cast(chars_), hash_field());
}
return isolate->factory()->NewTwoByteInternalizedString(
Vector<const uint16_t>::cast(chars_), hash_field());
}
Handle<String> AsHandle(LocalIsolate* isolate) {
if (sizeof(Char) == 1) {
return isolate->factory()->NewOneByteInternalizedString(
Vector<const uint8_t>::cast(chars_), hash_field());
@ -331,7 +340,8 @@ class SeqSubStringKey final : public StringTableKey {
return CompareChars(string_->GetChars(no_gc) + from_, data, length()) == 0;
}
Handle<String> AsHandle(Isolate* isolate) override {
template <typename LocalIsolate>
Handle<String> AsHandle(LocalIsolate* isolate) {
if (sizeof(Char) == 1 || (sizeof(Char) == 2 && convert_)) {
Handle<SeqOneByteString> result =
isolate->factory()->AllocateRawOneByteInternalizedString(
@ -399,7 +409,7 @@ Handle<String> String::Flatten(Isolate* isolate, Handle<String> string,
return string;
}
Handle<String> String::Flatten(OffThreadIsolate* isolate, Handle<String> string,
Handle<String> String::Flatten(LocalIsolate* isolate, Handle<String> string,
AllocationType allocation) {
// We should never pass non-flat strings to String::Flatten when off-thread.
DCHECK(string->IsFlat());

View File

@ -8,6 +8,7 @@
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
#include "src/common/ptr-compr-inl.h"
#include "src/execution/isolate-utils-inl.h"
#include "src/objects/internal-index.h"
#include "src/objects/object-list-macros.h"
#include "src/objects/slots-inl.h"
@ -347,7 +348,7 @@ class InternalizedStringKey final : public StringTableKey {
bool IsMatch(String string) override { return string_->SlowEquals(string); }
Handle<String> AsHandle(Isolate* isolate) override {
Handle<String> AsHandle(Isolate* isolate) {
// Internalize the string if possible.
MaybeHandle<Map> maybe_map =
isolate->factory()->InternalizedStringMapForString(string_);
@ -411,8 +412,9 @@ Handle<String> StringTable::LookupString(Isolate* isolate,
return result;
}
template <typename StringTableKey>
Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
template <typename StringTableKey, typename LocalIsolate>
Handle<String> StringTable::LookupKey(LocalIsolate* isolate,
StringTableKey* key) {
// String table lookups are allowed to be concurrent, assuming that:
//
// - The Heap access is allowed to be concurrent (using LocalHeap or
@ -447,6 +449,8 @@ Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
// allocation if another write also did an allocation. This assumes that
// writes are rarer than reads.
const Isolate* ptr_cmp_isolate = GetIsolateForPtrCompr(isolate);
Handle<String> new_string;
while (true) {
// Load the current string table data, in case another thread updates the
@ -458,9 +462,9 @@ Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
// because the new table won't delete it's corresponding entry until the
// string is dead, in which case it will die in this table too and worst
// case we'll have a false miss.
InternalIndex entry = data->FindEntry(isolate, key, key->hash());
InternalIndex entry = data->FindEntry(ptr_cmp_isolate, key, key->hash());
if (entry.is_found()) {
return handle(String::cast(data->Get(isolate, entry)), isolate);
return handle(String::cast(data->Get(ptr_cmp_isolate, entry)), isolate);
}
// No entry found, so adding new string.
@ -474,16 +478,16 @@ Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
{
base::MutexGuard table_write_guard(&write_mutex_);
EnsureCapacity(isolate, 1);
EnsureCapacity(ptr_cmp_isolate, 1);
// Reload the data pointer in case EnsureCapacity changed it.
StringTable::Data* data = data_.get();
// Check one last time if the key is present in the table, in case it was
// added after the check.
InternalIndex entry =
data->FindEntryOrInsertionEntry(isolate, key, key->hash());
data->FindEntryOrInsertionEntry(ptr_cmp_isolate, key, key->hash());
Object element = data->Get(isolate, entry);
Object element = data->Get(ptr_cmp_isolate, entry);
if (element == empty_element()) {
// This entry is empty, so write it and register that we added an
// element.
@ -513,6 +517,15 @@ template Handle<String> StringTable::LookupKey(Isolate* isolate,
template Handle<String> StringTable::LookupKey(Isolate* isolate,
SeqTwoByteSubStringKey* key);
template Handle<String> StringTable::LookupKey(LocalIsolate* isolate,
OneByteStringKey* key);
template Handle<String> StringTable::LookupKey(LocalIsolate* isolate,
TwoByteStringKey* key);
template Handle<String> StringTable::LookupKey(LocalIsolate* isolate,
SeqOneByteSubStringKey* key);
template Handle<String> StringTable::LookupKey(LocalIsolate* isolate,
SeqTwoByteSubStringKey* key);
template Handle<String> StringTable::LookupKey(Isolate* isolate,
StringTableInsertionKey* key);

View File

@ -22,7 +22,10 @@ class StringTableKey {
virtual ~StringTableKey() = default;
inline StringTableKey(uint32_t hash_field, int length);
virtual Handle<String> AsHandle(Isolate* isolate) = 0;
// The individual keys will have their own AsHandle, we shouldn't call the
// base version.
Handle<String> AsHandle(Isolate* isolate) = delete;
uint32_t hash_field() const {
DCHECK_NE(0, hash_field_);
return hash_field_;
@ -65,8 +68,8 @@ class V8_EXPORT_PRIVATE StringTable {
// Find string in the string table, using the given key. If the string is not
// there yet, it is created (by the key) and added. The return value is the
// string found.
template <typename StringTableKey>
Handle<String> LookupKey(Isolate* isolate, StringTableKey* key);
template <typename StringTableKey, typename LocalIsolate>
Handle<String> LookupKey(LocalIsolate* isolate, StringTableKey* key);
// {raw_string} must be a tagged String pointer.
// Returns a tagged pointer: either a Smi if the string is an array index, an

View File

@ -755,7 +755,7 @@ Handle<FixedArray> String::CalculateLineEnds(LocalIsolate* isolate,
template Handle<FixedArray> String::CalculateLineEnds(Isolate* isolate,
Handle<String> src,
bool include_ending_line);
template Handle<FixedArray> String::CalculateLineEnds(OffThreadIsolate* isolate,
template Handle<FixedArray> String::CalculateLineEnds(LocalIsolate* isolate,
Handle<String> src,
bool include_ending_line);

View File

@ -209,7 +209,7 @@ class String : public TorqueGeneratedString<String, Name> {
Isolate* isolate, Handle<String> string,
AllocationType allocation = AllocationType::kYoung);
static inline Handle<String> Flatten(
OffThreadIsolate* isolate, Handle<String> string,
LocalIsolate* isolate, Handle<String> string,
AllocationType allocation = AllocationType::kYoung);
// Tries to return the content of a flat string as a structure holding either

View File

@ -117,12 +117,13 @@ class FunctionTemplateInfo
MaybeHandle<Name> maybe_name);
static Handle<SharedFunctionInfo> GetOrCreateSharedFunctionInfo(
OffThreadIsolate* isolate, Handle<FunctionTemplateInfo> info,
LocalIsolate* 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.

View File

@ -5,7 +5,7 @@
#include "src/parsing/literal-buffer.h"
#include "src/execution/isolate.h"
#include "src/execution/off-thread-isolate.h"
#include "src/execution/local-isolate.h"
#include "src/heap/factory.h"
#include "src/utils/memcopy.h"
@ -21,8 +21,7 @@ Handle<String> LiteralBuffer::Internalize(LocalIsolate* isolate) const {
}
template Handle<String> LiteralBuffer::Internalize(Isolate* isolate) const;
template Handle<String> LiteralBuffer::Internalize(
OffThreadIsolate* isolate) const;
template Handle<String> LiteralBuffer::Internalize(LocalIsolate* isolate) const;
int LiteralBuffer::NewCapacity(int min_capacity) {
return min_capacity < (kMaxGrowth / (kGrowthFactor - 1))

View File

@ -271,7 +271,7 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
ScriptOriginOptions origin_options, NativesFlag natives);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<Script> ParseInfo::CreateScript(
OffThreadIsolate* isolate, Handle<String> source,
LocalIsolate* isolate, Handle<String> source,
MaybeHandle<FixedArray> maybe_wrapped_arguments,
ScriptOriginOptions origin_options, NativesFlag natives);

View File

@ -3092,7 +3092,7 @@ void Parser::HandleSourceURLComments(LocalIsolate* isolate,
template void Parser::HandleSourceURLComments(Isolate* isolate,
Handle<Script> script);
template void Parser::HandleSourceURLComments(OffThreadIsolate* isolate,
template void Parser::HandleSourceURLComments(LocalIsolate* isolate,
Handle<Script> script);
void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) {

View File

@ -10,9 +10,8 @@
#include "src/debug/debug.h"
#include "src/execution/isolate.h"
#include "src/execution/messages.h"
#include "src/execution/off-thread-isolate.h"
#include "src/handles/handles.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-heap-inl.h"
#include "src/objects/objects-inl.h"
namespace v8 {
@ -21,17 +20,15 @@ namespace internal {
void PendingCompilationErrorHandler::MessageDetails::SetString(
Handle<String> string, Isolate* isolate) {
DCHECK_NE(type_, kMainThreadHandle);
DCHECK_NE(type_, kOffThreadTransferHandle);
type_ = kMainThreadHandle;
arg_handle_ = string;
}
void PendingCompilationErrorHandler::MessageDetails::SetString(
Handle<String> string, OffThreadIsolate* isolate) {
Handle<String> string, LocalIsolate* isolate) {
DCHECK_NE(type_, kMainThreadHandle);
DCHECK_NE(type_, kOffThreadTransferHandle);
type_ = kOffThreadTransferHandle;
arg_transfer_handle_ = isolate->TransferHandle(string);
type_ = kMainThreadHandle;
arg_handle_ = isolate->heap()->NewPersistentHandle(string);
}
template <typename LocalIsolate>
@ -49,7 +46,6 @@ void PendingCompilationErrorHandler::MessageDetails::Prepare(
return;
case kMainThreadHandle:
case kOffThreadTransferHandle:
// The message details might already be prepared, so skip them if this is
// the case.
return;
@ -61,8 +57,6 @@ Handle<String> PendingCompilationErrorHandler::MessageDetails::ArgumentString(
switch (type_) {
case kMainThreadHandle:
return arg_handle_;
case kOffThreadTransferHandle:
return arg_transfer_handle_.ToHandle();
case kNone:
return isolate->factory()->undefined_string();
case kConstCharString:
@ -117,7 +111,7 @@ void PendingCompilationErrorHandler::PrepareWarnings(LocalIsolate* isolate) {
}
template void PendingCompilationErrorHandler::PrepareWarnings(Isolate* isolate);
template void PendingCompilationErrorHandler::PrepareWarnings(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
void PendingCompilationErrorHandler::ReportWarnings(
Isolate* isolate, Handle<Script> script) const {
@ -149,8 +143,7 @@ template EXPORT_TEMPLATE_DEFINE(
PrepareErrors(Isolate* isolate, AstValueFactory* ast_value_factory);
template EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler::
PrepareErrors(OffThreadIsolate* isolate,
AstValueFactory* ast_value_factory);
PrepareErrors(LocalIsolate* isolate, AstValueFactory* ast_value_factory);
void PendingCompilationErrorHandler::ReportErrors(Isolate* isolate,
Handle<Script> script) const {

View File

@ -7,10 +7,10 @@
#include <forward_list>
#include "src/base/export-template.h"
#include "src/base/macros.h"
#include "src/common/globals.h"
#include "src/common/message-template.h"
#include "src/execution/off-thread-isolate.h"
#include "src/handles/handles.h"
namespace v8 {
@ -105,16 +105,10 @@ class PendingCompilationErrorHandler {
void Prepare(LocalIsolate* isolate);
private:
enum Type {
kNone,
kAstRawString,
kConstCharString,
kMainThreadHandle,
kOffThreadTransferHandle
};
enum Type { kNone, kAstRawString, kConstCharString, kMainThreadHandle };
void SetString(Handle<String> string, Isolate* isolate);
void SetString(Handle<String> string, OffThreadIsolate* isolate);
void SetString(Handle<String> string, LocalIsolate* isolate);
int start_position_;
int end_position_;
@ -123,7 +117,6 @@ class PendingCompilationErrorHandler {
const AstRawString* arg_;
const char* char_arg_;
Handle<String> arg_handle_;
OffThreadTransferHandle<String> arg_transfer_handle_;
};
Type type_;
};
@ -144,11 +137,11 @@ class PendingCompilationErrorHandler {
extern template void PendingCompilationErrorHandler::PrepareErrors(
Isolate* isolate, AstValueFactory* ast_value_factory);
extern template void PendingCompilationErrorHandler::PrepareErrors(
OffThreadIsolate* isolate, AstValueFactory* ast_value_factory);
LocalIsolate* isolate, AstValueFactory* ast_value_factory);
extern template void PendingCompilationErrorHandler::PrepareWarnings(
Isolate* isolate);
extern template void PendingCompilationErrorHandler::PrepareWarnings(
OffThreadIsolate* isolate);
LocalIsolate* isolate);
} // namespace internal
} // namespace v8

View File

@ -5,11 +5,10 @@
#ifndef V8_PARSING_PREPARSE_DATA_IMPL_H_
#define V8_PARSING_PREPARSE_DATA_IMPL_H_
#include "src/parsing/preparse-data.h"
#include <memory>
#include "src/common/assert-scope.h"
#include "src/parsing/preparse-data.h"
namespace v8 {
namespace internal {
@ -200,7 +199,7 @@ class ZonePreparseData : public ZoneObject {
int child_length);
Handle<PreparseData> Serialize(Isolate* isolate);
Handle<PreparseData> Serialize(OffThreadIsolate* isolate);
Handle<PreparseData> Serialize(LocalIsolate* isolate);
int children_length() const { return static_cast<int>(children_.size()); }

View File

@ -9,7 +9,6 @@
#include "src/ast/scopes.h"
#include "src/ast/variables.h"
#include "src/handles/handles.h"
#include "src/heap/off-thread-factory.h"
#include "src/objects/objects-inl.h"
#include "src/objects/shared-function-info.h"
#include "src/parsing/parser.h"
@ -339,8 +338,8 @@ void PreparseDataBuilder::SaveScopeAllocationData(DeclarationScope* scope,
CHECK_LE(byte_data_.length(), std::numeric_limits<uint32_t>::max());
byte_data_.SaveCurrentSizeAtFirstUint32();
// For a data integrity check, write a value between data about skipped inner
// funcs and data about variables.
// For a data integrity check, write a value between data about skipped
// inner funcs and data about variables.
byte_data_.Reserve(kUint32Size * 3);
byte_data_.WriteUint32(kMagicValue);
byte_data_.WriteUint32(scope->start_position());
@ -437,8 +436,8 @@ Handle<PreparseData> PreparseDataBuilder::ByteData::CopyToHeap(
return data;
}
Handle<PreparseData> PreparseDataBuilder::ByteData::CopyToOffThreadHeap(
OffThreadIsolate* isolate, int children_length) {
Handle<PreparseData> PreparseDataBuilder::ByteData::CopyToLocalHeap(
LocalIsolate* isolate, int children_length) {
DCHECK(is_finalized_);
int data_length = zone_byte_data_.length();
Handle<PreparseData> data =
@ -463,11 +462,11 @@ Handle<PreparseData> PreparseDataBuilder::Serialize(Isolate* isolate) {
return data;
}
Handle<PreparseData> PreparseDataBuilder::Serialize(OffThreadIsolate* isolate) {
Handle<PreparseData> PreparseDataBuilder::Serialize(LocalIsolate* isolate) {
DCHECK(HasData());
DCHECK(!ThisOrParentBailedOut());
Handle<PreparseData> data =
byte_data_.CopyToOffThreadHeap(isolate, num_inner_with_data_);
byte_data_.CopyToLocalHeap(isolate, num_inner_with_data_);
int i = 0;
DCHECK(finalized_children_);
for (const auto& builder : children_) {
@ -505,7 +504,7 @@ class BuilderProducedPreparseData final : public ProducedPreparseData {
return builder_->Serialize(isolate);
}
Handle<PreparseData> Serialize(OffThreadIsolate* isolate) final {
Handle<PreparseData> Serialize(LocalIsolate* isolate) final {
return builder_->Serialize(isolate);
}
@ -527,7 +526,7 @@ class OnHeapProducedPreparseData final : public ProducedPreparseData {
return data_;
}
Handle<PreparseData> Serialize(OffThreadIsolate* isolate) final {
Handle<PreparseData> Serialize(LocalIsolate* isolate) final {
// Not required.
UNREACHABLE();
}
@ -549,7 +548,7 @@ class ZoneProducedPreparseData final : public ProducedPreparseData {
return data_->Serialize(isolate);
}
Handle<PreparseData> Serialize(OffThreadIsolate* isolate) final {
Handle<PreparseData> Serialize(LocalIsolate* isolate) final {
return data_->Serialize(isolate);
}
@ -795,7 +794,7 @@ Handle<PreparseData> ZonePreparseData::Serialize(Isolate* isolate) {
return result;
}
Handle<PreparseData> ZonePreparseData::Serialize(OffThreadIsolate* isolate) {
Handle<PreparseData> ZonePreparseData::Serialize(LocalIsolate* isolate) {
int data_size = static_cast<int>(byte_data()->size());
int child_data_length = children_length();
Handle<PreparseData> result =

View File

@ -139,8 +139,8 @@ class V8_EXPORT_PRIVATE PreparseDataBuilder : public ZoneObject,
void Finalize(Zone* zone);
Handle<PreparseData> CopyToHeap(Isolate* isolate, int children_length);
Handle<PreparseData> CopyToOffThreadHeap(OffThreadIsolate* isolate,
int children_length);
Handle<PreparseData> CopyToLocalHeap(LocalIsolate* isolate,
int children_length);
inline ZonePreparseData* CopyToZone(Zone* zone, int children_length);
void Reserve(size_t bytes);
@ -209,7 +209,7 @@ class V8_EXPORT_PRIVATE PreparseDataBuilder : public ZoneObject,
friend class BuilderProducedPreparseData;
Handle<PreparseData> Serialize(Isolate* isolate);
Handle<PreparseData> Serialize(OffThreadIsolate* isolate);
Handle<PreparseData> Serialize(LocalIsolate* isolate);
ZonePreparseData* Serialize(Zone* zone);
void FinalizeChildren(Zone* zone);
@ -255,7 +255,7 @@ class ProducedPreparseData : public ZoneObject {
// If there is data (if the Scope contains skippable inner functions), move
// the data into the heap and return a Handle to it; otherwise return a null
// MaybeHandle.
virtual Handle<PreparseData> Serialize(OffThreadIsolate* isolate) = 0;
virtual Handle<PreparseData> Serialize(LocalIsolate* isolate) = 0;
// If there is data (if the Scope contains skippable inner functions), return
// an off-heap ZonePreparseData representing the data; otherwise

View File

@ -600,7 +600,7 @@ Handle<String> Scanner::SourceUrl(LocalIsolate* isolate) const {
}
template Handle<String> Scanner::SourceUrl(Isolate* isolate) const;
template Handle<String> Scanner::SourceUrl(OffThreadIsolate* isolate) const;
template Handle<String> Scanner::SourceUrl(LocalIsolate* isolate) const;
template <typename LocalIsolate>
Handle<String> Scanner::SourceMappingUrl(LocalIsolate* isolate) const {
@ -612,8 +612,7 @@ Handle<String> Scanner::SourceMappingUrl(LocalIsolate* isolate) const {
}
template Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const;
template Handle<String> Scanner::SourceMappingUrl(
OffThreadIsolate* isolate) const;
template Handle<String> Scanner::SourceMappingUrl(LocalIsolate* isolate) const;
bool Scanner::ScanDigitsWithNumericSeparators(bool (*predicate)(uc32 ch),
bool is_check_first_digit) {

View File

@ -6,8 +6,7 @@
#define V8_ROOTS_ROOTS_INL_H_
#include "src/execution/isolate.h"
#include "src/execution/local-isolate-wrapper.h"
#include "src/execution/off-thread-isolate.h"
#include "src/execution/local-isolate.h"
#include "src/handles/handles.h"
#include "src/heap/read-only-heap.h"
#include "src/objects/api-callbacks.h"
@ -62,25 +61,13 @@ bool RootsTable::IsRootHandle(Handle<T> handle, RootIndex* index) const {
ReadOnlyRoots::ReadOnlyRoots(Heap* heap)
: ReadOnlyRoots(Isolate::FromHeap(heap)) {}
ReadOnlyRoots::ReadOnlyRoots(OffThreadHeap* heap)
: ReadOnlyRoots(OffThreadIsolate::FromHeap(heap)) {}
ReadOnlyRoots::ReadOnlyRoots(Isolate* isolate)
: read_only_roots_(reinterpret_cast<Address*>(
isolate->roots_table().read_only_roots_begin().address())) {}
ReadOnlyRoots::ReadOnlyRoots(OffThreadIsolate* isolate)
ReadOnlyRoots::ReadOnlyRoots(LocalIsolate* isolate)
: ReadOnlyRoots(isolate->factory()->read_only_roots()) {}
ReadOnlyRoots::ReadOnlyRoots(LocalHeapWrapper heap)
: ReadOnlyRoots(heap.is_off_thread() ? ReadOnlyRoots(heap.off_thread())
: ReadOnlyRoots(heap.main_thread())) {}
ReadOnlyRoots::ReadOnlyRoots(LocalIsolateWrapper isolate)
: ReadOnlyRoots(isolate.is_off_thread()
? ReadOnlyRoots(isolate.off_thread())
: ReadOnlyRoots(isolate.main_thread())) {}
// We use unchecked_cast below because we trust our read-only roots to
// have the right type, and to avoid the heavy #includes that would be
// required for checked casts.

View File

@ -8,7 +8,6 @@
#include "src/base/macros.h"
#include "src/builtins/accessors.h"
#include "src/common/globals.h"
#include "src/execution/local-isolate-wrapper.h"
#include "src/handles/handles.h"
#include "src/init/heap-symbols.h"
#include "src/objects/objects-definitions.h"
@ -20,8 +19,6 @@ namespace internal {
// Forward declarations.
enum ElementsKind : uint8_t;
class OffThreadHeap;
class OffThreadIsolate;
template <typename T>
class Handle;
class Heap;
@ -542,11 +539,8 @@ class ReadOnlyRoots {
static_cast<size_t>(RootIndex::kReadOnlyRootsCount);
V8_INLINE explicit ReadOnlyRoots(Heap* heap);
V8_INLINE explicit ReadOnlyRoots(OffThreadHeap* heap);
V8_INLINE explicit ReadOnlyRoots(Isolate* isolate);
V8_INLINE explicit ReadOnlyRoots(OffThreadIsolate* isolate);
V8_INLINE explicit ReadOnlyRoots(LocalIsolateWrapper wrapper);
V8_INLINE explicit ReadOnlyRoots(LocalHeapWrapper wrapper);
V8_INLINE explicit ReadOnlyRoots(LocalIsolate* isolate);
#define ROOT_ACCESSOR(Type, name, CamelName) \
V8_INLINE class Type name() const; \

View File

@ -9,7 +9,7 @@
#include "src/common/globals.h"
#include "src/debug/debug.h"
#include "src/heap/heap-inl.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/logging/counters.h"
#include "src/logging/log.h"
#include "src/objects/objects-inl.h"
@ -265,33 +265,28 @@ void CreateInterpreterDataForDeserializedCode(Isolate* isolate,
namespace {
class StressOffThreadDeserializeThread final : public base::Thread {
public:
explicit StressOffThreadDeserializeThread(
OffThreadIsolate* off_thread_isolate, const SerializedCodeData* scd)
explicit StressOffThreadDeserializeThread(LocalIsolate* local_isolate,
const SerializedCodeData* scd)
: Thread(
base::Thread::Options("StressOffThreadDeserializeThread", 2 * MB)),
off_thread_isolate_(off_thread_isolate),
local_isolate_(local_isolate),
scd_(scd) {}
MaybeHandle<SharedFunctionInfo> maybe_result() const {
return maybe_result_.ToHandle();
}
MaybeHandle<SharedFunctionInfo> maybe_result() const { return maybe_result_; }
void Run() final {
off_thread_isolate_->PinToCurrentThread();
MaybeHandle<SharedFunctionInfo> off_thread_maybe_result =
MaybeHandle<SharedFunctionInfo> local_maybe_result =
ObjectDeserializer::DeserializeSharedFunctionInfoOffThread(
off_thread_isolate_, scd_,
off_thread_isolate_->factory()->empty_string());
local_isolate_, scd_, local_isolate_->factory()->empty_string());
maybe_result_ =
off_thread_isolate_->TransferHandle(off_thread_maybe_result);
local_isolate_->heap()->NewPersistentMaybeHandle(local_maybe_result);
}
private:
OffThreadIsolate* off_thread_isolate_;
LocalIsolate* local_isolate_;
const SerializedCodeData* scd_;
OffThreadTransferMaybeHandle<SharedFunctionInfo> maybe_result_;
MaybeHandle<SharedFunctionInfo> maybe_result_;
};
} // namespace
@ -318,17 +313,14 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
// Deserialize.
MaybeHandle<SharedFunctionInfo> maybe_result;
if (FLAG_stress_background_compile) {
Zone zone(isolate->allocator(), "Deserialize");
OffThreadIsolate off_thread_isolate(isolate, &zone);
// TODO(leszeks): Add LocalHeap support to deserializer
if (false && FLAG_stress_background_compile) {
LocalIsolate local_isolate(isolate);
StressOffThreadDeserializeThread thread(&off_thread_isolate, &scd);
StressOffThreadDeserializeThread thread(&local_isolate, &scd);
CHECK(thread.Start());
thread.Join();
off_thread_isolate.FinishOffThread();
off_thread_isolate.Publish(isolate);
maybe_result = thread.maybe_result();
// Fix-up result script source.

View File

@ -11,10 +11,9 @@
namespace v8 {
namespace internal {
void DeserializerAllocator::Initialize(LocalHeapWrapper heap) {
void DeserializerAllocator::Initialize(Heap* heap) {
heap_ = heap;
roots_ = heap.is_off_thread() ? ReadOnlyRoots(heap.off_thread())
: ReadOnlyRoots(heap.main_thread());
roots_ = ReadOnlyRoots(heap);
}
// We know the space requirements before deserialization and can
@ -34,15 +33,10 @@ Address DeserializerAllocator::AllocateRaw(SnapshotSpace space, int size) {
// Note that we currently do not support deserialization of large code
// objects.
HeapObject obj;
if (heap_.is_off_thread()) {
obj = heap_.off_thread()->lo_space_.AllocateRaw(size).ToObjectChecked();
} else {
Heap* heap = heap_.main_thread();
AlwaysAllocateScope scope(heap);
OldLargeObjectSpace* lo_space = heap->lo_space();
AllocationResult result = lo_space->AllocateRaw(size);
obj = result.ToObjectChecked();
}
AlwaysAllocateScope scope(heap_);
OldLargeObjectSpace* lo_space = heap_->lo_space();
AllocationResult result = lo_space->AllocateRaw(size);
obj = result.ToObjectChecked();
deserialized_large_objects_.push_back(obj);
return obj.address();
} else if (space == SnapshotSpace::kMap) {
@ -121,7 +115,6 @@ void DeserializerAllocator::MoveToNextChunk(SnapshotSpace space) {
}
HeapObject DeserializerAllocator::GetMap(uint32_t index) {
DCHECK(!heap_.is_off_thread());
DCHECK_LT(index, next_map_index_);
return HeapObject::FromAddress(allocated_maps_[index]);
}
@ -169,16 +162,10 @@ bool DeserializerAllocator::ReserveSpace() {
}
#endif // DEBUG
DCHECK(allocated_maps_.empty());
if (heap_.is_off_thread()) {
if (!heap_.off_thread()->ReserveSpace(reservations_)) {
return false;
}
} else {
// TODO(v8:7464): Allocate using the off-heap ReadOnlySpace here once
// implemented.
if (!heap_.main_thread()->ReserveSpace(reservations_, &allocated_maps_)) {
return false;
}
// TODO(v8:7464): Allocate using the off-heap ReadOnlySpace here once
// implemented.
if (!heap_->ReserveSpace(reservations_, &allocated_maps_)) {
return false;
}
for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
high_water_[i] = reservations_[i][0].start;
@ -200,8 +187,7 @@ bool DeserializerAllocator::ReservationsAreFullyUsed() const {
}
void DeserializerAllocator::RegisterDeserializedObjectsForBlackAllocation() {
DCHECK(!heap_.is_off_thread());
heap_.main_thread()->RegisterDeserializedObjectsForBlackAllocation(
heap_->RegisterDeserializedObjectsForBlackAllocation(
reservations_, deserialized_large_objects_, allocated_maps_);
}

View File

@ -6,7 +6,6 @@
#define V8_SNAPSHOT_DESERIALIZER_ALLOCATOR_H_
#include "src/common/globals.h"
#include "src/execution/local-isolate-wrapper.h"
#include "src/heap/heap.h"
#include "src/objects/heap-object.h"
#include "src/roots/roots.h"
@ -18,13 +17,12 @@ namespace internal {
class Deserializer;
class StartupDeserializer;
class OffThreadHeap;
class DeserializerAllocator final {
public:
DeserializerAllocator() = default;
void Initialize(LocalHeapWrapper heap);
void Initialize(Heap* heap);
// ------- Allocation Methods -------
// Methods related to memory allocation during deserialization.
@ -103,7 +101,7 @@ class DeserializerAllocator final {
std::vector<HeapObject> deserialized_large_objects_;
// ReadOnlyRoots and heap are null until Initialize is called.
LocalHeapWrapper heap_ = LocalHeapWrapper(nullptr);
Heap* heap_ = nullptr;
ReadOnlyRoots roots_ = ReadOnlyRoots(static_cast<Address*>(nullptr));
DISALLOW_COPY_AND_ASSIGN(DeserializerAllocator);

View File

@ -8,13 +8,11 @@
#include "src/codegen/assembler-inl.h"
#include "src/common/external-pointer.h"
#include "src/execution/isolate.h"
#include "src/execution/local-isolate-wrapper-inl.h"
#include "src/heap/heap-inl.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/read-only-heap.h"
#include "src/interpreter/interpreter.h"
#include "src/logging/log.h"
#include "src/logging/off-thread-logger.h"
#include "src/objects/api-callbacks.h"
#include "src/objects/cell-inl.h"
#include "src/objects/hash-table.h"
@ -58,25 +56,22 @@ TSlot Deserializer::WriteExternalPointer(TSlot dest, Address value) {
return dest + (kExternalPointerSize / TSlot::kSlotDataSize);
}
void Deserializer::Initialize(LocalIsolateWrapper local_isolate) {
DCHECK(local_isolate_.is_null());
DCHECK(!local_isolate.is_null());
local_isolate_ = local_isolate;
allocator()->Initialize(local_isolate->heap());
void Deserializer::Initialize(Isolate* isolate) {
DCHECK_NULL(isolate_);
DCHECK_NOT_NULL(isolate);
isolate_ = isolate;
allocator()->Initialize(isolate->heap());
#ifdef DEBUG
num_api_references_ = 0;
if (!local_isolate.is_off_thread()) {
Isolate* isolate = local_isolate.main_thread();
// The read-only deserializer is run by read-only heap set-up before the
// heap is fully set up. External reference table relies on a few parts of
// this set-up (like old-space), so it may be uninitialized at this point.
if (isolate->isolate_data()->external_reference_table()->is_initialized()) {
// Count the number of external references registered through the API.
if (isolate->api_external_references() != nullptr) {
while (isolate->api_external_references()[num_api_references_] != 0) {
num_api_references_++;
}
// The read-only deserializer is run by read-only heap set-up before the
// heap is fully set up. External reference table relies on a few parts of
// this set-up (like old-space), so it may be uninitialized at this point.
if (isolate->isolate_data()->external_reference_table()->is_initialized()) {
// Count the number of external references registered through the API.
if (isolate->api_external_references() != nullptr) {
while (isolate->api_external_references()[num_api_references_] != 0) {
num_api_references_++;
}
}
}
@ -87,7 +82,7 @@ void Deserializer::Initialize(LocalIsolateWrapper local_isolate) {
void Deserializer::Rehash() {
DCHECK(can_rehash() || deserializing_user_code());
for (HeapObject item : to_rehash_) {
item.RehashBasedOnMap(local_isolate());
item.RehashBasedOnMap(isolate());
}
}
@ -159,8 +154,6 @@ void Deserializer::DeserializeDeferredObjects() {
void Deserializer::LogNewMapEvents() {
DisallowHeapAllocation no_gc;
DCHECK(is_main_thread());
for (Map map : new_maps_) {
DCHECK(FLAG_trace_maps);
LOG(isolate(), MapCreate(map));
@ -170,9 +163,9 @@ void Deserializer::LogNewMapEvents() {
void Deserializer::LogScriptEvents(Script script) {
DisallowHeapAllocation no_gc;
LOG(local_isolate(),
LOG(isolate(),
ScriptEvent(Logger::ScriptEventType::kDeserialize, script.id()));
LOG(local_isolate(), ScriptDetails(script));
LOG(isolate(), ScriptDetails(script));
}
StringTableInsertionKey::StringTableInsertionKey(Handle<String> string)
@ -223,11 +216,6 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj,
if (obj.IsString()) {
String string = String::cast(obj);
if (string.IsInternalizedString()) {
// Off-thread internalized strings are canonicalized during off-thread
// isolate publish, so we don't have to canonicalize them here.
// TODO(crbug.com/v8/10729): Add concurrent string table support.
if (local_isolate().is_off_thread()) return string;
// Canonicalize the internalized string. If it already exists in the
// string table, set it to forward to the existing one.
@ -244,7 +232,7 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj,
return result;
}
} else if (obj.IsScript()) {
new_scripts_.push_back(handle(Script::cast(obj), local_isolate()));
new_scripts_.push_back(handle(Script::cast(obj), isolate()));
} else if (obj.IsAllocationSite()) {
// We should link new allocation sites, but we can't do this immediately
// because |AllocationSite::HasWeakNext()| internally accesses
@ -321,7 +309,7 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj,
JSArrayBuffer buffer = JSArrayBuffer::cast(obj);
// Postpone allocation of backing store to avoid triggering the GC.
if (buffer.backing_store() != nullptr) {
new_off_heap_array_buffers_.push_back(handle(buffer, local_isolate()));
new_off_heap_array_buffers_.push_back(handle(buffer, isolate()));
}
} else if (obj.IsBytecodeArray()) {
// TODO(mythria): Remove these once we store the default values for these
@ -354,9 +342,8 @@ HeapObject Deserializer::GetBackReferencedObject(SnapshotSpace space) {
case SnapshotSpace::kReadOnlyHeap: {
uint32_t chunk_index = source_.GetInt();
uint32_t chunk_offset = source_.GetInt();
if (is_off_thread() || isolate()->heap()->deserialization_complete()) {
ReadOnlySpace* read_only_space =
local_isolate()->heap()->read_only_space();
if (isolate()->heap()->deserialization_complete()) {
ReadOnlySpace* read_only_space = isolate()->heap()->read_only_space();
ReadOnlyPage* page = read_only_space->pages()[chunk_index];
Address address = page->OffsetToAddress(chunk_offset);
obj = HeapObject::FromAddress(address);
@ -401,7 +388,7 @@ HeapObject Deserializer::ReadObject(SnapshotSpace space) {
Address address = allocator()->Allocate(space, size);
HeapObject obj = HeapObject::FromAddress(address);
local_isolate()->heap()->OnAllocationEvent(obj, size);
isolate()->heap()->OnAllocationEvent(obj, size);
MaybeObjectSlot current(address);
MaybeObjectSlot limit(address + size);
@ -708,9 +695,7 @@ bool Deserializer::ReadData(TSlot current, TSlot limit,
reference_id < num_api_references_,
"too few external references provided through the API");
address = static_cast<Address>(
local_isolate()
.main_thread()
->api_external_references()[reference_id]);
isolate()->api_external_references()[reference_id]);
} else {
address = reinterpret_cast<Address>(NoExternalReferencesCallback);
}
@ -724,8 +709,7 @@ bool Deserializer::ReadData(TSlot current, TSlot limit,
}
case kClearedWeakReference:
current =
Write(current, HeapObjectReference::ClearedValue(local_isolate()));
current = Write(current, HeapObjectReference::ClearedValue(isolate()));
break;
case kWeakPrefix:
@ -753,7 +737,7 @@ bool Deserializer::ReadData(TSlot current, TSlot limit,
int id = data & kRootArrayConstantsMask;
RootIndex root_index = static_cast<RootIndex>(id);
MaybeObject object =
MaybeObject(ReadOnlyRoots(local_isolate()).at(root_index));
MaybeObject(ReadOnlyRoots(isolate()).at(root_index));
DCHECK(!Heap::InYoungGeneration(object));
current = Write(current, object);
break;
@ -849,14 +833,13 @@ TSlot Deserializer::ReadDataCase(TSlot current, Address current_object_address,
} else if (bytecode == kRootArray) {
int id = source_.GetInt();
RootIndex root_index = static_cast<RootIndex>(id);
heap_object = HeapObject::cast(local_isolate()->root(root_index));
heap_object = HeapObject::cast(isolate()->root(root_index));
emit_write_barrier = Heap::InYoungGeneration(heap_object);
hot_objects_.Add(heap_object);
} else if (bytecode == kReadOnlyObjectCache) {
int cache_index = source_.GetInt();
heap_object = HeapObject::cast(
local_isolate()->read_only_heap()->cached_read_only_object(
cache_index));
isolate()->read_only_heap()->cached_read_only_object(cache_index));
DCHECK(!Heap::InYoungGeneration(heap_object));
emit_write_barrier = false;
} else if (bytecode == kStartupObjectCache) {
@ -879,7 +862,7 @@ TSlot Deserializer::ReadDataCase(TSlot current, Address current_object_address,
if (emit_write_barrier && write_barrier_needed) {
DCHECK_IMPLIES(FLAG_disable_write_barriers, !write_barrier_needed);
HeapObject host_object = HeapObject::FromAddress(current_object_address);
SLOW_DCHECK(local_isolate()->heap()->Contains(host_object));
SLOW_DCHECK(isolate()->heap()->Contains(host_object));
GenerationalBarrier(host_object, MaybeObjectSlot(current.address()),
heap_object_ref);
}

View File

@ -8,7 +8,6 @@
#include <utility>
#include <vector>
#include "src/execution/local-isolate-wrapper.h"
#include "src/objects/allocation-site.h"
#include "src/objects/api-callbacks.h"
#include "src/objects/backing-store.h"
@ -49,7 +48,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
// Create a deserializer from a snapshot byte source.
template <class Data>
Deserializer(Data* data, bool deserializing_user_code)
: local_isolate_(nullptr),
: isolate_(nullptr),
source_(data->Payload()),
magic_number_(data->GetMagicNumber()),
deserializing_user_code_(deserializing_user_code),
@ -60,10 +59,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
backing_stores_.push_back({});
}
void Initialize(Isolate* isolate) {
Initialize(LocalIsolateWrapper(isolate));
}
void Initialize(LocalIsolateWrapper isolate);
void Initialize(Isolate* isolate);
void DeserializeDeferredObjects();
// Create Log events for newly deserialized objects.
@ -85,10 +81,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
CHECK_EQ(new_off_heap_array_buffers().size(), 0);
}
LocalIsolateWrapper local_isolate() const { return local_isolate_; }
Isolate* isolate() const { return local_isolate().main_thread(); }
bool is_main_thread() const { return local_isolate().is_main_thread(); }
bool is_off_thread() const { return local_isolate().is_off_thread(); }
Isolate* isolate() const { return isolate_; }
SnapshotByteSource* source() { return &source_; }
const std::vector<AllocationSite>& new_allocation_sites() const {
@ -180,7 +173,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
HeapObject PostProcessNewObject(HeapObject obj, SnapshotSpace space);
// Cached current isolate.
LocalIsolateWrapper local_isolate_;
Isolate* isolate_;
// Objects from the attached object descriptions in the serialized user code.
std::vector<Handle<HeapObject>> attached_objects_;
@ -226,7 +219,8 @@ class StringTableInsertionKey final : public StringTableKey {
bool IsMatch(String string) override;
V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate) override;
V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate);
V8_WARN_UNUSED_RESULT Handle<String> AsHandle(LocalIsolate* isolate);
private:
uint32_t ComputeHashField(String string);

View File

@ -6,7 +6,6 @@
#include "src/codegen/assembler-inl.h"
#include "src/execution/isolate.h"
#include "src/execution/local-isolate-wrapper-inl.h"
#include "src/heap/heap-inl.h"
#include "src/objects/allocation-site-inl.h"
#include "src/objects/objects.h"
@ -27,34 +26,25 @@ ObjectDeserializer::DeserializeSharedFunctionInfo(
d.AddAttachedObject(source);
Handle<HeapObject> result;
return d.Deserialize(LocalIsolateWrapper(isolate)).ToHandle(&result)
return d.Deserialize(isolate).ToHandle(&result)
? Handle<SharedFunctionInfo>::cast(result)
: MaybeHandle<SharedFunctionInfo>();
}
MaybeHandle<SharedFunctionInfo>
ObjectDeserializer::DeserializeSharedFunctionInfoOffThread(
OffThreadIsolate* isolate, const SerializedCodeData* data,
LocalIsolate* isolate, const SerializedCodeData* data,
Handle<String> source) {
DCHECK(ReadOnlyHeap::Contains(*source) || Heap::InOffThreadSpace(*source));
ObjectDeserializer d(data);
d.AddAttachedObject(source);
Handle<HeapObject> result;
return d.Deserialize(LocalIsolateWrapper(isolate)).ToHandle(&result)
? Handle<SharedFunctionInfo>::cast(result)
: MaybeHandle<SharedFunctionInfo>();
// TODO(leszeks): Add LocalHeap support to deserializer
UNREACHABLE();
}
MaybeHandle<HeapObject> ObjectDeserializer::Deserialize(
LocalIsolateWrapper local_isolate) {
Initialize(local_isolate);
MaybeHandle<HeapObject> ObjectDeserializer::Deserialize(Isolate* isolate) {
Initialize(isolate);
if (!allocator()->ReserveSpace()) return MaybeHandle<HeapObject>();
DCHECK(deserializing_user_code());
LocalHandleScopeWrapper scope(local_isolate);
HandleScope scope(isolate);
Handle<HeapObject> result;
{
DisallowHeapAllocation no_gc;
@ -62,14 +52,10 @@ MaybeHandle<HeapObject> ObjectDeserializer::Deserialize(
VisitRootPointer(Root::kStartupObjectCache, nullptr, FullObjectSlot(&root));
DeserializeDeferredObjects();
CHECK(new_code_objects().empty());
if (is_main_thread()) {
LinkAllocationSites();
LogNewMapEvents();
}
result = handle(HeapObject::cast(root), local_isolate);
if (is_main_thread()) {
allocator()->RegisterDeserializedObjectsForBlackAllocation();
}
LinkAllocationSites();
LogNewMapEvents();
result = handle(HeapObject::cast(root), isolate);
allocator()->RegisterDeserializedObjectsForBlackAllocation();
}
Rehash();
@ -78,31 +64,23 @@ MaybeHandle<HeapObject> ObjectDeserializer::Deserialize(
}
void ObjectDeserializer::CommitPostProcessedObjects() {
if (is_main_thread()) {
for (Handle<JSArrayBuffer> buffer : new_off_heap_array_buffers()) {
uint32_t store_index = buffer->GetBackingStoreRefForDeserialization();
auto bs = backing_store(store_index);
SharedFlag shared =
bs && bs->is_shared() ? SharedFlag::kShared : SharedFlag::kNotShared;
buffer->Setup(shared, bs);
}
} else {
CHECK_EQ(new_off_heap_array_buffers().size(), 0);
for (Handle<JSArrayBuffer> buffer : new_off_heap_array_buffers()) {
uint32_t store_index = buffer->GetBackingStoreRefForDeserialization();
auto bs = backing_store(store_index);
SharedFlag shared =
bs && bs->is_shared() ? SharedFlag::kShared : SharedFlag::kNotShared;
buffer->Setup(shared, bs);
}
for (Handle<Script> script : new_scripts()) {
// Assign a new script id to avoid collision.
script->set_id(local_isolate()->GetNextScriptId());
script->set_id(isolate()->GetNextScriptId());
LogScriptEvents(*script);
// Add script to list.
if (is_main_thread()) {
Handle<WeakArrayList> list = isolate()->factory()->script_list();
list = WeakArrayList::AddToEnd(isolate(), list,
MaybeObjectHandle::Weak(script));
isolate()->heap()->SetRootScriptList(*list);
} else {
local_isolate().off_thread()->heap()->AddToScriptList(script);
}
}
}

Some files were not shown because too many files have changed in this diff Show More