Commit 854a3728 authored by Jakob Linke's avatar Jakob Linke Committed by V8 LUCI CQ

[maglev] Move deferred code helpers to masm

Bug: v8:7700
Change-Id: Ie9be2aaf0a75cf1fd19f50ce4697f71e92a36df6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3879223Reviewed-by: 's avatarVictor Gomes <victorgomes@chromium.org>
Commit-Queue: Jakob Linke <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83053}
parent 43b4e424
......@@ -86,6 +86,179 @@ inline void MaglevAssembler::DefineExceptionHandlerAndLazyDeoptPoint(
DefineLazyDeoptPoint(node->lazy_deopt_info());
}
// ---
// Deferred code handling.
// ---
namespace detail {
// Base case provides an error.
template <typename T, typename Enable = void>
struct CopyForDeferredHelper {
template <typename U>
struct No_Copy_Helper_Implemented_For_Type;
static void Copy(MaglevCompilationInfo* compilation_info,
No_Copy_Helper_Implemented_For_Type<T>);
};
// Helper for copies by value.
template <typename T, typename Enable = void>
struct CopyForDeferredByValue {
static T Copy(MaglevCompilationInfo* compilation_info, T node) {
return node;
}
};
// Node pointers are copied by value.
template <typename T>
struct CopyForDeferredHelper<
T*, typename std::enable_if<std::is_base_of<NodeBase, T>::value>::type>
: public CopyForDeferredByValue<T*> {};
// Arithmetic values and enums are copied by value.
template <typename T>
struct CopyForDeferredHelper<
T, typename std::enable_if<std::is_arithmetic<T>::value>::type>
: public CopyForDeferredByValue<T> {};
template <typename T>
struct CopyForDeferredHelper<
T, typename std::enable_if<std::is_enum<T>::value>::type>
: public CopyForDeferredByValue<T> {};
// MaglevCompilationInfos are copied by value.
template <>
struct CopyForDeferredHelper<MaglevCompilationInfo*>
: public CopyForDeferredByValue<MaglevCompilationInfo*> {};
// Machine registers are copied by value.
template <>
struct CopyForDeferredHelper<Register>
: public CopyForDeferredByValue<Register> {};
// Bytecode offsets are copied by value.
template <>
struct CopyForDeferredHelper<BytecodeOffset>
: public CopyForDeferredByValue<BytecodeOffset> {};
// EagerDeoptInfo pointers are copied by value.
template <>
struct CopyForDeferredHelper<EagerDeoptInfo*>
: public CopyForDeferredByValue<EagerDeoptInfo*> {};
// ZoneLabelRef is copied by value.
template <>
struct CopyForDeferredHelper<ZoneLabelRef>
: public CopyForDeferredByValue<ZoneLabelRef> {};
// Register snapshots are copied by value.
template <>
struct CopyForDeferredHelper<RegisterSnapshot>
: public CopyForDeferredByValue<RegisterSnapshot> {};
// Feedback slots are copied by value.
template <>
struct CopyForDeferredHelper<FeedbackSlot>
: public CopyForDeferredByValue<FeedbackSlot> {};
template <typename T>
T CopyForDeferred(MaglevCompilationInfo* compilation_info, T&& value) {
return CopyForDeferredHelper<T>::Copy(compilation_info,
std::forward<T>(value));
}
template <typename T>
T CopyForDeferred(MaglevCompilationInfo* compilation_info, T& value) {
return CopyForDeferredHelper<T>::Copy(compilation_info, value);
}
template <typename T>
T CopyForDeferred(MaglevCompilationInfo* compilation_info, const T& value) {
return CopyForDeferredHelper<T>::Copy(compilation_info, value);
}
template <typename Function>
struct FunctionArgumentsTupleHelper
: public FunctionArgumentsTupleHelper<decltype(&Function::operator())> {};
template <typename C, typename R, typename... A>
struct FunctionArgumentsTupleHelper<R (C::*)(A...) const> {
using FunctionPointer = R (*)(A...);
using Tuple = std::tuple<A...>;
static constexpr size_t kSize = sizeof...(A);
};
template <typename R, typename... A>
struct FunctionArgumentsTupleHelper<R (&)(A...)> {
using FunctionPointer = R (*)(A...);
using Tuple = std::tuple<A...>;
static constexpr size_t kSize = sizeof...(A);
};
template <typename T>
struct StripFirstTwoTupleArgs;
template <typename T1, typename T2, typename... T>
struct StripFirstTwoTupleArgs<std::tuple<T1, T2, T...>> {
using Stripped = std::tuple<T...>;
};
template <typename Function>
class DeferredCodeInfoImpl final : public DeferredCodeInfo {
public:
using FunctionPointer =
typename FunctionArgumentsTupleHelper<Function>::FunctionPointer;
using Tuple = typename StripFirstTwoTupleArgs<
typename FunctionArgumentsTupleHelper<Function>::Tuple>::Stripped;
static constexpr size_t kSize = FunctionArgumentsTupleHelper<Function>::kSize;
template <typename... InArgs>
explicit DeferredCodeInfoImpl(MaglevCompilationInfo* compilation_info,
FunctionPointer function, InArgs&&... args)
: function(function),
args(CopyForDeferred(compilation_info, std::forward<InArgs>(args))...) {
}
DeferredCodeInfoImpl(DeferredCodeInfoImpl&&) = delete;
DeferredCodeInfoImpl(const DeferredCodeInfoImpl&) = delete;
void Generate(MaglevAssembler* masm, Label* return_label) override {
DoCall(masm, return_label, std::make_index_sequence<kSize - 2>{});
}
private:
template <size_t... I>
auto DoCall(MaglevAssembler* masm, Label* return_label,
std::index_sequence<I...>) {
// TODO(leszeks): This could be replaced with std::apply in C++17.
return function(masm, return_label, std::get<I>(args)...);
}
FunctionPointer function;
Tuple args;
};
} // namespace detail
template <typename Function, typename... Args>
inline DeferredCodeInfo* MaglevAssembler::PushDeferredCode(
Function&& deferred_code_gen, Args&&... args) {
using DeferredCodeInfoT = detail::DeferredCodeInfoImpl<Function>;
DeferredCodeInfoT* deferred_code =
compilation_info()->zone()->New<DeferredCodeInfoT>(
compilation_info(), deferred_code_gen, std::forward<Args>(args)...);
code_gen_state()->PushDeferredCode(deferred_code);
return deferred_code;
}
// Note this doesn't take capturing lambdas by design, since state may
// change until `deferred_code_gen` is actually executed. Use either a
// non-capturing lambda, or a plain function pointer.
template <typename Function, typename... Args>
inline void MaglevAssembler::JumpToDeferredIf(Condition cond,
Function&& deferred_code_gen,
Args&&... args) {
DeferredCodeInfo* deferred_code = PushDeferredCode<Function, Args...>(
std::forward<Function>(deferred_code_gen), std::forward<Args>(args)...);
if (FLAG_code_comments) {
RecordComment("-- Jump to deferred code");
}
j(cond, &deferred_code->deferred_code_label);
bind(&deferred_code->return_label);
}
} // namespace maglev
} // namespace internal
} // namespace v8
......
......@@ -12,6 +12,25 @@ namespace v8 {
namespace internal {
namespace maglev {
// Label allowed to be passed to deferred code.
class ZoneLabelRef {
public:
explicit ZoneLabelRef(Zone* zone) : label_(zone->New<Label>()) {}
static ZoneLabelRef UnsafeFromLabelPointer(Label* label) {
// This is an unsafe operation, {label} must be zone allocated.
return ZoneLabelRef(label);
}
Label* operator*() { return label_; }
private:
Label* label_;
// Unsafe constructor. {label} must be zone allocated.
explicit ZoneLabelRef(Label* label) : label_(label) {}
};
class MaglevAssembler : public MacroAssembler {
public:
explicit MaglevAssembler(MaglevCodeGenState* code_gen_state)
......@@ -48,6 +67,13 @@ class MaglevAssembler : public MacroAssembler {
inline void DefineExceptionHandlerPoint(NodeBase* node);
inline void DefineExceptionHandlerAndLazyDeoptPoint(NodeBase* node);
template <typename Function, typename... Args>
inline DeferredCodeInfo* PushDeferredCode(Function&& deferred_code_gen,
Args&&... args);
template <typename Function, typename... Args>
inline void JumpToDeferredIf(Condition cond, Function&& deferred_code_gen,
Args&&... args);
compiler::NativeContextRef native_context() const {
return code_gen_state()->broker()->target_native_context();
}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment