blob: afa8d4aad3e827d0ad0c892206cfa3c92b1d5cfb [file] [log] [blame]
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_RUNTIME_DEX_INSTRUCTION_ITERATOR_H_
18#define ART_RUNTIME_DEX_INSTRUCTION_ITERATOR_H_
19
20#include <iterator>
21
22#include "dex_instruction.h"
23#include "base/logging.h"
24
25namespace art {
26
Mathieu Chartieraf7c9022017-10-27 09:42:46 -070027// Base helper class to prevent duplicated comparators.
28class DexInstructionIteratorBase : public std::iterator<std::forward_iterator_tag, Instruction> {
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -070029 public:
Vladimir Markod7559b72017-09-28 13:50:37 +010030 using value_type = std::iterator<std::forward_iterator_tag, Instruction>::value_type;
31 using difference_type = std::iterator<std::forward_iterator_tag, value_type>::difference_type;
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -070032
Mathieu Chartieraf7c9022017-10-27 09:42:46 -070033 DexInstructionIteratorBase() = default;
34 explicit DexInstructionIteratorBase(const value_type* inst) : inst_(inst) {}
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -070035
Mathieu Chartieraf7c9022017-10-27 09:42:46 -070036 const value_type* Inst() const {
37 return inst_;
38 }
39
40 // Return the dex pc for an iterator compared to the code item begin.
41 uint32_t GetDexPC(const DexInstructionIteratorBase& code_item_begin) {
42 return reinterpret_cast<const uint16_t*>(inst_) -
43 reinterpret_cast<const uint16_t*>(code_item_begin.inst_);
44 }
45
46 protected:
47 const value_type* inst_ = nullptr;
48};
49
50
51static ALWAYS_INLINE inline bool operator==(const DexInstructionIteratorBase& lhs,
52 const DexInstructionIteratorBase& rhs) {
53 return lhs.Inst() == rhs.Inst();
54}
55
56static inline bool operator!=(const DexInstructionIteratorBase& lhs,
57 const DexInstructionIteratorBase& rhs) {
58 return !(lhs == rhs);
59}
60
61static inline bool operator<(const DexInstructionIteratorBase& lhs,
62 const DexInstructionIteratorBase& rhs) {
63 return lhs.Inst() < rhs.Inst();
64}
65
66static inline bool operator>(const DexInstructionIteratorBase& lhs,
67 const DexInstructionIteratorBase& rhs) {
68 return rhs < lhs;
69}
70
71static inline bool operator<=(const DexInstructionIteratorBase& lhs,
72 const DexInstructionIteratorBase& rhs) {
73 return !(rhs < lhs);
74}
75
76static inline bool operator>=(const DexInstructionIteratorBase& lhs,
77 const DexInstructionIteratorBase& rhs) {
78 return !(lhs < rhs);
79}
80
81class DexInstructionIterator : public DexInstructionIteratorBase {
82 public:
83 using value_type = std::iterator<std::forward_iterator_tag, Instruction>::value_type;
84 using difference_type = std::iterator<std::forward_iterator_tag, value_type>::difference_type;
85 using DexInstructionIteratorBase::DexInstructionIteratorBase;
86
87 explicit DexInstructionIterator(const uint16_t* inst)
88 : DexInstructionIteratorBase(value_type::At(inst)) {}
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -070089
90 // Value after modification.
91 DexInstructionIterator& operator++() {
92 inst_ = inst_->Next();
93 return *this;
94 }
95
96 // Value before modification.
97 DexInstructionIterator operator++(int) {
98 DexInstructionIterator temp = *this;
99 ++*this;
100 return temp;
101 }
102
Vladimir Markod7559b72017-09-28 13:50:37 +0100103 const value_type& operator*() const {
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -0700104 return *inst_;
105 }
106
Vladimir Markod7559b72017-09-28 13:50:37 +0100107 const value_type* operator->() const {
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -0700108 return &**this;
109 }
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700110};
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -0700111
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700112class SafeDexInstructionIterator : public DexInstructionIteratorBase {
113 public:
114 explicit SafeDexInstructionIterator(const DexInstructionIteratorBase& start,
115 const DexInstructionIteratorBase& end)
116 : DexInstructionIteratorBase(start.Inst())
117 , end_(end.Inst()) {}
118
119 // Value after modification, does not read past the end of the allowed region. May increment past
120 // the end of the code item though.
121 SafeDexInstructionIterator& operator++() {
122 AssertValid();
123 const size_t size_code_units = Inst()->CodeUnitsRequiredForSizeComputation();
124 const size_t available = reinterpret_cast<const uint16_t*>(end_) -
125 reinterpret_cast<const uint16_t*>(Inst());
126 if (size_code_units > available) {
127 error_state_ = true;
128 } else {
129 inst_ = inst_->Next();
130 }
131 return *this;
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -0700132 }
133
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700134 // Value before modification.
135 SafeDexInstructionIterator operator++(int) {
136 SafeDexInstructionIterator temp = *this;
137 ++*this;
138 return temp;
139 }
140
141 const value_type& operator*() const {
142 AssertValid();
143 return *inst_;
144 }
145
146 const value_type* operator->() const {
147 AssertValid();
148 return &**this;
149 }
150
151 // Returns true if the iterator is in an error state. This occurs when an instruction couldn't
152 // have its size computed without reading past the end iterator.
153 bool IsErrorState() const {
154 return error_state_;
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -0700155 }
156
157 private:
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700158 ALWAYS_INLINE void AssertValid() const {
159 DCHECK(!IsErrorState());
160 DCHECK_LT(Inst(), end_);
161 }
162
163 const value_type* end_ = nullptr;
164 bool error_state_ = false;
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -0700165};
166
Mathieu Chartier1d2d4ff2017-09-23 16:11:06 -0700167} // namespace art
168
169#endif // ART_RUNTIME_DEX_INSTRUCTION_ITERATOR_H_