1// Copyright 2015 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#include "src/interpreter/bytecode-register.h"
6
7namespace v8 {
8namespace internal {
9namespace interpreter {
10
11static const int kLastParamRegisterIndex =
12    (InterpreterFrameConstants::kRegisterFileFromFp -
13     InterpreterFrameConstants::kLastParamFromFp) /
14    kPointerSize;
15static const int kFunctionClosureRegisterIndex =
16    (InterpreterFrameConstants::kRegisterFileFromFp -
17     StandardFrameConstants::kFunctionOffset) /
18    kPointerSize;
19static const int kCurrentContextRegisterIndex =
20    (InterpreterFrameConstants::kRegisterFileFromFp -
21     StandardFrameConstants::kContextOffset) /
22    kPointerSize;
23static const int kNewTargetRegisterIndex =
24    (InterpreterFrameConstants::kRegisterFileFromFp -
25     InterpreterFrameConstants::kNewTargetFromFp) /
26    kPointerSize;
27static const int kBytecodeArrayRegisterIndex =
28    (InterpreterFrameConstants::kRegisterFileFromFp -
29     InterpreterFrameConstants::kBytecodeArrayFromFp) /
30    kPointerSize;
31static const int kBytecodeOffsetRegisterIndex =
32    (InterpreterFrameConstants::kRegisterFileFromFp -
33     InterpreterFrameConstants::kBytecodeOffsetFromFp) /
34    kPointerSize;
35static const int kCallerPCOffsetRegisterIndex =
36    (InterpreterFrameConstants::kRegisterFileFromFp -
37     InterpreterFrameConstants::kCallerPCOffsetFromFp) /
38    kPointerSize;
39
40Register Register::FromParameterIndex(int index, int parameter_count) {
41  DCHECK_GE(index, 0);
42  DCHECK_LT(index, parameter_count);
43  int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
44  DCHECK_LT(register_index, 0);
45  return Register(register_index);
46}
47
48int Register::ToParameterIndex(int parameter_count) const {
49  DCHECK(is_parameter());
50  return index() - kLastParamRegisterIndex + parameter_count - 1;
51}
52
53Register Register::function_closure() {
54  return Register(kFunctionClosureRegisterIndex);
55}
56
57bool Register::is_function_closure() const {
58  return index() == kFunctionClosureRegisterIndex;
59}
60
61Register Register::current_context() {
62  return Register(kCurrentContextRegisterIndex);
63}
64
65bool Register::is_current_context() const {
66  return index() == kCurrentContextRegisterIndex;
67}
68
69Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
70
71bool Register::is_new_target() const {
72  return index() == kNewTargetRegisterIndex;
73}
74
75Register Register::bytecode_array() {
76  return Register(kBytecodeArrayRegisterIndex);
77}
78
79bool Register::is_bytecode_array() const {
80  return index() == kBytecodeArrayRegisterIndex;
81}
82
83Register Register::bytecode_offset() {
84  return Register(kBytecodeOffsetRegisterIndex);
85}
86
87bool Register::is_bytecode_offset() const {
88  return index() == kBytecodeOffsetRegisterIndex;
89}
90
91// static
92Register Register::virtual_accumulator() {
93  return Register(kCallerPCOffsetRegisterIndex);
94}
95
96OperandSize Register::SizeOfOperand() const {
97  int32_t operand = ToOperand();
98  if (operand >= kMinInt8 && operand <= kMaxInt8) {
99    return OperandSize::kByte;
100  } else if (operand >= kMinInt16 && operand <= kMaxInt16) {
101    return OperandSize::kShort;
102  } else {
103    return OperandSize::kQuad;
104  }
105}
106
107bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
108                             Register reg4, Register reg5) {
109  if (reg1.index() + 1 != reg2.index()) {
110    return false;
111  }
112  if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) {
113    return false;
114  }
115  if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) {
116    return false;
117  }
118  if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) {
119    return false;
120  }
121  return true;
122}
123
124std::string Register::ToString(int parameter_count) const {
125  if (is_current_context()) {
126    return std::string("<context>");
127  } else if (is_function_closure()) {
128    return std::string("<closure>");
129  } else if (is_new_target()) {
130    return std::string("<new.target>");
131  } else if (is_parameter()) {
132    int parameter_index = ToParameterIndex(parameter_count);
133    if (parameter_index == 0) {
134      return std::string("<this>");
135    } else {
136      std::ostringstream s;
137      s << "a" << parameter_index - 1;
138      return s.str();
139    }
140  } else {
141    std::ostringstream s;
142    s << "r" << index();
143    return s.str();
144  }
145}
146
147}  // namespace interpreter
148}  // namespace internal
149}  // namespace v8
150