summaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter/register-translator.h
blob: b683a899e2f265e39aca15c9ad01297920f058c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2015 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_INTERPRETER_REGISTER_TRANSLATOR_H_
#define V8_INTERPRETER_REGISTER_TRANSLATOR_H_

#include "src/interpreter/bytecodes.h"

namespace v8 {
namespace internal {
namespace interpreter {

class RegisterMover;

// A class that enables bytecodes having only byte sized register operands
// to access all registers in the two byte space. Most bytecode uses few
// registers so space can be saved if most bytecodes with register operands
// just take byte operands.
//
// To reach the wider register space, a translation window is reserved in
// the byte addressable space specifically for copying registers into and
// out of before a bytecode is emitted. The translation window occupies
// the last register slots at the top of the byte addressable range.
//
// Because of the translation window any registers which naturally lie
// at above the translation window have to have their register index
// incremented by the window width before they are emitted.
//
// This class does not support moving ranges of registers to and from
// the translation window. It would be straightforward to add support
// for constrained ranges, e.g. kRegPair8, kRegTriple8 operands, but
// these would have two negative effects. The translation window would
// need to be wider, further limiting the space for byte operands. And
// every register in a range would need to be moved consuming more
// space in the bytecode array.
class RegisterTranslator final {
 public:
  explicit RegisterTranslator(RegisterMover* mover);

  // Translate and re-write the register operands that are inputs
  // to |bytecode| when it is about to be emitted.
  void TranslateInputRegisters(Bytecode bytecode, uint32_t* raw_operands,
                               int raw_operand_count);

  // Translate and re-write the register operands that are outputs
  // from |bytecode| when it has just been output.
  void TranslateOutputRegisters();

  // Returns true if |reg| is in the translation window.
  static bool InTranslationWindow(Register reg);

  // Return register value as if it had been translated.
  static Register UntranslateRegister(Register reg);

  // Returns the distance in registers between the translation window
  // start and |reg|. The result is negative when |reg| is above the
  // start of the translation window.
  static int DistanceToTranslationWindow(Register reg);

  // Returns true if |reg| can be represented as an 8-bit operand
  // after translation.
  static bool FitsInReg8Operand(Register reg);

  // Returns true if |reg| can be represented as an 16-bit operand
  // after translation.
  static bool FitsInReg16Operand(Register reg);

  // Returns the increment to the register count necessary if the
  // value indicates the translation window is required.
  static int RegisterCountAdjustment(int register_count, int parameter_count);

 private:
  static const int kTranslationWindowLength = 4;
  static const int kTranslationWindowLimit = -kMinInt8;
  static const int kTranslationWindowStart =
      kTranslationWindowLimit - kTranslationWindowLength + 1;

  Register TranslateAndMove(Bytecode bytecode, int operand_index, Register reg);
  static bool RegisterIsMovableToWindow(Bytecode bytecode, int operand_index);

  static Register Translate(Register reg);

  RegisterMover* mover() const { return mover_; }

  // Entity to perform register moves necessary to translate registers
  // and ensure reachability.
  RegisterMover* mover_;

  // Flag to avoid re-entrancy when emitting move bytecodes for
  // translation.
  bool emitting_moves_;

  // Number of window registers in use.
  int window_registers_count_;

  // State for restoring register moves emitted by TranslateOutputRegisters.
  std::pair<Register, Register> output_moves_[kTranslationWindowLength];
  int output_moves_count_;
};

// Interface for RegisterTranslator helper class that will emit
// register move bytecodes at the translator's behest.
class RegisterMover {
 public:
  virtual ~RegisterMover() {}

  // Move register |from| to register |to| with no translation.
  // returns false if either register operand is invalid. Implementations
  // of this method must be aware that register moves with bad
  // register values are a security hole.
  virtual void MoveRegisterUntranslated(Register from, Register to) = 0;
};

}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_REGISTER_TRANSLATOR_H_