// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_INTERPRETER_BYTECODE_ARRAY_ACCESSOR_H_ #define V8_INTERPRETER_BYTECODE_ARRAY_ACCESSOR_H_ #include <memory> #include "src/base/optional.h" #include "src/common/globals.h" #include "src/handles/handles.h" #include "src/interpreter/bytecode-register.h" #include "src/interpreter/bytecodes.h" #include "src/objects/objects.h" #include "src/objects/smi.h" #include "src/runtime/runtime.h" namespace v8 { namespace internal { class BytecodeArray; namespace interpreter { class BytecodeArrayAccessor; struct V8_EXPORT_PRIVATE JumpTableTargetOffset { int case_value; int target_offset; }; class V8_EXPORT_PRIVATE JumpTableTargetOffsets final { public: // Minimal iterator implementation for use in ranged-for. class V8_EXPORT_PRIVATE iterator final { public: iterator(int case_value, int table_offset, int table_end, const BytecodeArrayAccessor* accessor); JumpTableTargetOffset operator*(); iterator& operator++(); bool operator!=(const iterator& other); private: void UpdateAndAdvanceToValid(); const BytecodeArrayAccessor* accessor_; Smi current_; int index_; int table_offset_; int table_end_; }; JumpTableTargetOffsets(const BytecodeArrayAccessor* accessor, int table_start, int table_size, int case_value_base); iterator begin() const; iterator end() const; int size() const; private: const BytecodeArrayAccessor* accessor_; int table_start_; int table_size_; int case_value_base_; }; class V8_EXPORT_PRIVATE AbstractBytecodeArray { public: virtual int length() const = 0; virtual int parameter_count() const = 0; virtual uint8_t get(int index) const = 0; virtual void set(int index, uint8_t value) = 0; virtual Address GetFirstBytecodeAddress() const = 0; virtual Handle<Object> GetConstantAtIndex(int index, Isolate* isolate) const = 0; virtual bool IsConstantAtIndexSmi(int index) const = 0; virtual Smi GetConstantAtIndexAsSmi(int index) const = 0; virtual ~AbstractBytecodeArray() = default; }; class V8_EXPORT_PRIVATE BytecodeArrayAccessor { public: BytecodeArrayAccessor(std::unique_ptr<AbstractBytecodeArray> bytecode_array, int initial_offset); BytecodeArrayAccessor(Handle<BytecodeArray> bytecode_array, int initial_offset); BytecodeArrayAccessor(const BytecodeArrayAccessor&) = delete; BytecodeArrayAccessor& operator=(const BytecodeArrayAccessor&) = delete; void SetOffset(int offset); void ApplyDebugBreak(); Bytecode current_bytecode() const; int current_bytecode_size() const; int current_offset() const { return bytecode_offset_; } OperandScale current_operand_scale() const { return operand_scale_; } int current_prefix_offset() const { return prefix_offset_; } AbstractBytecodeArray* bytecode_array() const { return bytecode_array_.get(); } uint32_t GetFlagOperand(int operand_index) const; uint32_t GetUnsignedImmediateOperand(int operand_index) const; int32_t GetImmediateOperand(int operand_index) const; uint32_t GetIndexOperand(int operand_index) const; FeedbackSlot GetSlotOperand(int operand_index) const; Register GetReceiver() const; Register GetParameter(int parameter_index) const; uint32_t GetRegisterCountOperand(int operand_index) const; Register GetRegisterOperand(int operand_index) const; int GetRegisterOperandRange(int operand_index) const; Runtime::FunctionId GetRuntimeIdOperand(int operand_index) const; Runtime::FunctionId GetIntrinsicIdOperand(int operand_index) const; uint32_t GetNativeContextIndexOperand(int operand_index) const; Handle<Object> GetConstantAtIndex(int offset, Isolate* isolate) const; bool IsConstantAtIndexSmi(int offset) const; Smi GetConstantAtIndexAsSmi(int offset) const; Handle<Object> GetConstantForIndexOperand(int operand_index, Isolate* isolate) const; // Returns the relative offset of the branch target at the current bytecode. // It is an error to call this method if the bytecode is not for a jump or // conditional jump. Returns a negative offset for backward jumps. int GetRelativeJumpTargetOffset() const; // Returns the absolute offset of the branch target at the current bytecode. // It is an error to call this method if the bytecode is not for a jump or // conditional jump. int GetJumpTargetOffset() const; // Returns an iterator over the absolute offsets of the targets of the current // switch bytecode's jump table. It is an error to call this method if the // bytecode is not a switch. JumpTableTargetOffsets GetJumpTableTargetOffsets() const; // Returns the absolute offset of the bytecode at the given relative offset // from the current bytecode. int GetAbsoluteOffset(int relative_offset) const; bool OffsetWithinBytecode(int offset) const; std::ostream& PrintTo(std::ostream& os) const; private: bool OffsetInBounds() const; uint32_t GetUnsignedOperand(int operand_index, OperandType operand_type) const; int32_t GetSignedOperand(int operand_index, OperandType operand_type) const; void UpdateOperandScale(); std::unique_ptr<AbstractBytecodeArray> bytecode_array_; int bytecode_offset_; OperandScale operand_scale_; int prefix_offset_; }; } // namespace interpreter } // namespace internal } // namespace v8 #endif // V8_INTERPRETER_BYTECODE_ARRAY_ACCESSOR_H_