11cb0ef41Sopenharmony_ci// Copyright 2022 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_MAGLEV_MAGLEV_REGISTER_FRAME_ARRAY_H_
61cb0ef41Sopenharmony_ci#define V8_MAGLEV_MAGLEV_REGISTER_FRAME_ARRAY_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-register.h"
91cb0ef41Sopenharmony_ci#include "src/maglev/maglev-compilation-unit.h"
101cb0ef41Sopenharmony_ci#include "src/zone/zone.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace v8 {
131cb0ef41Sopenharmony_cinamespace internal {
141cb0ef41Sopenharmony_cinamespace maglev {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// Vector of values associated with a bytecode's register frame. Indexable by
171cb0ef41Sopenharmony_ci// interpreter register.
181cb0ef41Sopenharmony_citemplate <typename T>
191cb0ef41Sopenharmony_ciclass RegisterFrameArray {
201cb0ef41Sopenharmony_ci public:
211cb0ef41Sopenharmony_ci  explicit RegisterFrameArray(const MaglevCompilationUnit& info) {
221cb0ef41Sopenharmony_ci    // The first local is at index zero, parameters are behind it with
231cb0ef41Sopenharmony_ci    // negative indices, and the unoptimized frame header is between the two,
241cb0ef41Sopenharmony_ci    // so the entire frame state including parameters is the distance from the
251cb0ef41Sopenharmony_ci    // last parameter to the last local frame register, plus one to include both
261cb0ef41Sopenharmony_ci    // ends.
271cb0ef41Sopenharmony_ci    interpreter::Register last_local =
281cb0ef41Sopenharmony_ci        interpreter::Register(info.register_count() - 1);
291cb0ef41Sopenharmony_ci    interpreter::Register last_param =
301cb0ef41Sopenharmony_ci        interpreter::Register::FromParameterIndex(info.parameter_count() - 1);
311cb0ef41Sopenharmony_ci    DCHECK_LT(last_param.index(), 0);
321cb0ef41Sopenharmony_ci    T* frame =
331cb0ef41Sopenharmony_ci        info.zone()->NewArray<T>(last_local.index() - last_param.index() + 1);
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci    // Set frame_start_ to a "butterfly" pointer into the middle of the above
361cb0ef41Sopenharmony_ci    // Zone-allocated array. Parameters are at a negative index, so we have to
371cb0ef41Sopenharmony_ci    // subtract it from the above frame pointer.
381cb0ef41Sopenharmony_ci    frame_start_ = frame - last_param.index();
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  // Disallow copy (use CopyFrom instead).
421cb0ef41Sopenharmony_ci  RegisterFrameArray(const RegisterFrameArray& other) V8_NOEXCEPT = delete;
431cb0ef41Sopenharmony_ci  RegisterFrameArray& operator=(const RegisterFrameArray& other)
441cb0ef41Sopenharmony_ci      V8_NOEXCEPT = delete;
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  // Allow move.
471cb0ef41Sopenharmony_ci  RegisterFrameArray(RegisterFrameArray&& other) V8_NOEXCEPT = default;
481cb0ef41Sopenharmony_ci  RegisterFrameArray& operator=(RegisterFrameArray&& other)
491cb0ef41Sopenharmony_ci      V8_NOEXCEPT = default;
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  void CopyFrom(const MaglevCompilationUnit& info,
521cb0ef41Sopenharmony_ci                const RegisterFrameArray& other,
531cb0ef41Sopenharmony_ci                const compiler::BytecodeLivenessState* liveness) {
541cb0ef41Sopenharmony_ci    interpreter::Register last_param =
551cb0ef41Sopenharmony_ci        interpreter::Register::FromParameterIndex(info.parameter_count() - 1);
561cb0ef41Sopenharmony_ci    int end = 1;
571cb0ef41Sopenharmony_ci    if (!liveness) {
581cb0ef41Sopenharmony_ci      interpreter::Register last_local =
591cb0ef41Sopenharmony_ci          interpreter::Register(info.register_count() - 1);
601cb0ef41Sopenharmony_ci      end = last_local.index();
611cb0ef41Sopenharmony_ci    }
621cb0ef41Sopenharmony_ci    // All parameters are live.
631cb0ef41Sopenharmony_ci    for (int index = last_param.index(); index <= end; ++index) {
641cb0ef41Sopenharmony_ci      interpreter::Register reg(index);
651cb0ef41Sopenharmony_ci      (*this)[reg] = other[reg];
661cb0ef41Sopenharmony_ci    }
671cb0ef41Sopenharmony_ci    if (liveness) {
681cb0ef41Sopenharmony_ci      for (int index : *liveness) {
691cb0ef41Sopenharmony_ci        interpreter::Register reg(index);
701cb0ef41Sopenharmony_ci        (*this)[reg] = other[reg];
711cb0ef41Sopenharmony_ci      }
721cb0ef41Sopenharmony_ci    }
731cb0ef41Sopenharmony_ci  }
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  T& operator[](interpreter::Register reg) { return frame_start_[reg.index()]; }
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  const T& operator[](interpreter::Register reg) const {
781cb0ef41Sopenharmony_ci    return frame_start_[reg.index()];
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci private:
821cb0ef41Sopenharmony_ci  static int DataSize(int register_count, int parameter_count) {
831cb0ef41Sopenharmony_ci    // The first local is at index zero, parameters are behind it with
841cb0ef41Sopenharmony_ci    // negative indices, and the unoptimized frame header is between the two,
851cb0ef41Sopenharmony_ci    // so the entire frame state including parameters is the distance from the
861cb0ef41Sopenharmony_ci    // last parameter to the last local frame register, plus one to include both
871cb0ef41Sopenharmony_ci    // ends.
881cb0ef41Sopenharmony_ci    interpreter::Register last_local =
891cb0ef41Sopenharmony_ci        interpreter::Register(register_count - 1);
901cb0ef41Sopenharmony_ci    interpreter::Register last_param =
911cb0ef41Sopenharmony_ci        interpreter::Register::FromParameterIndex(parameter_count - 1);
921cb0ef41Sopenharmony_ci    return last_local.index() - last_param.index() + 1;
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  T* data_begin(int parameter_count) const {
961cb0ef41Sopenharmony_ci    return frame_start_ +
971cb0ef41Sopenharmony_ci           interpreter::Register::FromParameterIndex(parameter_count - 1)
981cb0ef41Sopenharmony_ci               .index();
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  // Butterfly pointer for registers, pointing into the middle of a
1021cb0ef41Sopenharmony_ci  // Zone-allocated Node array.
1031cb0ef41Sopenharmony_ci  //                                        |
1041cb0ef41Sopenharmony_ci  //                                        v
1051cb0ef41Sopenharmony_ci  // [Parameters] [Unoptimized Frame Header] [Locals]
1061cb0ef41Sopenharmony_ci  T* frame_start_ = nullptr;
1071cb0ef41Sopenharmony_ci};
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci}  // namespace maglev
1101cb0ef41Sopenharmony_ci}  // namespace internal
1111cb0ef41Sopenharmony_ci}  // namespace v8
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci#endif  // V8_MAGLEV_MAGLEV_REGISTER_FRAME_ARRAY_H_
114