OLD | NEW |
(Empty) | |
| 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 #ifndef V8_INTERPRETER_REGISTER_TRANSLATOR_H_ |
| 6 #define V8_INTERPRETER_REGISTER_TRANSLATOR_H_ |
| 7 |
| 8 #include "src/interpreter/bytecodes.h" |
| 9 |
| 10 namespace v8 { |
| 11 namespace internal { |
| 12 namespace interpreter { |
| 13 |
| 14 class RegisterMover; |
| 15 |
| 16 // A class that enables bytecodes having only byte sized register operands |
| 17 // to access all registers in the two byte space. Most bytecode uses few |
| 18 // registers so space can be saved if most bytecodes with register operands |
| 19 // just take byte operands. |
| 20 // |
| 21 // To reach the wider register space, a translation window is reserved in |
| 22 // the byte addressable space specifically for copying registers into and |
| 23 // out of before a bytecode is emitted. The translation window occupies |
| 24 // the last register slots at the top of the byte addressable range. |
| 25 // |
| 26 // Because of the translation window any registers which naturally lie |
| 27 // at above the translation window have to have their register index |
| 28 // incremented by the window width before they are emitted. |
| 29 // |
| 30 // This class does not support moving ranges of registers to and from |
| 31 // the translation window. It would be straightforward to add support |
| 32 // for constrained ranges, e.g. kRegPair8, kRegTriple8 operands, but |
| 33 // these would have two negative effects. The translation window would |
| 34 // need to be wider, further limiting the space for byte operands. And |
| 35 // every register in a range would need to be moved consuming more |
| 36 // space in the bytecode array. |
| 37 class RegisterTranslator final { |
| 38 public: |
| 39 explicit RegisterTranslator(RegisterMover* mover); |
| 40 |
| 41 // Translate and re-write the register operands that are inputs |
| 42 // to |bytecode| when it is about to be emitted. |
| 43 void TranslateInputRegisters(Bytecode bytecode, uint32_t* raw_operands, |
| 44 int raw_operand_count); |
| 45 |
| 46 // Translate and re-write the register operands that are outputs |
| 47 // from |bytecode| when it has just been output. |
| 48 void TranslateOutputRegisters(); |
| 49 |
| 50 // Returns true if |reg| is in the translation window. |
| 51 static bool InTranslationWindow(Register reg); |
| 52 |
| 53 // Return register value as if it had been translated. |
| 54 static Register UntranslateRegister(Register reg); |
| 55 |
| 56 // Returns the distance in registers between the translation window |
| 57 // start and |reg|. The result is negative when |reg| is above the |
| 58 // start of the translation window. |
| 59 static int DistanceToTranslationWindow(Register reg); |
| 60 |
| 61 // Returns true if |reg| can be represented as an 8-bit operand |
| 62 // after translation. |
| 63 static bool FitsInReg8Operand(Register reg); |
| 64 |
| 65 // Returns true if |reg| can be represented as an 16-bit operand |
| 66 // after translation. |
| 67 static bool FitsInReg16Operand(Register reg); |
| 68 |
| 69 // Returns the increment to the register count necessary if the |
| 70 // value indicates the translation window is required. |
| 71 static int RegisterCountAdjustment(int register_count, int parameter_count); |
| 72 |
| 73 private: |
| 74 static const int kTranslationWindowLength = 4; |
| 75 static const int kTranslationWindowLimit = -kMinInt8; |
| 76 static const int kTranslationWindowStart = |
| 77 kTranslationWindowLimit - kTranslationWindowLength + 1; |
| 78 |
| 79 Register TranslateAndMove(Bytecode bytecode, int operand_index, Register reg); |
| 80 Register MakeAddressable(Register reg, OperandType reg_type); |
| 81 static Register Translate(Register reg); |
| 82 |
| 83 RegisterMover* mover() const { return mover_; } |
| 84 |
| 85 // Entity to perform register moves necessary to translate registers |
| 86 // and ensure reachability. |
| 87 RegisterMover* mover_; |
| 88 |
| 89 // Flag to avoid re-entrancy when emitting move bytecodes for |
| 90 // translation. |
| 91 bool emitting_moves_; |
| 92 |
| 93 // State for restoring registers after bytecode. |
| 94 Register window_registers_[kTranslationWindowLength]; |
| 95 int window_registers_count_; |
| 96 }; |
| 97 |
| 98 |
| 99 // Interface for RegisterTranslator helper class that will emit |
| 100 // register move bytecodes at the translator's behest. |
| 101 class RegisterMover { |
| 102 public: |
| 103 virtual ~RegisterMover() {} |
| 104 |
| 105 // Move register |from| to register |to| with no translation. |
| 106 // returns false if either register operand is invalid. Implementations |
| 107 // of this method must be aware that register moves with bad |
| 108 // register values are a security hole. |
| 109 virtual void MoveRegisterUntranslated(Register from, Register to) = 0; |
| 110 |
| 111 // Returns true if the register operand can be moved into the |
| 112 // translation window. |
| 113 virtual bool RegisterOperandIsMovable(Bytecode bytecode, |
| 114 int operand_index) = 0; |
| 115 }; |
| 116 |
| 117 } // namespace interpreter |
| 118 } // namespace internal |
| 119 } // namespace v8 |
| 120 |
| 121 #endif // V8_INTERPRETER_REGISTER_TRANSLATOR_H_ |
OLD | NEW |