LCOV - code coverage report
Current view: top level - src/interpreter - bytecode-register-optimizer.h (source / functions) Hit Total Coverage
Test: app.info Lines: 30 32 93.8 %
Date: 2017-04-26 Functions: 5 9 55.6 %

          Line data    Source code
       1             : // Copyright 2016 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_BYTECODE_REGISTER_OPTIMIZER_H_
       6             : #define V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_
       7             : 
       8             : #include "src/base/compiler-specific.h"
       9             : #include "src/globals.h"
      10             : #include "src/interpreter/bytecode-register-allocator.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : namespace interpreter {
      15             : 
      16             : // An optimization stage for eliminating unnecessary transfers between
      17             : // registers. The bytecode generator uses temporary registers
      18             : // liberally for correctness and convenience and this stage removes
      19             : // transfers that are not required and preserves correctness.
      20             : class V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final
      21             :     : public NON_EXPORTED_BASE(BytecodeRegisterAllocator::Observer),
      22             :       public NON_EXPORTED_BASE(ZoneObject) {
      23             :  public:
      24             :   class BytecodeWriter {
      25             :    public:
      26     2104165 :     BytecodeWriter() {}
      27           0 :     virtual ~BytecodeWriter() {}
      28             : 
      29             :     // Called to emit a register transfer bytecode.
      30             :     virtual void EmitLdar(Register input) = 0;
      31             :     virtual void EmitStar(Register output) = 0;
      32             :     virtual void EmitMov(Register input, Register output) = 0;
      33             : 
      34             :    private:
      35             :     DISALLOW_COPY_AND_ASSIGN(BytecodeWriter);
      36             :   };
      37             : 
      38             :   BytecodeRegisterOptimizer(Zone* zone,
      39             :                             BytecodeRegisterAllocator* register_allocator,
      40             :                             int fixed_registers_count, int parameter_count,
      41             :                             BytecodeWriter* bytecode_writer);
      42           0 :   virtual ~BytecodeRegisterOptimizer() {}
      43             : 
      44             :   // Perform explicit register transfer operations.
      45     8909421 :   void DoLdar(Register input) {
      46             :     // TODO(rmcilroy): Avoid treating accumulator loads as clobbering the
      47             :     // accumulator until the value is actually materialized in the accumulator.
      48             :     RegisterInfo* input_info = GetRegisterInfo(input);
      49     8909421 :     RegisterTransfer(input_info, accumulator_info_);
      50     8909425 :   }
      51    24505570 :   void DoStar(Register output) {
      52             :     RegisterInfo* output_info = GetRegisterInfo(output);
      53    24505570 :     RegisterTransfer(accumulator_info_, output_info);
      54    24505574 :   }
      55      831841 :   void DoMov(Register input, Register output) {
      56             :     RegisterInfo* input_info = GetRegisterInfo(input);
      57             :     RegisterInfo* output_info = GetRegisterInfo(output);
      58      831841 :     RegisterTransfer(input_info, output_info);
      59      831841 :   }
      60             : 
      61             :   // Materialize all live registers and flush equivalence sets.
      62             :   void Flush();
      63             : 
      64             :   // Prepares for |bytecode|.
      65             :   template <Bytecode bytecode, AccumulatorUse accumulator_use>
      66             :   INLINE(void PrepareForBytecode()) {
      67    47514620 :     if (Bytecodes::IsJump(bytecode) || bytecode == Bytecode::kDebugger ||
      68             :         bytecode == Bytecode::kSuspendGenerator) {
      69             :       // All state must be flushed before emitting
      70             :       // - a jump bytecode (as the register equivalents at the jump target
      71             :       // aren't
      72             :       //   known.
      73             :       // - a call to the debugger (as it can manipulate locals and parameters),
      74             :       // - a generator suspend (as this involves saving all registers).
      75     3112898 :       Flush();
      76             :     }
      77             : 
      78             :     // Materialize the accumulator if it is read by the bytecode. The
      79             :     // accumulator is special and no other register can be materialized
      80             :     // in it's place.
      81    47544751 :     if (BytecodeOperands::ReadsAccumulator(accumulator_use)) {
      82    14678689 :       Materialize(accumulator_info_);
      83             :     }
      84             : 
      85             :     // Materialize an equivalent to the accumulator if it will be
      86             :     // clobbered when the bytecode is dispatched.
      87    47544756 :     if (BytecodeOperands::WritesAccumulator(accumulator_use)) {
      88    32705798 :       PrepareOutputRegister(accumulator_);
      89             :     }
      90             :   }
      91             : 
      92             :   // Prepares |reg| for being used as an output operand.
      93             :   void PrepareOutputRegister(Register reg);
      94             : 
      95             :   // Prepares registers in |reg_list| for being used as an output operand.
      96             :   void PrepareOutputRegisterList(RegisterList reg_list);
      97             : 
      98             :   // Returns an equivalent register to |reg| to be used as an input operand.
      99             :   Register GetInputRegister(Register reg);
     100             : 
     101             :   // Returns an equivalent register list to |reg_list| to be used as an input
     102             :   // operand.
     103             :   RegisterList GetInputRegisterList(RegisterList reg_list);
     104             : 
     105             :   int maxiumum_register_index() const { return max_register_index_; }
     106             : 
     107             :  private:
     108             :   static const uint32_t kInvalidEquivalenceId;
     109             : 
     110             :   class RegisterInfo;
     111             : 
     112             :   // BytecodeRegisterAllocator::Observer interface.
     113             :   void RegisterAllocateEvent(Register reg) override;
     114             :   void RegisterListAllocateEvent(RegisterList reg_list) override;
     115             :   void RegisterListFreeEvent(RegisterList reg) override;
     116             : 
     117             :   // Update internal state for register transfer from |input| to |output|
     118             :   void RegisterTransfer(RegisterInfo* input, RegisterInfo* output);
     119             : 
     120             :   // Emit a register transfer bytecode from |input| to |output|.
     121             :   void OutputRegisterTransfer(RegisterInfo* input, RegisterInfo* output);
     122             : 
     123             :   void CreateMaterializedEquivalent(RegisterInfo* info);
     124             :   RegisterInfo* GetMaterializedEquivalent(RegisterInfo* info);
     125             :   RegisterInfo* GetMaterializedEquivalentNotAccumulator(RegisterInfo* info);
     126             :   void Materialize(RegisterInfo* info);
     127             :   void AddToEquivalenceSet(RegisterInfo* set_member,
     128             :                            RegisterInfo* non_set_member);
     129             : 
     130             :   // Methods for finding and creating metadata for each register.
     131   115809407 :   RegisterInfo* GetRegisterInfo(Register reg) {
     132             :     size_t index = GetRegisterInfoTableIndex(reg);
     133             :     DCHECK_LT(index, register_info_table_.size());
     134   230346481 :     return register_info_table_[index];
     135             :   }
     136    19437947 :   RegisterInfo* GetOrCreateRegisterInfo(Register reg) {
     137             :     size_t index = GetRegisterInfoTableIndex(reg);
     138    19437947 :     return index < register_info_table_.size() ? register_info_table_[index]
     139    52126383 :                                                : NewRegisterInfo(reg);
     140             :   }
     141             :   RegisterInfo* NewRegisterInfo(Register reg) {
     142             :     size_t index = GetRegisterInfoTableIndex(reg);
     143             :     DCHECK_GE(index, register_info_table_.size());
     144     6187467 :     GrowRegisterMap(reg);
     145    12374952 :     return register_info_table_[index];
     146             :   }
     147             : 
     148             :   void GrowRegisterMap(Register reg);
     149             : 
     150             :   bool RegisterIsTemporary(Register reg) const {
     151             :     return reg >= temporary_base_;
     152             :   }
     153             : 
     154             :   bool RegisterIsObservable(Register reg) const {
     155   103572366 :     return reg != accumulator_ && !RegisterIsTemporary(reg);
     156             :   }
     157             : 
     158             :   static Register OperandToRegister(uint32_t operand) {
     159             :     return Register::FromOperand(static_cast<int32_t>(operand));
     160             :   }
     161             : 
     162             :   size_t GetRegisterInfoTableIndex(Register reg) const {
     163   142679955 :     return static_cast<size_t>(reg.index() + register_info_table_offset_);
     164             :   }
     165             : 
     166             :   Register RegisterFromRegisterInfoTableIndex(size_t index) const {
     167    29585254 :     return Register(static_cast<int>(index) - register_info_table_offset_);
     168             :   }
     169             : 
     170    69139370 :   uint32_t NextEquivalenceId() {
     171    69139370 :     equivalence_id_++;
     172             :     // TODO(rmcilroy): use the same type for these and remove static_cast.
     173    69139370 :     CHECK_NE(static_cast<size_t>(equivalence_id_), kInvalidEquivalenceId);
     174    69139370 :     return equivalence_id_;
     175             :   }
     176             : 
     177             :   Zone* zone() { return zone_; }
     178             : 
     179             :   const Register accumulator_;
     180             :   RegisterInfo* accumulator_info_;
     181             :   const Register temporary_base_;
     182             :   int max_register_index_;
     183             : 
     184             :   // Direct mapping to register info.
     185             :   ZoneVector<RegisterInfo*> register_info_table_;
     186             :   int register_info_table_offset_;
     187             : 
     188             :   // Counter for equivalence sets identifiers.
     189             :   int equivalence_id_;
     190             : 
     191             :   BytecodeWriter* bytecode_writer_;
     192             :   bool flush_required_;
     193             :   Zone* zone_;
     194             : 
     195             :   DISALLOW_COPY_AND_ASSIGN(BytecodeRegisterOptimizer);
     196             : };
     197             : 
     198             : }  // namespace interpreter
     199             : }  // namespace internal
     200             : }  // namespace v8
     201             : 
     202             : #endif  // V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_

Generated by: LCOV version 1.10