1// Copyright 2022 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_MAGLEV_MAGLEV_REGISTER_FRAME_ARRAY_H_
6#define V8_MAGLEV_MAGLEV_REGISTER_FRAME_ARRAY_H_
7
8#include "src/interpreter/bytecode-register.h"
9#include "src/maglev/maglev-compilation-unit.h"
10#include "src/zone/zone.h"
11
12namespace v8 {
13namespace internal {
14namespace maglev {
15
16// Vector of values associated with a bytecode's register frame. Indexable by
17// interpreter register.
18template <typename T>
19class RegisterFrameArray {
20 public:
21  explicit RegisterFrameArray(const MaglevCompilationUnit& info) {
22    // The first local is at index zero, parameters are behind it with
23    // negative indices, and the unoptimized frame header is between the two,
24    // so the entire frame state including parameters is the distance from the
25    // last parameter to the last local frame register, plus one to include both
26    // ends.
27    interpreter::Register last_local =
28        interpreter::Register(info.register_count() - 1);
29    interpreter::Register last_param =
30        interpreter::Register::FromParameterIndex(info.parameter_count() - 1);
31    DCHECK_LT(last_param.index(), 0);
32    T* frame =
33        info.zone()->NewArray<T>(last_local.index() - last_param.index() + 1);
34
35    // Set frame_start_ to a "butterfly" pointer into the middle of the above
36    // Zone-allocated array. Parameters are at a negative index, so we have to
37    // subtract it from the above frame pointer.
38    frame_start_ = frame - last_param.index();
39  }
40
41  // Disallow copy (use CopyFrom instead).
42  RegisterFrameArray(const RegisterFrameArray& other) V8_NOEXCEPT = delete;
43  RegisterFrameArray& operator=(const RegisterFrameArray& other)
44      V8_NOEXCEPT = delete;
45
46  // Allow move.
47  RegisterFrameArray(RegisterFrameArray&& other) V8_NOEXCEPT = default;
48  RegisterFrameArray& operator=(RegisterFrameArray&& other)
49      V8_NOEXCEPT = default;
50
51  void CopyFrom(const MaglevCompilationUnit& info,
52                const RegisterFrameArray& other,
53                const compiler::BytecodeLivenessState* liveness) {
54    interpreter::Register last_param =
55        interpreter::Register::FromParameterIndex(info.parameter_count() - 1);
56    int end = 1;
57    if (!liveness) {
58      interpreter::Register last_local =
59          interpreter::Register(info.register_count() - 1);
60      end = last_local.index();
61    }
62    // All parameters are live.
63    for (int index = last_param.index(); index <= end; ++index) {
64      interpreter::Register reg(index);
65      (*this)[reg] = other[reg];
66    }
67    if (liveness) {
68      for (int index : *liveness) {
69        interpreter::Register reg(index);
70        (*this)[reg] = other[reg];
71      }
72    }
73  }
74
75  T& operator[](interpreter::Register reg) { return frame_start_[reg.index()]; }
76
77  const T& operator[](interpreter::Register reg) const {
78    return frame_start_[reg.index()];
79  }
80
81 private:
82  static int DataSize(int register_count, int parameter_count) {
83    // The first local is at index zero, parameters are behind it with
84    // negative indices, and the unoptimized frame header is between the two,
85    // so the entire frame state including parameters is the distance from the
86    // last parameter to the last local frame register, plus one to include both
87    // ends.
88    interpreter::Register last_local =
89        interpreter::Register(register_count - 1);
90    interpreter::Register last_param =
91        interpreter::Register::FromParameterIndex(parameter_count - 1);
92    return last_local.index() - last_param.index() + 1;
93  }
94
95  T* data_begin(int parameter_count) const {
96    return frame_start_ +
97           interpreter::Register::FromParameterIndex(parameter_count - 1)
98               .index();
99  }
100
101  // Butterfly pointer for registers, pointing into the middle of a
102  // Zone-allocated Node array.
103  //                                        |
104  //                                        v
105  // [Parameters] [Unoptimized Frame Header] [Locals]
106  T* frame_start_ = nullptr;
107};
108
109}  // namespace maglev
110}  // namespace internal
111}  // namespace v8
112
113#endif  // V8_MAGLEV_MAGLEV_REGISTER_FRAME_ARRAY_H_
114