blob: 4966126824786cc12a760ff2384ab9d49a892eca [file] [log] [blame] [edit]
// 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.
#ifndef V8_MAGLEV_MAGLEV_COMPILATION_INFO_H_
#define V8_MAGLEV_MAGLEV_COMPILATION_INFO_H_
#include <memory>
#include <optional>
#include "src/handles/handles.h"
#include "src/handles/maybe-handles.h"
#include "src/utils/utils.h"
#include "src/zone/zone.h"
namespace v8 {
namespace base {
class DefaultAllocationPolicy;
}
namespace internal {
class Isolate;
class PersistentHandles;
class SharedFunctionInfo;
class TranslationArrayBuilder;
namespace compiler {
class JSHeapBroker;
}
namespace maglev {
class MaglevCompilationUnit;
class MaglevGraphLabeller;
class MaglevCodeGenerator;
// A list of v8_flag values copied into the MaglevCompilationInfo for
// guaranteed {immutable,threadsafe} access.
#define MAGLEV_COMPILATION_FLAG_LIST(V) \
V(code_comments) \
V(maglev) \
V(print_maglev_code) \
V(print_maglev_graph) \
V(trace_maglev_regalloc)
class MaglevCompilationInfo final {
public:
static std::unique_ptr<MaglevCompilationInfo> NewForTurboshaft(
Isolate* isolate, compiler::JSHeapBroker* broker,
IndirectHandle<JSFunction> function, BytecodeOffset osr_offset,
bool specialize_to_function_context) {
// Doesn't use make_unique due to the private ctor.
return std::unique_ptr<MaglevCompilationInfo>(new MaglevCompilationInfo(
isolate, function, osr_offset, broker, specialize_to_function_context,
/*for_turboshaft_frontend*/ true));
}
static std::unique_ptr<MaglevCompilationInfo> New(
Isolate* isolate, IndirectHandle<JSFunction> function,
BytecodeOffset osr_offset) {
// Doesn't use make_unique due to the private ctor.
return std::unique_ptr<MaglevCompilationInfo>(
new MaglevCompilationInfo(isolate, function, osr_offset));
}
~MaglevCompilationInfo();
Zone* zone() { return &zone_; }
compiler::JSHeapBroker* broker() const { return broker_; }
MaglevCompilationUnit* toplevel_compilation_unit() const {
return toplevel_compilation_unit_;
}
IndirectHandle<JSFunction> toplevel_function() const {
return toplevel_function_;
}
BytecodeOffset toplevel_osr_offset() const { return osr_offset_; }
bool toplevel_is_osr() const { return osr_offset_ != BytecodeOffset::None(); }
void set_code(IndirectHandle<Code> code) {
DCHECK(code_.is_null());
code_ = code;
}
MaybeIndirectHandle<Code> get_code() { return code_; }
bool is_turbolev() const { return is_turbolev_; }
bool has_graph_labeller() const { return !!graph_labeller_; }
void set_graph_labeller(MaglevGraphLabeller* graph_labeller);
MaglevGraphLabeller* graph_labeller() const {
DCHECK(has_graph_labeller());
return graph_labeller_.get();
}
#ifdef V8_ENABLE_MAGLEV
void set_code_generator(std::unique_ptr<MaglevCodeGenerator> code_generator);
MaglevCodeGenerator* code_generator() const { return code_generator_.get(); }
#endif
// Flag accessors (for thread-safe access to global flags).
// TODO(v8:7700): Consider caching these.
#define V(Name) \
bool Name() const { return Name##_; }
MAGLEV_COMPILATION_FLAG_LIST(V)
#undef V
bool collect_source_positions() const { return collect_source_positions_; }
bool specialize_to_function_context() const {
return specialize_to_function_context_;
}
// Must be called from within a MaglevCompilationHandleScope. Transfers owned
// handles (e.g. shared_, function_) to the new scope.
void ReopenAndCanonicalizeHandlesInNewScope(Isolate* isolate);
// Persistent and canonical handles are passed back and forth between the
// Isolate, this info, and the LocalIsolate.
void set_persistent_handles(
std::unique_ptr<PersistentHandles>&& persistent_handles);
std::unique_ptr<PersistentHandles> DetachPersistentHandles();
void set_canonical_handles(
std::unique_ptr<CanonicalHandlesMap>&& canonical_handles);
std::unique_ptr<CanonicalHandlesMap> DetachCanonicalHandles();
bool is_detached();
bool could_not_inline_all_candidates() {
return could_not_inline_all_candidates_;
}
void set_could_not_inline_all_candidates() {
could_not_inline_all_candidates_ = true;
}
private:
MaglevCompilationInfo(
Isolate* isolate, IndirectHandle<JSFunction> function,
BytecodeOffset osr_offset,
std::optional<compiler::JSHeapBroker*> broker = std::nullopt,
std::optional<bool> specialize_to_function_context = std::nullopt,
bool for_turboshaft_frontend = false);
// Storing the raw pointer to the CanonicalHandlesMap is generally not safe.
// Use DetachCanonicalHandles() to transfer ownership instead.
// We explicitly allow the JSHeapBroker to store the raw pointer as it is
// guaranteed that the MaglevCompilationInfo's lifetime exceeds the lifetime
// of the broker.
CanonicalHandlesMap* canonical_handles() { return canonical_handles_.get(); }
friend compiler::JSHeapBroker;
Zone zone_;
compiler::JSHeapBroker* broker_;
// Must be initialized late since it requires an initialized heap broker.
MaglevCompilationUnit* toplevel_compilation_unit_ = nullptr;
IndirectHandle<JSFunction> toplevel_function_;
IndirectHandle<Code> code_;
BytecodeOffset osr_offset_;
// True if this MaglevCompilationInfo owns its broker and false otherwise. In
// particular, when used as Turboshaft front-end, this will use Turboshaft's
// broker.
bool owns_broker_ = true;
// When this MaglevCompilationInfo is created to be used in Turboshaft's
// frontend, {for_turboshaft_frontend_} is true.
bool is_turbolev_ = false;
// True if some inlinees were skipped due to total size constraints.
bool could_not_inline_all_candidates_ = false;
std::unique_ptr<MaglevGraphLabeller> graph_labeller_;
#ifdef V8_ENABLE_MAGLEV
// Produced off-thread during ExecuteJobImpl.
std::unique_ptr<MaglevCodeGenerator> code_generator_;
#endif
#define V(Name) const bool Name##_;
MAGLEV_COMPILATION_FLAG_LIST(V)
#undef V
bool collect_source_positions_;
// If enabled, the generated code can rely on the function context to be a
// constant (known at compile-time). This opens new optimization
// opportunities, but prevents code sharing between different function
// contexts.
const bool specialize_to_function_context_;
// 1) PersistentHandles created via PersistentHandlesScope inside of
// CompilationHandleScope.
// 2) Owned by MaglevCompilationInfo.
// 3) Owned by the broker's LocalHeap when entering the LocalHeapScope.
// 4) Back to MaglevCompilationInfo when exiting the LocalHeapScope.
//
// TODO(jgruber,v8:7700): Update this comment:
//
// In normal execution it gets destroyed when PipelineData gets destroyed.
// There is a special case in GenerateCodeForTesting where the JSHeapBroker
// will not be retired in that same method. In this case, we need to re-attach
// the PersistentHandles container to the JSHeapBroker.
std::unique_ptr<PersistentHandles> ph_;
// Canonical handles follow the same path as described by the persistent
// handles above. The only difference is that is created in the
// CanonicalHandleScope(i.e step 1) is different).
std::unique_ptr<CanonicalHandlesMap> canonical_handles_;
};
} // namespace maglev
} // namespace internal
} // namespace v8
#endif // V8_MAGLEV_MAGLEV_COMPILATION_INFO_H_