blob: 535b613ba1bdb9b19cbe9d59a69ab4478b25ee06 [file] [log] [blame]
buzbee2502e002012-12-31 16:05:53 -08001/*
2 * Copyright (C) 2012 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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_
18#define ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_
buzbee2502e002012-12-31 16:05:53 -080019
20#include "compiler_internals.h"
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000021#include "UniquePtr.h"
22#include "utils/scoped_arena_allocator.h"
buzbee2502e002012-12-31 16:05:53 -080023
24#define NO_VALUE 0xffff
25#define ARRAY_REF 0xfffe
26
27namespace art {
28
Vladimir Markof59f18b2014-02-17 15:53:57 +000029class DexFile;
buzbee2502e002012-12-31 16:05:53 -080030
buzbee311ca162013-02-28 15:56:43 -080031class LocalValueNumbering {
Vladimir Markof59f18b2014-02-17 15:53:57 +000032 private:
33 // Field types correspond to the ordering of GET/PUT instructions; this order is the same
34 // for IGET, IPUT, SGET, SPUT, AGET and APUT:
35 // op 0
36 // op_WIDE 1
37 // op_OBJECT 2
38 // op_BOOLEAN 3
39 // op_BYTE 4
40 // op_CHAR 5
41 // op_SHORT 6
42 static constexpr size_t kFieldTypeCount = 7;
43
44 // FieldReference represents either a unique resolved field or all unresolved fields together.
45 struct FieldReference {
46 const DexFile* dex_file;
47 uint16_t field_idx;
48 };
49
50 struct FieldReferenceComparator {
51 bool operator()(const FieldReference& lhs, const FieldReference& rhs) const {
52 if (lhs.field_idx != rhs.field_idx) {
53 return lhs.field_idx < rhs.field_idx;
54 }
55 return lhs.dex_file < rhs.dex_file;
56 }
57 };
58
59 struct MemoryVersionKey {
60 uint16_t base;
61 uint16_t field_id;
62 uint16_t type;
63 };
64
65 struct MemoryVersionKeyComparator {
66 bool operator()(const MemoryVersionKey& lhs, const MemoryVersionKey& rhs) const {
67 if (lhs.base != rhs.base) {
68 return lhs.base < rhs.base;
69 }
70 if (lhs.field_id != rhs.field_id) {
71 return lhs.field_id < rhs.field_id;
72 }
73 return lhs.type < rhs.type;
74 }
75 };
76
77 // Key is s_reg, value is value name.
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000078 typedef SafeMap<uint16_t, uint16_t, std::less<uint16_t>,
79 ScopedArenaAllocatorAdapter<std::pair<uint16_t, uint16_t> > > SregValueMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000080 // Key is concatenation of opcode, operand1, operand2 and modifier, value is value name.
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000081 typedef SafeMap<uint64_t, uint16_t, std::less<uint64_t>,
82 ScopedArenaAllocatorAdapter<std::pair<uint64_t, uint16_t> > > ValueMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000083 // Key represents a memory address, value is generation.
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000084 typedef SafeMap<MemoryVersionKey, uint16_t, MemoryVersionKeyComparator,
85 ScopedArenaAllocatorAdapter<std::pair<MemoryVersionKey, uint16_t> > > MemoryVersionMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000086 // Maps field key to field id for resolved fields.
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000087 typedef SafeMap<FieldReference, uint32_t, FieldReferenceComparator,
88 ScopedArenaAllocatorAdapter<std::pair<FieldReference, uint16_t> > > FieldIndexMap;
89 // A set of value names.
90 typedef std::set<uint16_t, std::less<uint16_t>,
91 ScopedArenaAllocatorAdapter<uint16_t> > ValueNameSet;
Vladimir Markof59f18b2014-02-17 15:53:57 +000092
buzbee2502e002012-12-31 16:05:53 -080093 public:
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000094 static LocalValueNumbering* Create(CompilationUnit* cu) {
95 UniquePtr<ScopedArenaAllocator> allocator(ScopedArenaAllocator::Create(&cu->arena_stack));
96 void* addr = allocator->Alloc(sizeof(LocalValueNumbering), kArenaAllocMisc);
97 return new(addr) LocalValueNumbering(cu, allocator.release());
Vladimir Markof59f18b2014-02-17 15:53:57 +000098 }
buzbee2502e002012-12-31 16:05:53 -080099
Ian Rogers71fe2672013-03-19 20:45:02 -0700100 static uint64_t BuildKey(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
buzbee2502e002012-12-31 16:05:53 -0800101 return (static_cast<uint64_t>(op) << 48 | static_cast<uint64_t>(operand1) << 32 |
102 static_cast<uint64_t>(operand2) << 16 | static_cast<uint64_t>(modifier));
103 };
104
Ian Rogers71fe2672013-03-19 20:45:02 -0700105 uint16_t LookupValue(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
buzbee2502e002012-12-31 16:05:53 -0800106 uint16_t res;
107 uint64_t key = BuildKey(op, operand1, operand2, modifier);
108 ValueMap::iterator it = value_map_.find(key);
109 if (it != value_map_.end()) {
110 res = it->second;
111 } else {
112 res = value_map_.size() + 1;
113 value_map_.Put(key, res);
114 }
115 return res;
116 };
117
Ian Rogers71fe2672013-03-19 20:45:02 -0700118 bool ValueExists(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) const {
buzbee2502e002012-12-31 16:05:53 -0800119 uint64_t key = BuildKey(op, operand1, operand2, modifier);
Ian Rogers71fe2672013-03-19 20:45:02 -0700120 ValueMap::const_iterator it = value_map_.find(key);
buzbee2502e002012-12-31 16:05:53 -0800121 return (it != value_map_.end());
122 };
123
Ian Rogers71fe2672013-03-19 20:45:02 -0700124 void SetOperandValue(uint16_t s_reg, uint16_t value) {
buzbee2502e002012-12-31 16:05:53 -0800125 SregValueMap::iterator it = sreg_value_map_.find(s_reg);
126 if (it != sreg_value_map_.end()) {
127 DCHECK_EQ(it->second, value);
128 } else {
129 sreg_value_map_.Put(s_reg, value);
130 }
131 };
132
Ian Rogers71fe2672013-03-19 20:45:02 -0700133 uint16_t GetOperandValue(int s_reg) {
buzbee2502e002012-12-31 16:05:53 -0800134 uint16_t res = NO_VALUE;
135 SregValueMap::iterator it = sreg_value_map_.find(s_reg);
136 if (it != sreg_value_map_.end()) {
137 res = it->second;
138 } else {
139 // First use
140 res = LookupValue(NO_VALUE, s_reg, NO_VALUE, NO_VALUE);
141 sreg_value_map_.Put(s_reg, res);
142 }
143 return res;
144 };
145
Ian Rogers71fe2672013-03-19 20:45:02 -0700146 void SetOperandValueWide(uint16_t s_reg, uint16_t value) {
buzbee2502e002012-12-31 16:05:53 -0800147 SregValueMap::iterator it = sreg_wide_value_map_.find(s_reg);
148 if (it != sreg_wide_value_map_.end()) {
149 DCHECK_EQ(it->second, value);
150 } else {
151 sreg_wide_value_map_.Put(s_reg, value);
152 }
153 };
154
Ian Rogers71fe2672013-03-19 20:45:02 -0700155 uint16_t GetOperandValueWide(int s_reg) {
buzbee2502e002012-12-31 16:05:53 -0800156 uint16_t res = NO_VALUE;
157 SregValueMap::iterator it = sreg_wide_value_map_.find(s_reg);
158 if (it != sreg_wide_value_map_.end()) {
159 res = it->second;
160 } else {
161 // First use
162 res = LookupValue(NO_VALUE, s_reg, NO_VALUE, NO_VALUE);
163 sreg_wide_value_map_.Put(s_reg, res);
164 }
165 return res;
166 };
167
168 uint16_t GetValueNumber(MIR* mir);
169
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000170 // Allow delete-expression to destroy a LocalValueNumbering object without deallocation.
171 static void operator delete(void* ptr) { UNUSED(ptr); }
172
buzbee2502e002012-12-31 16:05:53 -0800173 private:
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000174 LocalValueNumbering(CompilationUnit* cu, ScopedArenaAllocator* allocator)
175 : cu_(cu),
176 allocator_(allocator),
177 sreg_value_map_(std::less<uint16_t>(), allocator->Adapter()),
178 sreg_wide_value_map_(std::less<uint16_t>(), allocator->Adapter()),
179 value_map_(std::less<uint64_t>(), allocator->Adapter()),
180 next_memory_version_(1u),
181 global_memory_version_(0u),
182 memory_version_map_(MemoryVersionKeyComparator(), allocator->Adapter()),
183 field_index_map_(FieldReferenceComparator(), allocator->Adapter()),
184 non_aliasing_refs_(std::less<uint16_t>(), allocator->Adapter()),
185 null_checked_(std::less<uint16_t>(), allocator->Adapter()) {
186 std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
187 std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
188 }
189
Vladimir Markof59f18b2014-02-17 15:53:57 +0000190 uint16_t GetFieldId(const DexFile* dex_file, uint16_t field_idx);
191 void AdvanceGlobalMemory();
192 uint16_t GetMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
193 uint16_t AdvanceMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
194 uint16_t MarkNonAliasingNonNull(MIR* mir);
195 void MakeArgsAliasing(MIR* mir);
196 void HandleNullCheck(MIR* mir, uint16_t reg);
197 void HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index);
198 void HandlePutObject(MIR* mir);
199
Ian Rogers71fe2672013-03-19 20:45:02 -0700200 CompilationUnit* const cu_;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000201 UniquePtr<ScopedArenaAllocator> allocator_;
buzbee2502e002012-12-31 16:05:53 -0800202 SregValueMap sreg_value_map_;
203 SregValueMap sreg_wide_value_map_;
204 ValueMap value_map_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000205 uint16_t next_memory_version_;
206 uint16_t global_memory_version_;
207 uint16_t unresolved_sfield_version_[kFieldTypeCount];
208 uint16_t unresolved_ifield_version_[kFieldTypeCount];
buzbee2502e002012-12-31 16:05:53 -0800209 MemoryVersionMap memory_version_map_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000210 FieldIndexMap field_index_map_;
211 // Value names of references to objects that cannot be reached through a different value name.
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000212 ValueNameSet non_aliasing_refs_;
213 ValueNameSet null_checked_;
214
215 DISALLOW_COPY_AND_ASSIGN(LocalValueNumbering);
buzbee2502e002012-12-31 16:05:53 -0800216};
217
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700218} // namespace art
buzbee2502e002012-12-31 16:05:53 -0800219
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700220#endif // ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_