%PDF- %PDF-
Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/maglev/ |
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/maglev/maglev-ir-inl.h |
// Copyright 2021 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_IR_INL_H_ #define V8_MAGLEV_MAGLEV_IR_INL_H_ #include <type_traits> #include "src/maglev/maglev-interpreter-frame-state.h" #include "src/maglev/maglev-ir.h" namespace v8 { namespace internal { namespace maglev { namespace detail { // A little bit of template magic to allow DeepForEachInput to either take a // `const DeoptInfo*` or a `DeoptInfo*`, depending on whether the Function // processes read-only `ValueNode*` or read-write `ValueNode*&`. template <typename F, typename Ret, typename A, typename... Rest> A first_argument_helper(Ret (F::*)(A, Rest...)); template <typename F, typename Ret, typename A, typename... Rest> A first_argument_helper(Ret (F::*)(A, Rest...) const); template <typename Function> using first_argument = decltype(first_argument_helper( &std::remove_reference_t<Function>::operator())); template <typename T, typename Function> using const_if_function_first_arg_not_reference = std::conditional_t<std::is_reference_v<first_argument<Function>>, T, const T>; template <typename Function> void DeepForEachInputImpl( const_if_function_first_arg_not_reference<DeoptFrame, Function>& frame, InputLocation* input_locations, int& index, Function&& f) { if (frame.parent()) { DeepForEachInputImpl(*frame.parent(), input_locations, index, f); } switch (frame.type()) { case DeoptFrame::FrameType::kInterpretedFrame: f(frame.as_interpreted().closure(), &input_locations[index++]); frame.as_interpreted().frame_state()->ForEachValue( frame.as_interpreted().unit(), [&](first_argument<Function> node, interpreter::Register reg) { f(node, &input_locations[index++]); }); break; case DeoptFrame::FrameType::kInlinedArgumentsFrame: { f(frame.as_inlined_arguments().closure(), &input_locations[index++]); for (first_argument<Function> node : frame.as_inlined_arguments().arguments()) { f(node, &input_locations[index++]); } break; } case DeoptFrame::FrameType::kConstructInvokeStubFrame: { f(frame.as_construct_stub().receiver(), &input_locations[index++]); f(frame.as_construct_stub().context(), &input_locations[index++]); break; } case DeoptFrame::FrameType::kBuiltinContinuationFrame: for (first_argument<Function> node : frame.as_builtin_continuation().parameters()) { f(node, &input_locations[index++]); } f(frame.as_builtin_continuation().context(), &input_locations[index++]); break; } } template <typename Function> void DeepForEachInput(const_if_function_first_arg_not_reference< EagerDeoptInfo, Function>* deopt_info, Function&& f) { int index = 0; DeepForEachInputImpl(deopt_info->top_frame(), deopt_info->input_locations(), index, std::forward<Function>(f)); } template <typename Function> void DeepForEachInput(const_if_function_first_arg_not_reference< LazyDeoptInfo, Function>* deopt_info, Function&& f) { int index = 0; InputLocation* input_locations = deopt_info->input_locations(); auto& top_frame = deopt_info->top_frame(); if (top_frame.parent()) { DeepForEachInputImpl(*top_frame.parent(), input_locations, index, f); } // Handle the top-of-frame info separately, since we have to skip the result // location. switch (top_frame.type()) { case DeoptFrame::FrameType::kInterpretedFrame: f(top_frame.as_interpreted().closure(), &input_locations[index++]); top_frame.as_interpreted().frame_state()->ForEachValue( top_frame.as_interpreted().unit(), [&](first_argument<Function> node, interpreter::Register reg) { // Skip over the result location since it is irrelevant for lazy // deopts (unoptimized code will recreate the result). if (deopt_info->IsResultRegister(reg)) return; f(node, &input_locations[index++]); }); break; case DeoptFrame::FrameType::kConstructInvokeStubFrame: { f(top_frame.as_construct_stub().receiver(), &input_locations[index++]); f(top_frame.as_construct_stub().context(), &input_locations[index++]); break; } case DeoptFrame::FrameType::kInlinedArgumentsFrame: // The inlined arguments frame can never be the top frame. UNREACHABLE(); case DeoptFrame::FrameType::kBuiltinContinuationFrame: for (first_argument<Function> node : top_frame.as_builtin_continuation().parameters()) { f(node, &input_locations[index++]); } f(top_frame.as_builtin_continuation().context(), &input_locations[index++]); break; } } } // namespace detail inline void AddDeoptRegistersToSnapshot(RegisterSnapshot* snapshot, const EagerDeoptInfo* deopt_info) { detail::DeepForEachInput(deopt_info, [&](ValueNode* node, InputLocation* input) { if (!input->IsAnyRegister()) return; if (input->IsDoubleRegister()) { snapshot->live_double_registers.set(input->AssignedDoubleRegister()); } else { snapshot->live_registers.set(input->AssignedGeneralRegister()); if (node->is_tagged()) { snapshot->live_tagged_registers.set(input->AssignedGeneralRegister()); } } }); } #ifdef DEBUG inline RegList GetGeneralRegistersUsedAsInputs( const EagerDeoptInfo* deopt_info) { RegList regs; detail::DeepForEachInput(deopt_info, [®s](ValueNode* value, InputLocation* input) { if (input->IsGeneralRegister()) { regs.set(input->AssignedGeneralRegister()); } }); return regs; } #endif // DEBUG // Helper macro for checking that a reglist is empty which prints the contents // when non-empty. #define DCHECK_REGLIST_EMPTY(...) DCHECK_EQ((__VA_ARGS__), RegList{}) // --- // Value location constraint setting helpers. // --- static constexpr int kNoVreg = -1; inline void DefineAsRegister(Node* node) { node->result().SetUnallocated( compiler::UnallocatedOperand::MUST_HAVE_REGISTER, kNoVreg); } inline void DefineAsConstant(Node* node) { node->result().SetUnallocated(compiler::UnallocatedOperand::NONE, kNoVreg); } inline void DefineAsFixed(Node* node, Register reg) { node->result().SetUnallocated(compiler::UnallocatedOperand::FIXED_REGISTER, reg.code(), kNoVreg); } inline void DefineSameAsFirst(Node* node) { node->result().SetUnallocated(kNoVreg, 0); } inline void UseRegister(Input& input) { input.SetUnallocated(compiler::UnallocatedOperand::MUST_HAVE_REGISTER, compiler::UnallocatedOperand::USED_AT_END, kNoVreg); } inline void UseAndClobberRegister(Input& input) { input.SetUnallocated(compiler::UnallocatedOperand::MUST_HAVE_REGISTER, compiler::UnallocatedOperand::USED_AT_START, kNoVreg); } inline void UseAny(Input& input) { input.SetUnallocated( compiler::UnallocatedOperand::REGISTER_OR_SLOT_OR_CONSTANT, compiler::UnallocatedOperand::USED_AT_END, kNoVreg); } inline void UseFixed(Input& input, Register reg) { input.SetUnallocated(compiler::UnallocatedOperand::FIXED_REGISTER, reg.code(), kNoVreg); input.node()->SetHint(input.operand()); } inline void UseFixed(Input& input, DoubleRegister reg) { input.SetUnallocated(compiler::UnallocatedOperand::FIXED_FP_REGISTER, reg.code(), kNoVreg); input.node()->SetHint(input.operand()); } } // namespace maglev } // namespace internal } // namespace v8 #endif // V8_MAGLEV_MAGLEV_IR_INL_H_