blob: 0c2b6a7e01ee1bdbd37ca2c4e827b39f6becb31e [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
Ian Rogers700a4022014-05-19 16:49:03 -070020#include <memory>
21
buzbee2502e002012-12-31 16:05:53 -080022#include "compiler_internals.h"
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000023#include "utils/scoped_arena_allocator.h"
Vladimir Marko69f08ba2014-04-11 12:28:11 +010024#include "utils/scoped_arena_containers.h"
buzbee2502e002012-12-31 16:05:53 -080025
26#define NO_VALUE 0xffff
27#define ARRAY_REF 0xfffe
28
29namespace art {
30
Vladimir Markof59f18b2014-02-17 15:53:57 +000031class DexFile;
buzbee2502e002012-12-31 16:05:53 -080032
buzbee311ca162013-02-28 15:56:43 -080033class LocalValueNumbering {
Vladimir Markof59f18b2014-02-17 15:53:57 +000034 private:
35 // Field types correspond to the ordering of GET/PUT instructions; this order is the same
36 // for IGET, IPUT, SGET, SPUT, AGET and APUT:
37 // op 0
38 // op_WIDE 1
39 // op_OBJECT 2
40 // op_BOOLEAN 3
41 // op_BYTE 4
42 // op_CHAR 5
43 // op_SHORT 6
44 static constexpr size_t kFieldTypeCount = 7;
45
46 // FieldReference represents either a unique resolved field or all unresolved fields together.
47 struct FieldReference {
48 const DexFile* dex_file;
49 uint16_t field_idx;
50 };
51
52 struct FieldReferenceComparator {
53 bool operator()(const FieldReference& lhs, const FieldReference& rhs) const {
54 if (lhs.field_idx != rhs.field_idx) {
55 return lhs.field_idx < rhs.field_idx;
56 }
57 return lhs.dex_file < rhs.dex_file;
58 }
59 };
60
61 struct MemoryVersionKey {
62 uint16_t base;
63 uint16_t field_id;
64 uint16_t type;
65 };
66
67 struct MemoryVersionKeyComparator {
68 bool operator()(const MemoryVersionKey& lhs, const MemoryVersionKey& rhs) const {
69 if (lhs.base != rhs.base) {
70 return lhs.base < rhs.base;
71 }
72 if (lhs.field_id != rhs.field_id) {
73 return lhs.field_id < rhs.field_id;
74 }
75 return lhs.type < rhs.type;
76 }
77 };
78
79 // Key is s_reg, value is value name.
Vladimir Marko69f08ba2014-04-11 12:28:11 +010080 typedef ScopedArenaSafeMap<uint16_t, uint16_t> SregValueMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000081 // Key is concatenation of opcode, operand1, operand2 and modifier, value is value name.
Vladimir Marko69f08ba2014-04-11 12:28:11 +010082 typedef ScopedArenaSafeMap<uint64_t, uint16_t> ValueMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000083 // Key represents a memory address, value is generation.
Vladimir Marko69f08ba2014-04-11 12:28:11 +010084 typedef ScopedArenaSafeMap<MemoryVersionKey, uint16_t, MemoryVersionKeyComparator
85 > MemoryVersionMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000086 // Maps field key to field id for resolved fields.
Vladimir Marko69f08ba2014-04-11 12:28:11 +010087 typedef ScopedArenaSafeMap<FieldReference, uint32_t, FieldReferenceComparator> FieldIndexMap;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000088 // A set of value names.
Vladimir Marko69f08ba2014-04-11 12:28:11 +010089 typedef ScopedArenaSet<uint16_t> ValueNameSet;
Vladimir Markof59f18b2014-02-17 15:53:57 +000090
buzbee2502e002012-12-31 16:05:53 -080091 public:
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000092 static LocalValueNumbering* Create(CompilationUnit* cu) {
Ian Rogers700a4022014-05-19 16:49:03 -070093 std::unique_ptr<ScopedArenaAllocator> allocator(ScopedArenaAllocator::Create(&cu->arena_stack));
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000094 void* addr = allocator->Alloc(sizeof(LocalValueNumbering), kArenaAllocMisc);
95 return new(addr) LocalValueNumbering(cu, allocator.release());
Vladimir Markof59f18b2014-02-17 15:53:57 +000096 }
buzbee2502e002012-12-31 16:05:53 -080097
Ian Rogers71fe2672013-03-19 20:45:02 -070098 static uint64_t BuildKey(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
buzbee2502e002012-12-31 16:05:53 -080099 return (static_cast<uint64_t>(op) << 48 | static_cast<uint64_t>(operand1) << 32 |
100 static_cast<uint64_t>(operand2) << 16 | static_cast<uint64_t>(modifier));
101 };
102
Ian Rogers71fe2672013-03-19 20:45:02 -0700103 uint16_t LookupValue(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
buzbee2502e002012-12-31 16:05:53 -0800104 uint16_t res;
105 uint64_t key = BuildKey(op, operand1, operand2, modifier);
106 ValueMap::iterator it = value_map_.find(key);
107 if (it != value_map_.end()) {
108 res = it->second;
109 } else {
110 res = value_map_.size() + 1;
111 value_map_.Put(key, res);
112 }
113 return res;
114 };
115
Ian Rogers71fe2672013-03-19 20:45:02 -0700116 bool ValueExists(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) const {
buzbee2502e002012-12-31 16:05:53 -0800117 uint64_t key = BuildKey(op, operand1, operand2, modifier);
Ian Rogers71fe2672013-03-19 20:45:02 -0700118 ValueMap::const_iterator it = value_map_.find(key);
buzbee2502e002012-12-31 16:05:53 -0800119 return (it != value_map_.end());
120 };
121
Ian Rogers71fe2672013-03-19 20:45:02 -0700122 void SetOperandValue(uint16_t s_reg, uint16_t value) {
buzbee2502e002012-12-31 16:05:53 -0800123 SregValueMap::iterator it = sreg_value_map_.find(s_reg);
124 if (it != sreg_value_map_.end()) {
125 DCHECK_EQ(it->second, value);
126 } else {
127 sreg_value_map_.Put(s_reg, value);
128 }
129 };
130
Ian Rogers71fe2672013-03-19 20:45:02 -0700131 uint16_t GetOperandValue(int s_reg) {
buzbee2502e002012-12-31 16:05:53 -0800132 uint16_t res = NO_VALUE;
133 SregValueMap::iterator it = sreg_value_map_.find(s_reg);
134 if (it != sreg_value_map_.end()) {
135 res = it->second;
136 } else {
137 // First use
138 res = LookupValue(NO_VALUE, s_reg, NO_VALUE, NO_VALUE);
139 sreg_value_map_.Put(s_reg, res);
140 }
141 return res;
142 };
143
Ian Rogers71fe2672013-03-19 20:45:02 -0700144 void SetOperandValueWide(uint16_t s_reg, uint16_t value) {
buzbee2502e002012-12-31 16:05:53 -0800145 SregValueMap::iterator it = sreg_wide_value_map_.find(s_reg);
146 if (it != sreg_wide_value_map_.end()) {
147 DCHECK_EQ(it->second, value);
148 } else {
149 sreg_wide_value_map_.Put(s_reg, value);
150 }
151 };
152
Ian Rogers71fe2672013-03-19 20:45:02 -0700153 uint16_t GetOperandValueWide(int s_reg) {
buzbee2502e002012-12-31 16:05:53 -0800154 uint16_t res = NO_VALUE;
155 SregValueMap::iterator it = sreg_wide_value_map_.find(s_reg);
156 if (it != sreg_wide_value_map_.end()) {
157 res = it->second;
158 } else {
159 // First use
160 res = LookupValue(NO_VALUE, s_reg, NO_VALUE, NO_VALUE);
161 sreg_wide_value_map_.Put(s_reg, res);
162 }
163 return res;
164 };
165
166 uint16_t GetValueNumber(MIR* mir);
167
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000168 // Allow delete-expression to destroy a LocalValueNumbering object without deallocation.
169 static void operator delete(void* ptr) { UNUSED(ptr); }
170
buzbee2502e002012-12-31 16:05:53 -0800171 private:
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000172 LocalValueNumbering(CompilationUnit* cu, ScopedArenaAllocator* allocator)
173 : cu_(cu),
174 allocator_(allocator),
175 sreg_value_map_(std::less<uint16_t>(), allocator->Adapter()),
176 sreg_wide_value_map_(std::less<uint16_t>(), allocator->Adapter()),
177 value_map_(std::less<uint64_t>(), allocator->Adapter()),
178 next_memory_version_(1u),
179 global_memory_version_(0u),
180 memory_version_map_(MemoryVersionKeyComparator(), allocator->Adapter()),
181 field_index_map_(FieldReferenceComparator(), allocator->Adapter()),
182 non_aliasing_refs_(std::less<uint16_t>(), allocator->Adapter()),
183 null_checked_(std::less<uint16_t>(), allocator->Adapter()) {
184 std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
185 std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
186 }
187
Vladimir Markof59f18b2014-02-17 15:53:57 +0000188 uint16_t GetFieldId(const DexFile* dex_file, uint16_t field_idx);
189 void AdvanceGlobalMemory();
190 uint16_t GetMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
191 uint16_t AdvanceMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
192 uint16_t MarkNonAliasingNonNull(MIR* mir);
193 void MakeArgsAliasing(MIR* mir);
194 void HandleNullCheck(MIR* mir, uint16_t reg);
195 void HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index);
196 void HandlePutObject(MIR* mir);
197
Ian Rogers71fe2672013-03-19 20:45:02 -0700198 CompilationUnit* const cu_;
Ian Rogers700a4022014-05-19 16:49:03 -0700199 std::unique_ptr<ScopedArenaAllocator> allocator_;
buzbee2502e002012-12-31 16:05:53 -0800200 SregValueMap sreg_value_map_;
201 SregValueMap sreg_wide_value_map_;
202 ValueMap value_map_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000203 uint16_t next_memory_version_;
204 uint16_t global_memory_version_;
205 uint16_t unresolved_sfield_version_[kFieldTypeCount];
206 uint16_t unresolved_ifield_version_[kFieldTypeCount];
buzbee2502e002012-12-31 16:05:53 -0800207 MemoryVersionMap memory_version_map_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000208 FieldIndexMap field_index_map_;
209 // Value names of references to objects that cannot be reached through a different value name.
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000210 ValueNameSet non_aliasing_refs_;
211 ValueNameSet null_checked_;
212
213 DISALLOW_COPY_AND_ASSIGN(LocalValueNumbering);
buzbee2502e002012-12-31 16:05:53 -0800214};
215
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700216} // namespace art
buzbee2502e002012-12-31 16:05:53 -0800217
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700218#endif // ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_