| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 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 |  | 
| buzbee | 311ca16 | 2013-02-28 15:56:43 -0800 | [diff] [blame] | 17 | #include "local_value_numbering.h" | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 18 |  | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame^] | 19 | #include "mir_field_info.h" | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 20 | #include "mir_graph.h" | 
|  | 21 |  | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 22 | namespace art { | 
|  | 23 |  | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 24 | uint16_t LocalValueNumbering::GetFieldId(const DexFile* dex_file, uint16_t field_idx) { | 
|  | 25 | FieldReference key = { dex_file, field_idx }; | 
|  | 26 | auto it = field_index_map_.find(key); | 
|  | 27 | if (it != field_index_map_.end()) { | 
|  | 28 | return it->second; | 
|  | 29 | } | 
|  | 30 | uint16_t id = field_index_map_.size(); | 
|  | 31 | field_index_map_.Put(key, id); | 
|  | 32 | return id; | 
|  | 33 | } | 
|  | 34 |  | 
|  | 35 | void LocalValueNumbering::AdvanceGlobalMemory() { | 
|  | 36 | // See AdvanceMemoryVersion() for explanation. | 
|  | 37 | global_memory_version_ = next_memory_version_; | 
|  | 38 | ++next_memory_version_; | 
|  | 39 | } | 
|  | 40 |  | 
|  | 41 | uint16_t LocalValueNumbering::GetMemoryVersion(uint16_t base, uint16_t field, uint16_t type) { | 
|  | 42 | // See AdvanceMemoryVersion() for explanation. | 
|  | 43 | MemoryVersionKey key = { base, field, type }; | 
|  | 44 | MemoryVersionMap::iterator it = memory_version_map_.find(key); | 
|  | 45 | uint16_t memory_version = (it != memory_version_map_.end()) ? it->second : 0u; | 
|  | 46 | if (base != NO_VALUE && non_aliasing_refs_.find(base) == non_aliasing_refs_.end()) { | 
|  | 47 | // Check modifications by potentially aliased access. | 
|  | 48 | MemoryVersionKey aliased_access_key = { NO_VALUE, field, type }; | 
|  | 49 | auto aa_it = memory_version_map_.find(aliased_access_key); | 
|  | 50 | if (aa_it != memory_version_map_.end() && aa_it->second > memory_version) { | 
|  | 51 | memory_version = aa_it->second; | 
|  | 52 | } | 
|  | 53 | memory_version = std::max(memory_version, global_memory_version_); | 
|  | 54 | } else if (base != NO_VALUE) { | 
|  | 55 | // Ignore global_memory_version_ for access via unique references. | 
|  | 56 | } else { | 
|  | 57 | memory_version = std::max(memory_version, global_memory_version_); | 
|  | 58 | } | 
|  | 59 | return memory_version; | 
|  | 60 | }; | 
|  | 61 |  | 
|  | 62 | uint16_t LocalValueNumbering::AdvanceMemoryVersion(uint16_t base, uint16_t field, uint16_t type) { | 
|  | 63 | // When we read the same value from memory, we want to assign the same value name to it. | 
|  | 64 | // However, we need to be careful not to assign the same value name if the memory location | 
|  | 65 | // may have been written to between the reads. To avoid that we do "memory versioning". | 
|  | 66 | // | 
|  | 67 | // For each write to a memory location (instance field, static field, array element) we assign | 
|  | 68 | // a new memory version number to the location identified by the value name of the base register, | 
|  | 69 | // the field id and type, or "{ base, field, type }". For static fields the "base" is NO_VALUE | 
|  | 70 | // since they are not accessed via a reference. For arrays the "field" is NO_VALUE since they | 
|  | 71 | // don't have a field id. | 
|  | 72 | // | 
|  | 73 | // To account for the possibility of aliased access to the same memory location via different | 
|  | 74 | // "base", we also store the memory version number with the key "{ NO_VALUE, field, type }" | 
|  | 75 | // if "base" is an aliasing reference and check it in GetMemoryVersion() on reads via | 
|  | 76 | // aliasing references. A global memory version is set for method calls as a method can | 
|  | 77 | // potentially write to any memory location accessed via an aliasing reference. | 
|  | 78 |  | 
|  | 79 | uint16_t result = next_memory_version_; | 
|  | 80 | ++next_memory_version_; | 
|  | 81 | MemoryVersionKey key = { base, field, type }; | 
|  | 82 | memory_version_map_.Overwrite(key, result); | 
|  | 83 | if (base != NO_VALUE && non_aliasing_refs_.find(base) == non_aliasing_refs_.end()) { | 
|  | 84 | // Advance memory version for aliased access. | 
|  | 85 | MemoryVersionKey aliased_access_key = { NO_VALUE, field, type }; | 
|  | 86 | memory_version_map_.Overwrite(aliased_access_key, result); | 
|  | 87 | } | 
|  | 88 | return result; | 
|  | 89 | }; | 
|  | 90 |  | 
|  | 91 | uint16_t LocalValueNumbering::MarkNonAliasingNonNull(MIR* mir) { | 
|  | 92 | uint16_t res = GetOperandValue(mir->ssa_rep->defs[0]); | 
|  | 93 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 94 | DCHECK(null_checked_.find(res) == null_checked_.end()); | 
|  | 95 | null_checked_.insert(res); | 
|  | 96 | non_aliasing_refs_.insert(res); | 
|  | 97 | return res; | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | void LocalValueNumbering::MakeArgsAliasing(MIR* mir) { | 
|  | 101 | for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) { | 
|  | 102 | uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]); | 
|  | 103 | non_aliasing_refs_.erase(reg); | 
|  | 104 | } | 
|  | 105 | } | 
|  | 106 |  | 
|  | 107 | void LocalValueNumbering::HandleNullCheck(MIR* mir, uint16_t reg) { | 
|  | 108 | if (null_checked_.find(reg) != null_checked_.end()) { | 
|  | 109 | if (cu_->verbose) { | 
|  | 110 | LOG(INFO) << "Removing null check for 0x" << std::hex << mir->offset; | 
|  | 111 | } | 
|  | 112 | mir->optimization_flags |= MIR_IGNORE_NULL_CHECK; | 
|  | 113 | } else { | 
|  | 114 | null_checked_.insert(reg); | 
|  | 115 | } | 
|  | 116 | } | 
|  | 117 |  | 
|  | 118 | void LocalValueNumbering::HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index) { | 
|  | 119 | if (ValueExists(ARRAY_REF, array, index, NO_VALUE)) { | 
|  | 120 | if (cu_->verbose) { | 
|  | 121 | LOG(INFO) << "Removing range check for 0x" << std::hex << mir->offset; | 
|  | 122 | } | 
|  | 123 | mir->optimization_flags |= MIR_IGNORE_RANGE_CHECK; | 
|  | 124 | } | 
|  | 125 | // Use side effect to note range check completed. | 
|  | 126 | (void)LookupValue(ARRAY_REF, array, index, NO_VALUE); | 
|  | 127 | } | 
|  | 128 |  | 
|  | 129 | void LocalValueNumbering::HandlePutObject(MIR* mir) { | 
|  | 130 | // If we're storing a non-aliasing reference, stop tracking it as non-aliasing now. | 
|  | 131 | uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]); | 
|  | 132 | non_aliasing_refs_.erase(base); | 
|  | 133 | } | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 134 |  | 
| Brian Carlstrom | 2ce745c | 2013-07-17 17:44:30 -0700 | [diff] [blame] | 135 | uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) { | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 136 | uint16_t res = NO_VALUE; | 
|  | 137 | uint16_t opcode = mir->dalvikInsn.opcode; | 
|  | 138 | switch (opcode) { | 
|  | 139 | case Instruction::NOP: | 
|  | 140 | case Instruction::RETURN_VOID: | 
|  | 141 | case Instruction::RETURN: | 
|  | 142 | case Instruction::RETURN_OBJECT: | 
|  | 143 | case Instruction::RETURN_WIDE: | 
|  | 144 | case Instruction::MONITOR_ENTER: | 
|  | 145 | case Instruction::MONITOR_EXIT: | 
|  | 146 | case Instruction::GOTO: | 
|  | 147 | case Instruction::GOTO_16: | 
|  | 148 | case Instruction::GOTO_32: | 
|  | 149 | case Instruction::CHECK_CAST: | 
|  | 150 | case Instruction::THROW: | 
|  | 151 | case Instruction::FILL_ARRAY_DATA: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 152 | case Instruction::PACKED_SWITCH: | 
|  | 153 | case Instruction::SPARSE_SWITCH: | 
|  | 154 | case Instruction::IF_EQ: | 
|  | 155 | case Instruction::IF_NE: | 
|  | 156 | case Instruction::IF_LT: | 
|  | 157 | case Instruction::IF_GE: | 
|  | 158 | case Instruction::IF_GT: | 
|  | 159 | case Instruction::IF_LE: | 
|  | 160 | case Instruction::IF_EQZ: | 
|  | 161 | case Instruction::IF_NEZ: | 
|  | 162 | case Instruction::IF_LTZ: | 
|  | 163 | case Instruction::IF_GEZ: | 
|  | 164 | case Instruction::IF_GTZ: | 
|  | 165 | case Instruction::IF_LEZ: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 166 | case kMirOpFusedCmplFloat: | 
|  | 167 | case kMirOpFusedCmpgFloat: | 
|  | 168 | case kMirOpFusedCmplDouble: | 
|  | 169 | case kMirOpFusedCmpgDouble: | 
|  | 170 | case kMirOpFusedCmpLong: | 
|  | 171 | // Nothing defined - take no action. | 
|  | 172 | break; | 
|  | 173 |  | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 174 | case Instruction::FILLED_NEW_ARRAY: | 
|  | 175 | case Instruction::FILLED_NEW_ARRAY_RANGE: | 
|  | 176 | // Nothing defined but the result will be unique and non-null. | 
|  | 177 | if (mir->next != nullptr && mir->next->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) { | 
|  | 178 | MarkNonAliasingNonNull(mir->next); | 
|  | 179 | // The MOVE_RESULT_OBJECT will be processed next and we'll return the value name then. | 
|  | 180 | } | 
|  | 181 | MakeArgsAliasing(mir); | 
|  | 182 | break; | 
|  | 183 |  | 
|  | 184 | case Instruction::INVOKE_DIRECT: | 
|  | 185 | case Instruction::INVOKE_DIRECT_RANGE: | 
|  | 186 | case Instruction::INVOKE_VIRTUAL: | 
|  | 187 | case Instruction::INVOKE_VIRTUAL_RANGE: | 
|  | 188 | case Instruction::INVOKE_SUPER: | 
|  | 189 | case Instruction::INVOKE_SUPER_RANGE: | 
|  | 190 | case Instruction::INVOKE_INTERFACE: | 
|  | 191 | case Instruction::INVOKE_INTERFACE_RANGE: { | 
|  | 192 | // Nothing defined but handle the null check. | 
|  | 193 | uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]); | 
|  | 194 | HandleNullCheck(mir, reg); | 
|  | 195 | } | 
|  | 196 | // Intentional fall-through. | 
|  | 197 | case Instruction::INVOKE_STATIC: | 
|  | 198 | case Instruction::INVOKE_STATIC_RANGE: | 
|  | 199 | AdvanceGlobalMemory(); | 
|  | 200 | MakeArgsAliasing(mir); | 
|  | 201 | break; | 
|  | 202 |  | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 203 | case Instruction::MOVE_RESULT: | 
|  | 204 | case Instruction::MOVE_RESULT_OBJECT: | 
|  | 205 | case Instruction::INSTANCE_OF: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 206 | // 1 result, treat as unique each time, use result s_reg - will be unique. | 
|  | 207 | res = GetOperandValue(mir->ssa_rep->defs[0]); | 
|  | 208 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 209 | break; | 
|  | 210 | case Instruction::MOVE_EXCEPTION: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 211 | case Instruction::NEW_INSTANCE: | 
|  | 212 | case Instruction::CONST_STRING: | 
|  | 213 | case Instruction::CONST_STRING_JUMBO: | 
|  | 214 | case Instruction::CONST_CLASS: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 215 | case Instruction::NEW_ARRAY: | 
|  | 216 | // 1 result, treat as unique each time, use result s_reg - will be unique. | 
|  | 217 | res = MarkNonAliasingNonNull(mir); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 218 | break; | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 219 | case Instruction::MOVE_RESULT_WIDE: | 
|  | 220 | // 1 wide result, treat as unique each time, use result s_reg - will be unique. | 
|  | 221 | res = GetOperandValueWide(mir->ssa_rep->defs[0]); | 
|  | 222 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 223 | break; | 
|  | 224 |  | 
|  | 225 | case kMirOpPhi: | 
|  | 226 | /* | 
|  | 227 | * Because we'll only see phi nodes at the beginning of an extended basic block, | 
|  | 228 | * we can ignore them.  Revisit if we shift to global value numbering. | 
|  | 229 | */ | 
|  | 230 | break; | 
|  | 231 |  | 
|  | 232 | case Instruction::MOVE: | 
|  | 233 | case Instruction::MOVE_OBJECT: | 
|  | 234 | case Instruction::MOVE_16: | 
|  | 235 | case Instruction::MOVE_OBJECT_16: | 
|  | 236 | case Instruction::MOVE_FROM16: | 
|  | 237 | case Instruction::MOVE_OBJECT_FROM16: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 238 | case kMirOpCopy: | 
|  | 239 | // Just copy value number of source to value number of result. | 
|  | 240 | res = GetOperandValue(mir->ssa_rep->uses[0]); | 
|  | 241 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 242 | break; | 
|  | 243 |  | 
|  | 244 | case Instruction::MOVE_WIDE: | 
|  | 245 | case Instruction::MOVE_WIDE_16: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 246 | case Instruction::MOVE_WIDE_FROM16: | 
|  | 247 | // Just copy value number of source to value number of result. | 
|  | 248 | res = GetOperandValueWide(mir->ssa_rep->uses[0]); | 
|  | 249 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 250 | break; | 
|  | 251 |  | 
|  | 252 | case Instruction::CONST: | 
|  | 253 | case Instruction::CONST_4: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 254 | case Instruction::CONST_16: | 
|  | 255 | res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB), | 
|  | 256 | High16Bits(mir->dalvikInsn.vB >> 16), 0); | 
|  | 257 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 258 | break; | 
|  | 259 |  | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 260 | case Instruction::CONST_HIGH16: | 
|  | 261 | res = LookupValue(Instruction::CONST, 0, mir->dalvikInsn.vB, 0); | 
|  | 262 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 263 | break; | 
|  | 264 |  | 
|  | 265 | case Instruction::CONST_WIDE_16: | 
|  | 266 | case Instruction::CONST_WIDE_32: { | 
|  | 267 | uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB), | 
|  | 268 | High16Bits(mir->dalvikInsn.vB >> 16), 1); | 
|  | 269 | uint16_t high_res; | 
|  | 270 | if (mir->dalvikInsn.vB & 0x80000000) { | 
|  | 271 | high_res = LookupValue(Instruction::CONST, 0xffff, 0xffff, 2); | 
|  | 272 | } else { | 
|  | 273 | high_res = LookupValue(Instruction::CONST, 0, 0, 2); | 
|  | 274 | } | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 275 | res = LookupValue(Instruction::CONST, low_res, high_res, 3); | 
|  | 276 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 277 | } | 
|  | 278 | break; | 
|  | 279 |  | 
|  | 280 | case Instruction::CONST_WIDE: { | 
|  | 281 | uint32_t low_word = Low32Bits(mir->dalvikInsn.vB_wide); | 
|  | 282 | uint32_t high_word = High32Bits(mir->dalvikInsn.vB_wide); | 
|  | 283 | uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(low_word), | 
|  | 284 | High16Bits(low_word), 1); | 
|  | 285 | uint16_t high_res = LookupValue(Instruction::CONST, Low16Bits(high_word), | 
|  | 286 | High16Bits(high_word), 2); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 287 | res = LookupValue(Instruction::CONST, low_res, high_res, 3); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 288 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
|  | 289 | } | 
|  | 290 | break; | 
|  | 291 |  | 
|  | 292 | case Instruction::CONST_WIDE_HIGH16: { | 
|  | 293 | uint16_t low_res = LookupValue(Instruction::CONST, 0, 0, 1); | 
|  | 294 | uint16_t high_res = LookupValue(Instruction::CONST, 0, Low16Bits(mir->dalvikInsn.vB), 2); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 295 | res = LookupValue(Instruction::CONST, low_res, high_res, 3); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 296 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
|  | 297 | } | 
|  | 298 | break; | 
|  | 299 |  | 
|  | 300 | case Instruction::ARRAY_LENGTH: | 
|  | 301 | case Instruction::NEG_INT: | 
|  | 302 | case Instruction::NOT_INT: | 
|  | 303 | case Instruction::NEG_FLOAT: | 
|  | 304 | case Instruction::INT_TO_BYTE: | 
|  | 305 | case Instruction::INT_TO_SHORT: | 
|  | 306 | case Instruction::INT_TO_CHAR: | 
|  | 307 | case Instruction::INT_TO_FLOAT: | 
|  | 308 | case Instruction::FLOAT_TO_INT: { | 
|  | 309 | // res = op + 1 operand | 
|  | 310 | uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 311 | res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 312 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 313 | } | 
|  | 314 | break; | 
|  | 315 |  | 
|  | 316 | case Instruction::LONG_TO_FLOAT: | 
|  | 317 | case Instruction::LONG_TO_INT: | 
|  | 318 | case Instruction::DOUBLE_TO_FLOAT: | 
|  | 319 | case Instruction::DOUBLE_TO_INT: { | 
|  | 320 | // res = op + 1 wide operand | 
|  | 321 | uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 322 | res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 323 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 324 | } | 
|  | 325 | break; | 
|  | 326 |  | 
|  | 327 |  | 
|  | 328 | case Instruction::DOUBLE_TO_LONG: | 
|  | 329 | case Instruction::LONG_TO_DOUBLE: | 
|  | 330 | case Instruction::NEG_LONG: | 
|  | 331 | case Instruction::NOT_LONG: | 
|  | 332 | case Instruction::NEG_DOUBLE: { | 
|  | 333 | // wide res = op + 1 wide operand | 
|  | 334 | uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 335 | res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 336 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
|  | 337 | } | 
|  | 338 | break; | 
|  | 339 |  | 
|  | 340 | case Instruction::FLOAT_TO_DOUBLE: | 
|  | 341 | case Instruction::FLOAT_TO_LONG: | 
|  | 342 | case Instruction::INT_TO_DOUBLE: | 
|  | 343 | case Instruction::INT_TO_LONG: { | 
|  | 344 | // wide res = op + 1 operand | 
|  | 345 | uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 346 | res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 347 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
|  | 348 | } | 
|  | 349 | break; | 
|  | 350 |  | 
|  | 351 | case Instruction::CMPL_DOUBLE: | 
|  | 352 | case Instruction::CMPG_DOUBLE: | 
|  | 353 | case Instruction::CMP_LONG: { | 
|  | 354 | // res = op + 2 wide operands | 
|  | 355 | uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); | 
|  | 356 | uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 357 | res = LookupValue(opcode, operand1, operand2, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 358 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 359 | } | 
|  | 360 | break; | 
|  | 361 |  | 
|  | 362 | case Instruction::CMPG_FLOAT: | 
|  | 363 | case Instruction::CMPL_FLOAT: | 
|  | 364 | case Instruction::ADD_INT: | 
|  | 365 | case Instruction::ADD_INT_2ADDR: | 
|  | 366 | case Instruction::MUL_INT: | 
|  | 367 | case Instruction::MUL_INT_2ADDR: | 
|  | 368 | case Instruction::AND_INT: | 
|  | 369 | case Instruction::AND_INT_2ADDR: | 
|  | 370 | case Instruction::OR_INT: | 
|  | 371 | case Instruction::OR_INT_2ADDR: | 
|  | 372 | case Instruction::XOR_INT: | 
|  | 373 | case Instruction::XOR_INT_2ADDR: | 
|  | 374 | case Instruction::SUB_INT: | 
|  | 375 | case Instruction::SUB_INT_2ADDR: | 
|  | 376 | case Instruction::DIV_INT: | 
|  | 377 | case Instruction::DIV_INT_2ADDR: | 
|  | 378 | case Instruction::REM_INT: | 
|  | 379 | case Instruction::REM_INT_2ADDR: | 
|  | 380 | case Instruction::SHL_INT: | 
|  | 381 | case Instruction::SHL_INT_2ADDR: | 
|  | 382 | case Instruction::SHR_INT: | 
|  | 383 | case Instruction::SHR_INT_2ADDR: | 
|  | 384 | case Instruction::USHR_INT: | 
|  | 385 | case Instruction::USHR_INT_2ADDR: { | 
|  | 386 | // res = op + 2 operands | 
|  | 387 | uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); | 
|  | 388 | uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 389 | res = LookupValue(opcode, operand1, operand2, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 390 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 391 | } | 
|  | 392 | break; | 
|  | 393 |  | 
|  | 394 | case Instruction::ADD_LONG: | 
|  | 395 | case Instruction::SUB_LONG: | 
|  | 396 | case Instruction::MUL_LONG: | 
|  | 397 | case Instruction::DIV_LONG: | 
|  | 398 | case Instruction::REM_LONG: | 
|  | 399 | case Instruction::AND_LONG: | 
|  | 400 | case Instruction::OR_LONG: | 
|  | 401 | case Instruction::XOR_LONG: | 
|  | 402 | case Instruction::ADD_LONG_2ADDR: | 
|  | 403 | case Instruction::SUB_LONG_2ADDR: | 
|  | 404 | case Instruction::MUL_LONG_2ADDR: | 
|  | 405 | case Instruction::DIV_LONG_2ADDR: | 
|  | 406 | case Instruction::REM_LONG_2ADDR: | 
|  | 407 | case Instruction::AND_LONG_2ADDR: | 
|  | 408 | case Instruction::OR_LONG_2ADDR: | 
|  | 409 | case Instruction::XOR_LONG_2ADDR: | 
|  | 410 | case Instruction::ADD_DOUBLE: | 
|  | 411 | case Instruction::SUB_DOUBLE: | 
|  | 412 | case Instruction::MUL_DOUBLE: | 
|  | 413 | case Instruction::DIV_DOUBLE: | 
|  | 414 | case Instruction::REM_DOUBLE: | 
|  | 415 | case Instruction::ADD_DOUBLE_2ADDR: | 
|  | 416 | case Instruction::SUB_DOUBLE_2ADDR: | 
|  | 417 | case Instruction::MUL_DOUBLE_2ADDR: | 
|  | 418 | case Instruction::DIV_DOUBLE_2ADDR: | 
|  | 419 | case Instruction::REM_DOUBLE_2ADDR: { | 
|  | 420 | // wide res = op + 2 wide operands | 
|  | 421 | uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); | 
|  | 422 | uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 423 | res = LookupValue(opcode, operand1, operand2, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 424 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
|  | 425 | } | 
|  | 426 | break; | 
|  | 427 |  | 
|  | 428 | case Instruction::SHL_LONG: | 
|  | 429 | case Instruction::SHR_LONG: | 
|  | 430 | case Instruction::USHR_LONG: | 
|  | 431 | case Instruction::SHL_LONG_2ADDR: | 
|  | 432 | case Instruction::SHR_LONG_2ADDR: | 
|  | 433 | case Instruction::USHR_LONG_2ADDR: { | 
|  | 434 | // wide res = op + 1 wide operand + 1 operand | 
|  | 435 | uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); | 
|  | 436 | uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 437 | res = LookupValue(opcode, operand1, operand2, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 438 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
|  | 439 | } | 
|  | 440 | break; | 
|  | 441 |  | 
|  | 442 | case Instruction::ADD_FLOAT: | 
|  | 443 | case Instruction::SUB_FLOAT: | 
|  | 444 | case Instruction::MUL_FLOAT: | 
|  | 445 | case Instruction::DIV_FLOAT: | 
|  | 446 | case Instruction::REM_FLOAT: | 
|  | 447 | case Instruction::ADD_FLOAT_2ADDR: | 
|  | 448 | case Instruction::SUB_FLOAT_2ADDR: | 
|  | 449 | case Instruction::MUL_FLOAT_2ADDR: | 
|  | 450 | case Instruction::DIV_FLOAT_2ADDR: | 
|  | 451 | case Instruction::REM_FLOAT_2ADDR: { | 
|  | 452 | // res = op + 2 operands | 
|  | 453 | uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); | 
|  | 454 | uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 455 | res = LookupValue(opcode, operand1, operand2, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 456 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 457 | } | 
|  | 458 | break; | 
|  | 459 |  | 
|  | 460 | case Instruction::RSUB_INT: | 
|  | 461 | case Instruction::ADD_INT_LIT16: | 
|  | 462 | case Instruction::MUL_INT_LIT16: | 
|  | 463 | case Instruction::DIV_INT_LIT16: | 
|  | 464 | case Instruction::REM_INT_LIT16: | 
|  | 465 | case Instruction::AND_INT_LIT16: | 
|  | 466 | case Instruction::OR_INT_LIT16: | 
|  | 467 | case Instruction::XOR_INT_LIT16: | 
|  | 468 | case Instruction::ADD_INT_LIT8: | 
|  | 469 | case Instruction::RSUB_INT_LIT8: | 
|  | 470 | case Instruction::MUL_INT_LIT8: | 
|  | 471 | case Instruction::DIV_INT_LIT8: | 
|  | 472 | case Instruction::REM_INT_LIT8: | 
|  | 473 | case Instruction::AND_INT_LIT8: | 
|  | 474 | case Instruction::OR_INT_LIT8: | 
|  | 475 | case Instruction::XOR_INT_LIT8: | 
|  | 476 | case Instruction::SHL_INT_LIT8: | 
|  | 477 | case Instruction::SHR_INT_LIT8: | 
|  | 478 | case Instruction::USHR_INT_LIT8: { | 
|  | 479 | // Same as res = op + 2 operands, except use vB as operand 2 | 
|  | 480 | uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); | 
|  | 481 | uint16_t operand2 = LookupValue(Instruction::CONST, mir->dalvikInsn.vB, 0, 0); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 482 | res = LookupValue(opcode, operand1, operand2, NO_VALUE); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 483 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 484 | } | 
|  | 485 | break; | 
|  | 486 |  | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 487 | case Instruction::AGET_OBJECT: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 488 | case Instruction::AGET: | 
|  | 489 | case Instruction::AGET_WIDE: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 490 | case Instruction::AGET_BOOLEAN: | 
|  | 491 | case Instruction::AGET_BYTE: | 
|  | 492 | case Instruction::AGET_CHAR: | 
|  | 493 | case Instruction::AGET_SHORT: { | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 494 | uint16_t type = opcode - Instruction::AGET; | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 495 | uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 496 | HandleNullCheck(mir, array); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 497 | uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 498 | HandleRangeCheck(mir, array, index); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 499 | // Establish value number for loaded register. Note use of memory version. | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 500 | uint16_t memory_version = GetMemoryVersion(array, NO_VALUE, type); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 501 | uint16_t res = LookupValue(ARRAY_REF, array, index, memory_version); | 
|  | 502 | if (opcode == Instruction::AGET_WIDE) { | 
|  | 503 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
|  | 504 | } else { | 
|  | 505 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 506 | } | 
|  | 507 | } | 
|  | 508 | break; | 
|  | 509 |  | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 510 | case Instruction::APUT_OBJECT: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 511 | HandlePutObject(mir); | 
|  | 512 | // Intentional fall-through. | 
|  | 513 | case Instruction::APUT: | 
|  | 514 | case Instruction::APUT_WIDE: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 515 | case Instruction::APUT_BYTE: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 516 | case Instruction::APUT_BOOLEAN: | 
|  | 517 | case Instruction::APUT_SHORT: | 
|  | 518 | case Instruction::APUT_CHAR: { | 
|  | 519 | uint16_t type = opcode - Instruction::APUT; | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 520 | int array_idx = (opcode == Instruction::APUT_WIDE) ? 2 : 1; | 
|  | 521 | int index_idx = array_idx + 1; | 
|  | 522 | uint16_t array = GetOperandValue(mir->ssa_rep->uses[array_idx]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 523 | HandleNullCheck(mir, array); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 524 | uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 525 | HandleRangeCheck(mir, array, index); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 526 | // Rev the memory version | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 527 | AdvanceMemoryVersion(array, NO_VALUE, type); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 528 | } | 
|  | 529 | break; | 
|  | 530 |  | 
|  | 531 | case Instruction::IGET_OBJECT: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 532 | case Instruction::IGET: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 533 | case Instruction::IGET_WIDE: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 534 | case Instruction::IGET_BOOLEAN: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 535 | case Instruction::IGET_BYTE: | 
|  | 536 | case Instruction::IGET_CHAR: | 
|  | 537 | case Instruction::IGET_SHORT: { | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame^] | 538 | uint16_t type = opcode - Instruction::IGET; | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 539 | uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 540 | HandleNullCheck(mir, base); | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame^] | 541 | const MirFieldInfo& field_info = cu_->mir_graph->GetIFieldLoweringInfo(mir); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 542 | uint16_t memory_version; | 
|  | 543 | uint16_t field_id; | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame^] | 544 | if (!field_info.IsResolved() || field_info.IsVolatile()) { | 
|  | 545 | // Volatile fields always get a new memory version; field id is irrelevant. | 
|  | 546 | // Unresolved fields may be volatile, so handle them as such to be safe. | 
|  | 547 | field_id = 0u; | 
|  | 548 | memory_version = next_memory_version_; | 
|  | 549 | ++next_memory_version_; | 
|  | 550 | } else { | 
|  | 551 | DCHECK(field_info.IsResolved()); | 
|  | 552 | field_id = GetFieldId(field_info.DeclaringDexFile(), field_info.DeclaringFieldIndex()); | 
|  | 553 | memory_version = std::max(unresolved_ifield_version_[type], | 
|  | 554 | GetMemoryVersion(base, field_id, type)); | 
|  | 555 | } | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 556 | if (opcode == Instruction::IGET_WIDE) { | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 557 | res = LookupValue(Instruction::IGET_WIDE, base, field_id, memory_version); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 558 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
|  | 559 | } else { | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 560 | res = LookupValue(Instruction::IGET, base, field_id, memory_version); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 561 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 562 | } | 
|  | 563 | } | 
|  | 564 | break; | 
|  | 565 |  | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 566 | case Instruction::IPUT_OBJECT: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 567 | HandlePutObject(mir); | 
|  | 568 | // Intentional fall-through. | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 569 | case Instruction::IPUT: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 570 | case Instruction::IPUT_WIDE: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 571 | case Instruction::IPUT_BOOLEAN: | 
|  | 572 | case Instruction::IPUT_BYTE: | 
|  | 573 | case Instruction::IPUT_CHAR: | 
|  | 574 | case Instruction::IPUT_SHORT: { | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 575 | uint16_t type = opcode - Instruction::IPUT; | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 576 | int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1; | 
|  | 577 | uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 578 | HandleNullCheck(mir, base); | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame^] | 579 | const MirFieldInfo& field_info = cu_->mir_graph->GetIFieldLoweringInfo(mir); | 
|  | 580 | if (!field_info.IsResolved()) { | 
|  | 581 | // Unresolved fields always alias with everything of the same type. | 
|  | 582 | unresolved_ifield_version_[type] = next_memory_version_; | 
|  | 583 | ++next_memory_version_; | 
|  | 584 | } else if (field_info.IsVolatile()) { | 
|  | 585 | // Nothing to do, resolved volatile fields always get a new memory version anyway and | 
|  | 586 | // can't alias with resolved non-volatile fields. | 
|  | 587 | } else { | 
|  | 588 | AdvanceMemoryVersion(base, GetFieldId(field_info.DeclaringDexFile(), | 
|  | 589 | field_info.DeclaringFieldIndex()), type); | 
|  | 590 | } | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 591 | } | 
|  | 592 | break; | 
|  | 593 |  | 
|  | 594 | case Instruction::SGET_OBJECT: | 
|  | 595 | case Instruction::SGET: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 596 | case Instruction::SGET_WIDE: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 597 | case Instruction::SGET_BOOLEAN: | 
|  | 598 | case Instruction::SGET_BYTE: | 
|  | 599 | case Instruction::SGET_CHAR: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 600 | case Instruction::SGET_SHORT: { | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame^] | 601 | uint16_t type = opcode - Instruction::SGET; | 
|  | 602 | const MirFieldInfo& field_info = cu_->mir_graph->GetSFieldLoweringInfo(mir); | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 603 | uint16_t memory_version; | 
|  | 604 | uint16_t field_id; | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame^] | 605 | if (!field_info.IsResolved() || field_info.IsVolatile()) { | 
|  | 606 | // Volatile fields always get a new memory version; field id is irrelevant. | 
|  | 607 | // Unresolved fields may be volatile, so handle them as such to be safe. | 
|  | 608 | field_id = 0u; | 
|  | 609 | memory_version = next_memory_version_; | 
|  | 610 | ++next_memory_version_; | 
|  | 611 | } else { | 
|  | 612 | DCHECK(field_info.IsResolved()); | 
|  | 613 | field_id = GetFieldId(field_info.DeclaringDexFile(), field_info.DeclaringFieldIndex()); | 
|  | 614 | memory_version = std::max(unresolved_sfield_version_[type], | 
|  | 615 | GetMemoryVersion(NO_VALUE, field_id, type)); | 
|  | 616 | } | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 617 | if (opcode == Instruction::SGET_WIDE) { | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 618 | res = LookupValue(Instruction::SGET_WIDE, NO_VALUE, field_id, memory_version); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 619 | SetOperandValueWide(mir->ssa_rep->defs[0], res); | 
|  | 620 | } else { | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 621 | res = LookupValue(Instruction::SGET, NO_VALUE, field_id, memory_version); | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 622 | SetOperandValue(mir->ssa_rep->defs[0], res); | 
|  | 623 | } | 
|  | 624 | } | 
|  | 625 | break; | 
|  | 626 |  | 
|  | 627 | case Instruction::SPUT_OBJECT: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 628 | HandlePutObject(mir); | 
|  | 629 | // Intentional fall-through. | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 630 | case Instruction::SPUT: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 631 | case Instruction::SPUT_WIDE: | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 632 | case Instruction::SPUT_BOOLEAN: | 
|  | 633 | case Instruction::SPUT_BYTE: | 
|  | 634 | case Instruction::SPUT_CHAR: | 
| Vladimir Marko | f59f18b | 2014-02-17 15:53:57 +0000 | [diff] [blame] | 635 | case Instruction::SPUT_SHORT: { | 
|  | 636 | uint16_t type = opcode - Instruction::SPUT; | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame^] | 637 | const MirFieldInfo& field_info = cu_->mir_graph->GetSFieldLoweringInfo(mir); | 
|  | 638 | if (!field_info.IsResolved()) { | 
|  | 639 | // Unresolved fields always alias with everything of the same type. | 
|  | 640 | unresolved_sfield_version_[type] = next_memory_version_; | 
|  | 641 | ++next_memory_version_; | 
|  | 642 | } else if (field_info.IsVolatile()) { | 
|  | 643 | // Nothing to do, resolved volatile fields always get a new memory version anyway and | 
|  | 644 | // can't alias with resolved non-volatile fields. | 
|  | 645 | } else { | 
|  | 646 | AdvanceMemoryVersion(NO_VALUE, GetFieldId(field_info.DeclaringDexFile(), | 
|  | 647 | field_info.DeclaringFieldIndex()), type); | 
|  | 648 | } | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 649 | } | 
|  | 650 | break; | 
| buzbee | 2502e00 | 2012-12-31 16:05:53 -0800 | [diff] [blame] | 651 | } | 
|  | 652 | return res; | 
|  | 653 | } | 
|  | 654 |  | 
|  | 655 | }    // namespace art |