blob: 44ce492b780018f2fd94fda5ca6d7c178e47ac72 [file] [log] [blame]
// Copyright 2022 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/maglev/maglev-compilation-info.h"
#include <optional>
#include "src/codegen/compiler.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/js-heap-broker.h"
#include "src/execution/isolate.h"
#include "src/flags/flags.h"
#include "src/handles/persistent-handles.h"
#ifdef V8_ENABLE_MAGLEV
#include "src/maglev/maglev-code-generator.h"
#include "src/maglev/maglev-concurrent-dispatcher.h"
#endif
#include "src/maglev/maglev-compilation-unit.h"
#include "src/maglev/maglev-graph-labeller.h"
#include "src/objects/js-function-inl.h"
#include "src/utils/identity-map.h"
namespace v8 {
namespace internal {
namespace maglev {
namespace {
constexpr char kMaglevZoneName[] = "maglev-compilation-job-zone";
class V8_NODISCARD MaglevCompilationHandleScope final {
public:
MaglevCompilationHandleScope(Isolate* isolate,
maglev::MaglevCompilationInfo* info)
: info_(info),
persistent_(isolate)
#ifdef V8_ENABLE_MAGLEV
,
exported_info_(info)
#endif
{
info->ReopenAndCanonicalizeHandlesInNewScope(isolate);
}
~MaglevCompilationHandleScope() {
info_->set_persistent_handles(persistent_.Detach());
}
private:
maglev::MaglevCompilationInfo* const info_;
PersistentHandlesScope persistent_;
#ifdef V8_ENABLE_MAGLEV
ExportedMaglevCompilationInfo exported_info_;
#endif
};
static bool SpecializeToFunctionContext(
Isolate* isolate, BytecodeOffset osr_offset,
DirectHandle<JSFunction> function,
std::optional<bool> specialize_to_function_context_override) {
if (osr_offset != BytecodeOffset::None()) return false;
if (!v8_flags.maglev_function_context_specialization) return false;
if (specialize_to_function_context_override.has_value()) {
return specialize_to_function_context_override.value();
}
if (function->shared()->function_context_independent_compiled()) {
return false;
}
return function->raw_feedback_cell()->map() ==
ReadOnlyRoots(isolate).one_closure_cell_map();
}
} // namespace
MaglevCompilationInfo::MaglevCompilationInfo(
Isolate* isolate, IndirectHandle<JSFunction> function,
BytecodeOffset osr_offset, std::optional<compiler::JSHeapBroker*> js_broker,
std::optional<bool> specialize_to_function_context,
bool for_turboshaft_frontend)
: zone_(isolate->allocator(), kMaglevZoneName),
broker_(js_broker.has_value()
? js_broker.value()
: new compiler::JSHeapBroker(isolate, zone(),
v8_flags.trace_heap_broker,
CodeKind::MAGLEV)),
toplevel_function_(function),
osr_offset_(osr_offset),
owns_broker_(!js_broker.has_value()),
is_turbolev_(for_turboshaft_frontend)
#define V(Name) , Name##_(v8_flags.Name)
MAGLEV_COMPILATION_FLAG_LIST(V)
#undef V
,
specialize_to_function_context_(SpecializeToFunctionContext(
isolate, osr_offset, function, specialize_to_function_context)) {
if (owns_broker_) {
canonical_handles_ = std::make_unique<CanonicalHandlesMap>(
isolate->heap(), ZoneAllocationPolicy(&zone_));
compiler::CurrentHeapBrokerScope current_broker(broker_);
MaglevCompilationHandleScope compilation(isolate, this);
compiler::CompilationDependencies* deps =
zone()->New<compiler::CompilationDependencies>(broker(), zone());
USE(deps); // The deps register themselves in the heap broker.
broker()->AttachCompilationInfo(this);
// Heap broker initialization may already use IsPendingAllocation.
isolate->heap()->PublishMainThreadPendingAllocations();
broker()->InitializeAndStartSerializing(
direct_handle(function->native_context(), isolate));
broker()->StopSerializing();
// Serialization may have allocated.
isolate->heap()->PublishMainThreadPendingAllocations();
toplevel_compilation_unit_ =
MaglevCompilationUnit::New(zone(), this, function);
} else {
toplevel_compilation_unit_ =
MaglevCompilationUnit::New(zone(), this, function);
}
collect_source_positions_ = isolate->NeedsDetailedOptimizedCodeLineInfo();
}
MaglevCompilationInfo::~MaglevCompilationInfo() {
if (owns_broker_) {
delete broker_;
}
}
void MaglevCompilationInfo::set_graph_labeller(
MaglevGraphLabeller* graph_labeller) {
graph_labeller_.reset(graph_labeller);
}
#ifdef V8_ENABLE_MAGLEV
void MaglevCompilationInfo::set_code_generator(
std::unique_ptr<MaglevCodeGenerator> code_generator) {
code_generator_ = std::move(code_generator);
}
#endif
namespace {
template <typename T>
IndirectHandle<T> CanonicalHandle(CanonicalHandlesMap* canonical_handles,
Tagged<T> object, Isolate* isolate) {
DCHECK_NOT_NULL(canonical_handles);
DCHECK(PersistentHandlesScope::IsActive(isolate));
auto find_result = canonical_handles->FindOrInsert(object);
if (!find_result.already_exists) {
*find_result.entry = IndirectHandle<T>(object, isolate).location();
}
return IndirectHandle<T>(*find_result.entry);
}
} // namespace
void MaglevCompilationInfo::ReopenAndCanonicalizeHandlesInNewScope(
Isolate* isolate) {
toplevel_function_ =
CanonicalHandle(canonical_handles_.get(), *toplevel_function_, isolate);
}
void MaglevCompilationInfo::set_persistent_handles(
std::unique_ptr<PersistentHandles>&& persistent_handles) {
DCHECK_NULL(ph_);
ph_ = std::move(persistent_handles);
DCHECK_NOT_NULL(ph_);
}
std::unique_ptr<PersistentHandles>
MaglevCompilationInfo::DetachPersistentHandles() {
DCHECK_NOT_NULL(ph_);
return std::move(ph_);
}
void MaglevCompilationInfo::set_canonical_handles(
std::unique_ptr<CanonicalHandlesMap>&& canonical_handles) {
DCHECK_NULL(canonical_handles_);
canonical_handles_ = std::move(canonical_handles);
DCHECK_NOT_NULL(canonical_handles_);
}
bool MaglevCompilationInfo::is_detached() {
return toplevel_function_->context()->IsDetached();
}
std::unique_ptr<CanonicalHandlesMap>
MaglevCompilationInfo::DetachCanonicalHandles() {
DCHECK_NOT_NULL(canonical_handles_);
return std::move(canonical_handles_);
}
} // namespace maglev
} // namespace internal
} // namespace v8