11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_ 61cb0ef41Sopenharmony_ci#define V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h" 91cb0ef41Sopenharmony_ci#include "src/common/globals.h" 101cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-register-allocator.h" 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_cinamespace v8 { 131cb0ef41Sopenharmony_cinamespace internal { 141cb0ef41Sopenharmony_cinamespace interpreter { 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci// An optimization stage for eliminating unnecessary transfers between 171cb0ef41Sopenharmony_ci// registers. The bytecode generator uses temporary registers 181cb0ef41Sopenharmony_ci// liberally for correctness and convenience and this stage removes 191cb0ef41Sopenharmony_ci// transfers that are not required and preserves correctness. 201cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final 211cb0ef41Sopenharmony_ci : public NON_EXPORTED_BASE(BytecodeRegisterAllocator::Observer), 221cb0ef41Sopenharmony_ci public NON_EXPORTED_BASE(ZoneObject) { 231cb0ef41Sopenharmony_ci public: 241cb0ef41Sopenharmony_ci class BytecodeWriter { 251cb0ef41Sopenharmony_ci public: 261cb0ef41Sopenharmony_ci BytecodeWriter() = default; 271cb0ef41Sopenharmony_ci virtual ~BytecodeWriter() = default; 281cb0ef41Sopenharmony_ci BytecodeWriter(const BytecodeWriter&) = delete; 291cb0ef41Sopenharmony_ci BytecodeWriter& operator=(const BytecodeWriter&) = delete; 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci // Called to emit a register transfer bytecode. 321cb0ef41Sopenharmony_ci virtual void EmitLdar(Register input) = 0; 331cb0ef41Sopenharmony_ci virtual void EmitStar(Register output) = 0; 341cb0ef41Sopenharmony_ci virtual void EmitMov(Register input, Register output) = 0; 351cb0ef41Sopenharmony_ci }; 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci BytecodeRegisterOptimizer(Zone* zone, 381cb0ef41Sopenharmony_ci BytecodeRegisterAllocator* register_allocator, 391cb0ef41Sopenharmony_ci int fixed_registers_count, int parameter_count, 401cb0ef41Sopenharmony_ci BytecodeWriter* bytecode_writer); 411cb0ef41Sopenharmony_ci ~BytecodeRegisterOptimizer() override = default; 421cb0ef41Sopenharmony_ci BytecodeRegisterOptimizer(const BytecodeRegisterOptimizer&) = delete; 431cb0ef41Sopenharmony_ci BytecodeRegisterOptimizer& operator=(const BytecodeRegisterOptimizer&) = 441cb0ef41Sopenharmony_ci delete; 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci // Perform explicit register transfer operations. 471cb0ef41Sopenharmony_ci void DoLdar(Register input) { 481cb0ef41Sopenharmony_ci // TODO(rmcilroy): Avoid treating accumulator loads as clobbering the 491cb0ef41Sopenharmony_ci // accumulator until the value is actually materialized in the accumulator. 501cb0ef41Sopenharmony_ci RegisterInfo* input_info = GetRegisterInfo(input); 511cb0ef41Sopenharmony_ci RegisterTransfer(input_info, accumulator_info_); 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci void DoStar(Register output) { 541cb0ef41Sopenharmony_ci RegisterInfo* output_info = GetRegisterInfo(output); 551cb0ef41Sopenharmony_ci RegisterTransfer(accumulator_info_, output_info); 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci void DoMov(Register input, Register output) { 581cb0ef41Sopenharmony_ci RegisterInfo* input_info = GetRegisterInfo(input); 591cb0ef41Sopenharmony_ci RegisterInfo* output_info = GetRegisterInfo(output); 601cb0ef41Sopenharmony_ci RegisterTransfer(input_info, output_info); 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci // Materialize all live registers and flush equivalence sets. 641cb0ef41Sopenharmony_ci void Flush(); 651cb0ef41Sopenharmony_ci bool EnsureAllRegistersAreFlushed() const; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci // Prepares for |bytecode|. 681cb0ef41Sopenharmony_ci template <Bytecode bytecode, ImplicitRegisterUse implicit_register_use> 691cb0ef41Sopenharmony_ci V8_INLINE void PrepareForBytecode() { 701cb0ef41Sopenharmony_ci if (Bytecodes::IsJump(bytecode) || Bytecodes::IsSwitch(bytecode) || 711cb0ef41Sopenharmony_ci bytecode == Bytecode::kDebugger || 721cb0ef41Sopenharmony_ci bytecode == Bytecode::kSuspendGenerator || 731cb0ef41Sopenharmony_ci bytecode == Bytecode::kResumeGenerator) { 741cb0ef41Sopenharmony_ci // All state must be flushed before emitting 751cb0ef41Sopenharmony_ci // - a jump bytecode (as the register equivalents at the jump target 761cb0ef41Sopenharmony_ci // aren't known) 771cb0ef41Sopenharmony_ci // - a switch bytecode (as the register equivalents at the switch targets 781cb0ef41Sopenharmony_ci // aren't known) 791cb0ef41Sopenharmony_ci // - a call to the debugger (as it can manipulate locals and parameters), 801cb0ef41Sopenharmony_ci // - a generator suspend (as this involves saving all registers). 811cb0ef41Sopenharmony_ci // - a generator register restore. 821cb0ef41Sopenharmony_ci Flush(); 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci // Materialize the accumulator if it is read by the bytecode. The 861cb0ef41Sopenharmony_ci // accumulator is special and no other register can be materialized 871cb0ef41Sopenharmony_ci // in it's place. 881cb0ef41Sopenharmony_ci if (BytecodeOperands::ReadsAccumulator(implicit_register_use)) { 891cb0ef41Sopenharmony_ci Materialize(accumulator_info_); 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci // Materialize an equivalent to the accumulator if it will be 931cb0ef41Sopenharmony_ci // clobbered when the bytecode is dispatched. 941cb0ef41Sopenharmony_ci if (BytecodeOperands::WritesAccumulator(implicit_register_use)) { 951cb0ef41Sopenharmony_ci PrepareOutputRegister(accumulator_); 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci // Prepares |reg| for being used as an output operand. 1001cb0ef41Sopenharmony_ci void PrepareOutputRegister(Register reg); 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci // Prepares registers in |reg_list| for being used as an output operand. 1031cb0ef41Sopenharmony_ci void PrepareOutputRegisterList(RegisterList reg_list); 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci // Returns an equivalent register to |reg| to be used as an input operand. 1061cb0ef41Sopenharmony_ci Register GetInputRegister(Register reg); 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci // Returns an equivalent register list to |reg_list| to be used as an input 1091cb0ef41Sopenharmony_ci // operand. 1101cb0ef41Sopenharmony_ci RegisterList GetInputRegisterList(RegisterList reg_list); 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci int maxiumum_register_index() const { return max_register_index_; } 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci private: 1151cb0ef41Sopenharmony_ci static const uint32_t kInvalidEquivalenceId; 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci class RegisterInfo; 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci // BytecodeRegisterAllocator::Observer interface. 1201cb0ef41Sopenharmony_ci void RegisterAllocateEvent(Register reg) override; 1211cb0ef41Sopenharmony_ci void RegisterListAllocateEvent(RegisterList reg_list) override; 1221cb0ef41Sopenharmony_ci void RegisterListFreeEvent(RegisterList reg) override; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci // Update internal state for register transfer from |input| to |output| 1251cb0ef41Sopenharmony_ci void RegisterTransfer(RegisterInfo* input, RegisterInfo* output); 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci // Emit a register transfer bytecode from |input| to |output|. 1281cb0ef41Sopenharmony_ci void OutputRegisterTransfer(RegisterInfo* input, RegisterInfo* output); 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci void CreateMaterializedEquivalent(RegisterInfo* info); 1311cb0ef41Sopenharmony_ci RegisterInfo* GetMaterializedEquivalent(RegisterInfo* info); 1321cb0ef41Sopenharmony_ci RegisterInfo* GetMaterializedEquivalentNotAccumulator(RegisterInfo* info); 1331cb0ef41Sopenharmony_ci void Materialize(RegisterInfo* info); 1341cb0ef41Sopenharmony_ci void AddToEquivalenceSet(RegisterInfo* set_member, 1351cb0ef41Sopenharmony_ci RegisterInfo* non_set_member); 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci void PushToRegistersNeedingFlush(RegisterInfo* reg); 1381cb0ef41Sopenharmony_ci // Methods for finding and creating metadata for each register. 1391cb0ef41Sopenharmony_ci RegisterInfo* GetRegisterInfo(Register reg) { 1401cb0ef41Sopenharmony_ci size_t index = GetRegisterInfoTableIndex(reg); 1411cb0ef41Sopenharmony_ci DCHECK_LT(index, register_info_table_.size()); 1421cb0ef41Sopenharmony_ci return register_info_table_[index]; 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci RegisterInfo* GetOrCreateRegisterInfo(Register reg) { 1451cb0ef41Sopenharmony_ci size_t index = GetRegisterInfoTableIndex(reg); 1461cb0ef41Sopenharmony_ci return index < register_info_table_.size() ? register_info_table_[index] 1471cb0ef41Sopenharmony_ci : NewRegisterInfo(reg); 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci RegisterInfo* NewRegisterInfo(Register reg) { 1501cb0ef41Sopenharmony_ci size_t index = GetRegisterInfoTableIndex(reg); 1511cb0ef41Sopenharmony_ci DCHECK_GE(index, register_info_table_.size()); 1521cb0ef41Sopenharmony_ci GrowRegisterMap(reg); 1531cb0ef41Sopenharmony_ci return register_info_table_[index]; 1541cb0ef41Sopenharmony_ci } 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci void GrowRegisterMap(Register reg); 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci bool RegisterIsTemporary(Register reg) const { 1591cb0ef41Sopenharmony_ci return reg >= temporary_base_; 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci bool RegisterIsObservable(Register reg) const { 1631cb0ef41Sopenharmony_ci return reg != accumulator_ && !RegisterIsTemporary(reg); 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci static Register OperandToRegister(uint32_t operand) { 1671cb0ef41Sopenharmony_ci return Register::FromOperand(static_cast<int32_t>(operand)); 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci size_t GetRegisterInfoTableIndex(Register reg) const { 1711cb0ef41Sopenharmony_ci return static_cast<size_t>(reg.index() + register_info_table_offset_); 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci Register RegisterFromRegisterInfoTableIndex(size_t index) const { 1751cb0ef41Sopenharmony_ci return Register(static_cast<int>(index) - register_info_table_offset_); 1761cb0ef41Sopenharmony_ci } 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci uint32_t NextEquivalenceId() { 1791cb0ef41Sopenharmony_ci equivalence_id_++; 1801cb0ef41Sopenharmony_ci // TODO(rmcilroy): use the same type for these and remove static_cast. 1811cb0ef41Sopenharmony_ci CHECK_NE(static_cast<size_t>(equivalence_id_), kInvalidEquivalenceId); 1821cb0ef41Sopenharmony_ci return equivalence_id_; 1831cb0ef41Sopenharmony_ci } 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci void AllocateRegister(RegisterInfo* info); 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci Zone* zone() { return zone_; } 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci const Register accumulator_; 1901cb0ef41Sopenharmony_ci RegisterInfo* accumulator_info_; 1911cb0ef41Sopenharmony_ci const Register temporary_base_; 1921cb0ef41Sopenharmony_ci int max_register_index_; 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci // Direct mapping to register info. 1951cb0ef41Sopenharmony_ci ZoneVector<RegisterInfo*> register_info_table_; 1961cb0ef41Sopenharmony_ci int register_info_table_offset_; 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci ZoneDeque<RegisterInfo*> registers_needing_flushed_; 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci // Counter for equivalence sets identifiers. 2011cb0ef41Sopenharmony_ci int equivalence_id_; 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci BytecodeWriter* bytecode_writer_; 2041cb0ef41Sopenharmony_ci bool flush_required_; 2051cb0ef41Sopenharmony_ci Zone* zone_; 2061cb0ef41Sopenharmony_ci}; 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci} // namespace interpreter 2091cb0ef41Sopenharmony_ci} // namespace internal 2101cb0ef41Sopenharmony_ci} // namespace v8 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci#endif // V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_ 213