• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ITERATOR_H_
6 #define V8_INTERPRETER_BYTECODE_ARRAY_ITERATOR_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 BytecodeArrayIterator;
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 BytecodeArrayIterator* iterator);
40 
41     JumpTableTargetOffset operator*();
42     iterator& operator++();
43     bool operator!=(const iterator& other);
44 
45    private:
46     void UpdateAndAdvanceToValid();
47 
48     const BytecodeArrayIterator* iterator_;
49     Smi current_;
50     int index_;
51     int table_offset_;
52     int table_end_;
53   };
54 
55   JumpTableTargetOffsets(const BytecodeArrayIterator* iterator, 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 BytecodeArrayIterator* iterator_;
65   int table_start_;
66   int table_size_;
67   int case_value_base_;
68 };
69 
70 class V8_EXPORT_PRIVATE BytecodeArrayIterator {
71  public:
72   BytecodeArrayIterator(Handle<BytecodeArray> bytecode_array,
73                         int initial_offset = 0);
74   ~BytecodeArrayIterator();
75 
76   BytecodeArrayIterator(const BytecodeArrayIterator&) = delete;
77   BytecodeArrayIterator& operator=(const BytecodeArrayIterator&) = delete;
78 
Advance()79   inline void Advance() {
80     cursor_ += current_bytecode_size_without_prefix();
81     UpdateOperandScale();
82   }
83   void SetOffset(int offset);
Reset()84   void Reset() { SetOffset(0); }
85 
86   void ApplyDebugBreak();
87 
current_bytecode()88   inline Bytecode current_bytecode() const {
89     DCHECK(!done());
90     uint8_t current_byte = *cursor_;
91     Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
92     DCHECK(!Bytecodes::IsPrefixScalingBytecode(current_bytecode));
93     return current_bytecode;
94   }
current_bytecode_size()95   int current_bytecode_size() const {
96     return prefix_size_ + current_bytecode_size_without_prefix();
97   }
current_bytecode_size_without_prefix()98   int current_bytecode_size_without_prefix() const {
99     return Bytecodes::Size(current_bytecode(), current_operand_scale());
100   }
current_offset()101   int current_offset() const {
102     return static_cast<int>(cursor_ - start_ - prefix_size_);
103   }
next_offset()104   int next_offset() const { return current_offset() + current_bytecode_size(); }
current_operand_scale()105   OperandScale current_operand_scale() const { return operand_scale_; }
bytecode_array()106   Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
107 
108   uint32_t GetFlagOperand(int operand_index) const;
109   uint32_t GetUnsignedImmediateOperand(int operand_index) const;
110   int32_t GetImmediateOperand(int operand_index) const;
111   uint32_t GetIndexOperand(int operand_index) const;
112   FeedbackSlot GetSlotOperand(int operand_index) const;
113   Register GetReceiver() const;
114   Register GetParameter(int parameter_index) const;
115   uint32_t GetRegisterCountOperand(int operand_index) const;
116   Register GetRegisterOperand(int operand_index) const;
117   std::pair<Register, Register> GetRegisterPairOperand(int operand_index) const;
118   RegisterList GetRegisterListOperand(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   template <typename IsolateT>
124   Handle<Object> GetConstantAtIndex(int offset, IsolateT* isolate) const;
125   bool IsConstantAtIndexSmi(int offset) const;
126   Smi GetConstantAtIndexAsSmi(int offset) const;
127   template <typename IsolateT>
128   Handle<Object> GetConstantForIndexOperand(int operand_index,
129                                             IsolateT* isolate) const;
130 
131   // Returns the relative offset of the branch target at the current bytecode.
132   // It is an error to call this method if the bytecode is not for a jump or
133   // conditional jump. Returns a negative offset for backward jumps.
134   int GetRelativeJumpTargetOffset() const;
135   // Returns the absolute offset of the branch target at the current bytecode.
136   // It is an error to call this method if the bytecode is not for a jump or
137   // conditional jump.
138   int GetJumpTargetOffset() const;
139   // Returns an iterator over the absolute offsets of the targets of the current
140   // switch bytecode's jump table. It is an error to call this method if the
141   // bytecode is not a switch.
142   JumpTableTargetOffsets GetJumpTableTargetOffsets() const;
143 
144   // Returns the absolute offset of the bytecode at the given relative offset
145   // from the current bytecode.
146   int GetAbsoluteOffset(int relative_offset) const;
147 
148   std::ostream& PrintTo(std::ostream& os) const;
149 
UpdatePointersCallback(void * iterator)150   static void UpdatePointersCallback(void* iterator) {
151     reinterpret_cast<BytecodeArrayIterator*>(iterator)->UpdatePointers();
152   }
153 
154   void UpdatePointers();
155 
done()156   inline bool done() const { return cursor_ >= end_; }
157 
158  private:
159   uint32_t GetUnsignedOperand(int operand_index,
160                               OperandType operand_type) const;
161   int32_t GetSignedOperand(int operand_index, OperandType operand_type) const;
162 
UpdateOperandScale()163   inline void UpdateOperandScale() {
164     if (done()) return;
165     uint8_t current_byte = *cursor_;
166     Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
167     if (Bytecodes::IsPrefixScalingBytecode(current_bytecode)) {
168       operand_scale_ =
169           Bytecodes::PrefixBytecodeToOperandScale(current_bytecode);
170       ++cursor_;
171       prefix_size_ = 1;
172     } else {
173       operand_scale_ = OperandScale::kSingle;
174       prefix_size_ = 0;
175     }
176   }
177 
178   Handle<BytecodeArray> bytecode_array_;
179   uint8_t* start_;
180   uint8_t* end_;
181   // The cursor always points to the active bytecode. If there's a prefix, the
182   // prefix is at (cursor - 1).
183   uint8_t* cursor_;
184   OperandScale operand_scale_;
185   int prefix_size_;
186   LocalHeap* const local_heap_;
187 };
188 
189 }  // namespace interpreter
190 }  // namespace internal
191 }  // namespace v8
192 
193 #endif  // V8_INTERPRETER_BYTECODE_ARRAY_ITERATOR_H_
194