blob: 6d67afb862226c764e8187031bc62bbc05048ad1 [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"
Vladimir Marko69f08ba2014-04-11 12:28:11 +010023#include "utils/scoped_arena_containers.h"
buzbee2502e002012-12-31 16:05:53 -080024
25#define NO_VALUE 0xffff
26#define ARRAY_REF 0xfffe
27
28namespace art {
29
Vladimir Markof59f18b2014-02-17 15:53:57 +000030class DexFile;
buzbee2502e002012-12-31 16:05:53 -080031
buzbee311ca162013-02-28 15:56:43 -080032class LocalValueNumbering {
Vladimir Markof59f18b2014-02-17 15:53:57 +000033 private:
34 // Field types correspond to the ordering of GET/PUT instructions; this order is the same
35 // for IGET, IPUT, SGET, SPUT, AGET and APUT:
36 // op 0
37 // op_WIDE 1
38 // op_OBJECT 2
39 // op_BOOLEAN 3
40 // op_BYTE 4
41 // op_CHAR 5
42 // op_SHORT 6
43 static constexpr size_t kFieldTypeCount = 7;
44
45 // FieldReference represents either a unique resolved field or all unresolved fields together.
46 struct FieldReference {
47 const DexFile* dex_file;
48 uint16_t field_idx;
49 };
50
51 struct FieldReferenceComparator {
52 bool operator()(const FieldReference& lhs, const FieldReference& rhs) const {
53 if (lhs.field_idx != rhs.field_idx) {
54 return lhs.field_idx < rhs.field_idx;
55 }
56 return lhs.dex_file < rhs.dex_file;
57 }
58 };
59
60 struct MemoryVersionKey {
61 uint16_t base;
62 uint16_t field_id;
63 uint16_t type;
64 };
65
66 struct MemoryVersionKeyComparator {
67 bool operator()(const MemoryVersionKey& lhs, const MemoryVersionKey& rhs) const {
68 if (lhs.base != rhs.base) {
69 return lhs.base < rhs.base;
70 }
71 if (lhs.field_id != rhs.field_id) {
72 return lhs.field_id < rhs.field_id;
73 }
74 return lhs.type < rhs.type;
75 }
76 };
77
78 // Key is s_reg, value is value name.
Vladimir Marko69f08ba2014-04-11 12:28:11 +010079 typedef ScopedArenaSafeMap<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 Marko69f08ba2014-04-11 12:28:11 +010081 typedef ScopedArenaSafeMap<uint64_t, uint16_t> ValueMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000082 // Key represents a memory address, value is generation.
Vladimir Marko69f08ba2014-04-11 12:28:11 +010083 typedef ScopedArenaSafeMap<MemoryVersionKey, uint16_t, MemoryVersionKeyComparator
84 > MemoryVersionMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000085 // Maps field key to field id for resolved fields.
Vladimir Marko69f08ba2014-04-11 12:28:11 +010086 typedef ScopedArenaSafeMap<FieldReference, uint32_t, FieldReferenceComparator> FieldIndexMap;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000087 // A set of value names.
Vladimir Marko69f08ba2014-04-11 12:28:11 +010088 typedef ScopedArenaSet<uint16_t> ValueNameSet;
Vladimir Markof59f18b2014-02-17 15:53:57 +000089
buzbee2502e002012-12-31 16:05:53 -080090 public:
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000091 static LocalValueNumbering* Create(CompilationUnit* cu) {
92 UniquePtr<ScopedArenaAllocator> allocator(ScopedArenaAllocator::Create(&cu->arena_stack));
93 void* addr = allocator->Alloc(sizeof(LocalValueNumbering), kArenaAllocMisc);
94 return new(addr) LocalValueNumbering(cu, allocator.release());
Vladimir Markof59f18b2014-02-17 15:53:57 +000095 }
buzbee2502e002012-12-31 16:05:53 -080096
Ian Rogers71fe2672013-03-19 20:45:02 -070097 static uint64_t BuildKey(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
buzbee2502e002012-12-31 16:05:53 -080098 return (static_cast<uint64_t>(op) << 48 | static_cast<uint64_t>(operand1) << 32 |
99 static_cast<uint64_t>(operand2) << 16 | static_cast<uint64_t>(modifier));
100 };
101
Ian Rogers71fe2672013-03-19 20:45:02 -0700102 uint16_t LookupValue(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
buzbee2502e002012-12-31 16:05:53 -0800103 uint16_t res;
104 uint64_t key = BuildKey(op, operand1, operand2, modifier);
105 ValueMap::iterator it = value_map_.find(key);
106 if (it != value_map_.end()) {
107 res = it->second;
108 } else {
109 res = value_map_.size() + 1;
110 value_map_.Put(key, res);
111 }
112 return res;
113 };
114
Ian Rogers71fe2672013-03-19 20:45:02 -0700115 bool ValueExists(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) const {
buzbee2502e002012-12-31 16:05:53 -0800116 uint64_t key = BuildKey(op, operand1, operand2, modifier);
Ian Rogers71fe2672013-03-19 20:45:02 -0700117 ValueMap::const_iterator it = value_map_.find(key);
buzbee2502e002012-12-31 16:05:53 -0800118 return (it != value_map_.end());
119 };
120
Ian Rogers71fe2672013-03-19 20:45:02 -0700121 void SetOperandValue(uint16_t s_reg, uint16_t value) {
buzbee2502e002012-12-31 16:05:53 -0800122 SregValueMap::iterator it = sreg_value_map_.find(s_reg);
123 if (it != sreg_value_map_.end()) {
124 DCHECK_EQ(it->second, value);
125 } else {
126 sreg_value_map_.Put(s_reg, value);
127 }
128 };
129
Ian Rogers71fe2672013-03-19 20:45:02 -0700130 uint16_t GetOperandValue(int s_reg) {
buzbee2502e002012-12-31 16:05:53 -0800131 uint16_t res = NO_VALUE;
132 SregValueMap::iterator it = sreg_value_map_.find(s_reg);
133 if (it != sreg_value_map_.end()) {
134 res = it->second;
135 } else {
136 // First use
137 res = LookupValue(NO_VALUE, s_reg, NO_VALUE, NO_VALUE);
138 sreg_value_map_.Put(s_reg, res);
139 }
140 return res;
141 };
142
Ian Rogers71fe2672013-03-19 20:45:02 -0700143 void SetOperandValueWide(uint16_t s_reg, uint16_t value) {
buzbee2502e002012-12-31 16:05:53 -0800144 SregValueMap::iterator it = sreg_wide_value_map_.find(s_reg);
145 if (it != sreg_wide_value_map_.end()) {
146 DCHECK_EQ(it->second, value);
147 } else {
148 sreg_wide_value_map_.Put(s_reg, value);
149 }
150 };
151
Ian Rogers71fe2672013-03-19 20:45:02 -0700152 uint16_t GetOperandValueWide(int s_reg) {
buzbee2502e002012-12-31 16:05:53 -0800153 uint16_t res = NO_VALUE;
154 SregValueMap::iterator it = sreg_wide_value_map_.find(s_reg);
155 if (it != sreg_wide_value_map_.end()) {
156 res = it->second;
157 } else {
158 // First use
159 res = LookupValue(NO_VALUE, s_reg, NO_VALUE, NO_VALUE);
160 sreg_wide_value_map_.Put(s_reg, res);
161 }
162 return res;
163 };
164
165 uint16_t GetValueNumber(MIR* mir);
166
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000167 // Allow delete-expression to destroy a LocalValueNumbering object without deallocation.
168 static void operator delete(void* ptr) { UNUSED(ptr); }
169
buzbee2502e002012-12-31 16:05:53 -0800170 private:
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000171 LocalValueNumbering(CompilationUnit* cu, ScopedArenaAllocator* allocator)
172 : cu_(cu),
173 allocator_(allocator),
174 sreg_value_map_(std::less<uint16_t>(), allocator->Adapter()),
175 sreg_wide_value_map_(std::less<uint16_t>(), allocator->Adapter()),
176 value_map_(std::less<uint64_t>(), allocator->Adapter()),
177 next_memory_version_(1u),
178 global_memory_version_(0u),
179 memory_version_map_(MemoryVersionKeyComparator(), allocator->Adapter()),
180 field_index_map_(FieldReferenceComparator(), allocator->Adapter()),
181 non_aliasing_refs_(std::less<uint16_t>(), allocator->Adapter()),
182 null_checked_(std::less<uint16_t>(), allocator->Adapter()) {
183 std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
184 std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
185 }
186
Vladimir Markof59f18b2014-02-17 15:53:57 +0000187 uint16_t GetFieldId(const DexFile* dex_file, uint16_t field_idx);
188 void AdvanceGlobalMemory();
189 uint16_t GetMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
190 uint16_t AdvanceMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
191 uint16_t MarkNonAliasingNonNull(MIR* mir);
192 void MakeArgsAliasing(MIR* mir);
193 void HandleNullCheck(MIR* mir, uint16_t reg);
194 void HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index);
195 void HandlePutObject(MIR* mir);
196
Ian Rogers71fe2672013-03-19 20:45:02 -0700197 CompilationUnit* const cu_;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000198 UniquePtr<ScopedArenaAllocator> allocator_;
buzbee2502e002012-12-31 16:05:53 -0800199 SregValueMap sreg_value_map_;
200 SregValueMap sreg_wide_value_map_;
201 ValueMap value_map_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000202 uint16_t next_memory_version_;
203 uint16_t global_memory_version_;
204 uint16_t unresolved_sfield_version_[kFieldTypeCount];
205 uint16_t unresolved_ifield_version_[kFieldTypeCount];
buzbee2502e002012-12-31 16:05:53 -0800206 MemoryVersionMap memory_version_map_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000207 FieldIndexMap field_index_map_;
208 // Value names of references to objects that cannot be reached through a different value name.
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000209 ValueNameSet non_aliasing_refs_;
210 ValueNameSet null_checked_;
211
212 DISALLOW_COPY_AND_ASSIGN(LocalValueNumbering);
buzbee2502e002012-12-31 16:05:53 -0800213};
214
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700215} // namespace art
buzbee2502e002012-12-31 16:05:53 -0800216
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700217#endif // ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_