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_ARRAY_ACCESSOR_H_ 6 #define V8_INTERPRETER_BYTECODE_ARRAY_ACCESSOR_H_ 7 8 #include <memory> 9 10 #include "src/base/optional.h" 11 #include "src/common/globals.h" 12 #include "src/handles/handles.h" 13 #include "src/interpreter/bytecode-register.h" 14 #include "src/interpreter/bytecodes.h" 15 #include "src/objects/objects.h" 16 #include "src/objects/smi.h" 17 #include "src/runtime/runtime.h" 18 19 namespace v8 { 20 namespace internal { 21 22 class BytecodeArray; 23 24 namespace interpreter { 25 26 class BytecodeArrayAccessor; 27 28 struct V8_EXPORT_PRIVATE JumpTableTargetOffset { 29 int case_value; 30 int target_offset; 31 }; 32 33 class V8_EXPORT_PRIVATE JumpTableTargetOffsets final { 34 public: 35 // Minimal iterator implementation for use in ranged-for. 36 class V8_EXPORT_PRIVATE iterator final { 37 public: 38 iterator(int case_value, int table_offset, int table_end, 39 const BytecodeArrayAccessor* accessor); 40 41 JumpTableTargetOffset operator*(); 42 iterator& operator++(); 43 bool operator!=(const iterator& other); 44 45 private: 46 void UpdateAndAdvanceToValid(); 47 48 const BytecodeArrayAccessor* accessor_; 49 Smi current_; 50 int index_; 51 int table_offset_; 52 int table_end_; 53 }; 54 55 JumpTableTargetOffsets(const BytecodeArrayAccessor* accessor, int table_start, 56 int table_size, int case_value_base); 57 58 iterator begin() const; 59 iterator end() const; 60 61 int size() const; 62 63 private: 64 const BytecodeArrayAccessor* accessor_; 65 int table_start_; 66 int table_size_; 67 int case_value_base_; 68 }; 69 70 class V8_EXPORT_PRIVATE AbstractBytecodeArray { 71 public: 72 virtual int length() const = 0; 73 virtual int parameter_count() const = 0; 74 virtual uint8_t get(int index) const = 0; 75 virtual void set(int index, uint8_t value) = 0; 76 virtual Address GetFirstBytecodeAddress() const = 0; 77 78 virtual Handle<Object> GetConstantAtIndex(int index, 79 Isolate* isolate) const = 0; 80 virtual bool IsConstantAtIndexSmi(int index) const = 0; 81 virtual Smi GetConstantAtIndexAsSmi(int index) const = 0; 82 83 virtual ~AbstractBytecodeArray() = default; 84 }; 85 86 class V8_EXPORT_PRIVATE BytecodeArrayAccessor { 87 public: 88 BytecodeArrayAccessor(std::unique_ptr<AbstractBytecodeArray> bytecode_array, 89 int initial_offset); 90 91 BytecodeArrayAccessor(Handle<BytecodeArray> bytecode_array, 92 int initial_offset); 93 94 BytecodeArrayAccessor(const BytecodeArrayAccessor&) = delete; 95 BytecodeArrayAccessor& operator=(const BytecodeArrayAccessor&) = delete; 96 97 void SetOffset(int offset); 98 99 void ApplyDebugBreak(); 100 101 Bytecode current_bytecode() const; 102 int current_bytecode_size() const; current_offset()103 int current_offset() const { return bytecode_offset_; } current_operand_scale()104 OperandScale current_operand_scale() const { return operand_scale_; } current_prefix_offset()105 int current_prefix_offset() const { return prefix_offset_; } bytecode_array()106 AbstractBytecodeArray* bytecode_array() const { 107 return bytecode_array_.get(); 108 } 109 110 uint32_t GetFlagOperand(int operand_index) const; 111 uint32_t GetUnsignedImmediateOperand(int operand_index) const; 112 int32_t GetImmediateOperand(int operand_index) const; 113 uint32_t GetIndexOperand(int operand_index) const; 114 FeedbackSlot GetSlotOperand(int operand_index) const; 115 Register GetReceiver() const; 116 Register GetParameter(int parameter_index) const; 117 uint32_t GetRegisterCountOperand(int operand_index) const; 118 Register GetRegisterOperand(int operand_index) const; 119 int GetRegisterOperandRange(int operand_index) const; 120 Runtime::FunctionId GetRuntimeIdOperand(int operand_index) const; 121 Runtime::FunctionId GetIntrinsicIdOperand(int operand_index) const; 122 uint32_t GetNativeContextIndexOperand(int operand_index) const; 123 Handle<Object> GetConstantAtIndex(int offset, Isolate* isolate) const; 124 bool IsConstantAtIndexSmi(int offset) const; 125 Smi GetConstantAtIndexAsSmi(int offset) const; 126 Handle<Object> GetConstantForIndexOperand(int operand_index, 127 Isolate* isolate) const; 128 129 // Returns the relative offset of the branch target at the current bytecode. 130 // It is an error to call this method if the bytecode is not for a jump or 131 // conditional jump. Returns a negative offset for backward jumps. 132 int GetRelativeJumpTargetOffset() const; 133 // Returns the absolute offset of the branch target at the current bytecode. 134 // It is an error to call this method if the bytecode is not for a jump or 135 // conditional jump. 136 int GetJumpTargetOffset() const; 137 // Returns an iterator over the absolute offsets of the targets of the current 138 // switch bytecode's jump table. It is an error to call this method if the 139 // bytecode is not a switch. 140 JumpTableTargetOffsets GetJumpTableTargetOffsets() const; 141 142 // Returns the absolute offset of the bytecode at the given relative offset 143 // from the current bytecode. 144 int GetAbsoluteOffset(int relative_offset) const; 145 146 bool OffsetWithinBytecode(int offset) const; 147 148 std::ostream& PrintTo(std::ostream& os) const; 149 150 private: 151 bool OffsetInBounds() const; 152 153 uint32_t GetUnsignedOperand(int operand_index, 154 OperandType operand_type) const; 155 int32_t GetSignedOperand(int operand_index, OperandType operand_type) const; 156 157 void UpdateOperandScale(); 158 159 std::unique_ptr<AbstractBytecodeArray> bytecode_array_; 160 int bytecode_offset_; 161 OperandScale operand_scale_; 162 int prefix_offset_; 163 }; 164 165 } // namespace interpreter 166 } // namespace internal 167 } // namespace v8 168 169 #endif // V8_INTERPRETER_BYTECODE_ARRAY_ACCESSOR_H_ 170