local_value_numbering.h revision f59f18b2bd5432bb083205680c69fe64aaf60f39
1/*
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
17#ifndef ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_
18#define ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_
19
20#include "compiler_internals.h"
21
22#define NO_VALUE 0xffff
23#define ARRAY_REF 0xfffe
24
25namespace art {
26
27class DexFile;
28
29class LocalValueNumbering {
30 private:
31  // Field types correspond to the ordering of GET/PUT instructions; this order is the same
32  // for IGET, IPUT, SGET, SPUT, AGET and APUT:
33  // op         0
34  // op_WIDE    1
35  // op_OBJECT  2
36  // op_BOOLEAN 3
37  // op_BYTE    4
38  // op_CHAR    5
39  // op_SHORT   6
40  static constexpr size_t kFieldTypeCount = 7;
41
42  // FieldReference represents either a unique resolved field or all unresolved fields together.
43  struct FieldReference {
44    const DexFile* dex_file;
45    uint16_t field_idx;
46  };
47
48  struct FieldReferenceComparator {
49    bool operator()(const FieldReference& lhs, const FieldReference& rhs) const {
50      if (lhs.field_idx != rhs.field_idx) {
51        return lhs.field_idx < rhs.field_idx;
52      }
53      return lhs.dex_file < rhs.dex_file;
54    }
55  };
56
57  struct MemoryVersionKey {
58    uint16_t base;
59    uint16_t field_id;
60    uint16_t type;
61  };
62
63  struct MemoryVersionKeyComparator {
64    bool operator()(const MemoryVersionKey& lhs, const MemoryVersionKey& rhs) const {
65      if (lhs.base != rhs.base) {
66        return lhs.base < rhs.base;
67      }
68      if (lhs.field_id != rhs.field_id) {
69        return lhs.field_id < rhs.field_id;
70      }
71      return lhs.type < rhs.type;
72    }
73  };
74
75  // Key is s_reg, value is value name.
76  typedef SafeMap<uint16_t, uint16_t> SregValueMap;
77  // Key is concatenation of opcode, operand1, operand2 and modifier, value is value name.
78  typedef SafeMap<uint64_t, uint16_t> ValueMap;
79  // Key represents a memory address, value is generation.
80  typedef SafeMap<MemoryVersionKey, uint16_t, MemoryVersionKeyComparator> MemoryVersionMap;
81  // Maps field key to field id for resolved fields.
82  typedef SafeMap<FieldReference, uint32_t, FieldReferenceComparator> FieldIndexMap;
83
84 public:
85  explicit LocalValueNumbering(CompilationUnit* cu)
86      : cu_(cu),
87        sreg_value_map_(),
88        sreg_wide_value_map_(),
89        value_map_(),
90        next_memory_version_(1u),
91        global_memory_version_(0u),
92        memory_version_map_(),
93        field_index_map_(),
94        non_aliasing_refs_(),
95        null_checked_() {
96    std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
97    std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
98  }
99
100  static uint64_t BuildKey(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
101    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
105  uint16_t LookupValue(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
106    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
118  bool ValueExists(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) const {
119    uint64_t key = BuildKey(op, operand1, operand2, modifier);
120    ValueMap::const_iterator it = value_map_.find(key);
121    return (it != value_map_.end());
122  };
123
124  void SetOperandValue(uint16_t s_reg, uint16_t value) {
125    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
133  uint16_t GetOperandValue(int s_reg) {
134    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
146  void SetOperandValueWide(uint16_t s_reg, uint16_t value) {
147    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
155  uint16_t GetOperandValueWide(int s_reg) {
156    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
170 private:
171  uint16_t GetFieldId(const DexFile* dex_file, uint16_t field_idx);
172  void AdvanceGlobalMemory();
173  uint16_t GetMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
174  uint16_t AdvanceMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
175  uint16_t MarkNonAliasingNonNull(MIR* mir);
176  void MakeArgsAliasing(MIR* mir);
177  void HandleNullCheck(MIR* mir, uint16_t reg);
178  void HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index);
179  void HandlePutObject(MIR* mir);
180
181  CompilationUnit* const cu_;
182  SregValueMap sreg_value_map_;
183  SregValueMap sreg_wide_value_map_;
184  ValueMap value_map_;
185  uint16_t next_memory_version_;
186  uint16_t global_memory_version_;
187  uint16_t unresolved_sfield_version_[kFieldTypeCount];
188  uint16_t unresolved_ifield_version_[kFieldTypeCount];
189  MemoryVersionMap memory_version_map_;
190  FieldIndexMap field_index_map_;
191  // Value names of references to objects that cannot be reached through a different value name.
192  std::set<uint16_t> non_aliasing_refs_;
193  std::set<uint16_t> null_checked_;
194};
195
196}  // namespace art
197
198#endif  // ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_
199