local_value_numbering.cc revision 9820b7c1dc70e75ad405b9e6e63578fa9fe94e94
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#include "local_value_numbering.h" 18 19#include "mir_field_info.h" 20#include "mir_graph.h" 21 22namespace art { 23 24uint16_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 35void LocalValueNumbering::AdvanceGlobalMemory() { 36 // See AdvanceMemoryVersion() for explanation. 37 global_memory_version_ = next_memory_version_; 38 ++next_memory_version_; 39} 40 41uint16_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 62uint16_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 91uint16_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 100void 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 107void 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 118void 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 129void 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} 134 135uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) { 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: 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: 166 case kMirOpFusedCmplFloat: 167 case kMirOpFusedCmpgFloat: 168 case kMirOpFusedCmplDouble: 169 case kMirOpFusedCmpgDouble: 170 case kMirOpFusedCmpLong: 171 // Nothing defined - take no action. 172 break; 173 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 if ((mir->optimization_flags & MIR_INLINED) == 0) { 200 AdvanceGlobalMemory(); 201 MakeArgsAliasing(mir); 202 } 203 break; 204 205 case Instruction::MOVE_RESULT: 206 case Instruction::MOVE_RESULT_OBJECT: 207 case Instruction::INSTANCE_OF: 208 // 1 result, treat as unique each time, use result s_reg - will be unique. 209 res = GetOperandValue(mir->ssa_rep->defs[0]); 210 SetOperandValue(mir->ssa_rep->defs[0], res); 211 break; 212 case Instruction::MOVE_EXCEPTION: 213 case Instruction::NEW_INSTANCE: 214 case Instruction::CONST_STRING: 215 case Instruction::CONST_STRING_JUMBO: 216 case Instruction::CONST_CLASS: 217 case Instruction::NEW_ARRAY: 218 if ((mir->optimization_flags & MIR_INLINED) == 0) { 219 // 1 result, treat as unique each time, use result s_reg - will be unique. 220 res = MarkNonAliasingNonNull(mir); 221 } 222 break; 223 case Instruction::MOVE_RESULT_WIDE: 224 if ((mir->optimization_flags & MIR_INLINED) == 0) { 225 // 1 wide result, treat as unique each time, use result s_reg - will be unique. 226 res = GetOperandValueWide(mir->ssa_rep->defs[0]); 227 SetOperandValueWide(mir->ssa_rep->defs[0], res); 228 } 229 break; 230 231 case kMirOpPhi: 232 /* 233 * Because we'll only see phi nodes at the beginning of an extended basic block, 234 * we can ignore them. Revisit if we shift to global value numbering. 235 */ 236 break; 237 238 case Instruction::MOVE: 239 case Instruction::MOVE_OBJECT: 240 case Instruction::MOVE_16: 241 case Instruction::MOVE_OBJECT_16: 242 case Instruction::MOVE_FROM16: 243 case Instruction::MOVE_OBJECT_FROM16: 244 case kMirOpCopy: 245 // Just copy value number of source to value number of result. 246 res = GetOperandValue(mir->ssa_rep->uses[0]); 247 SetOperandValue(mir->ssa_rep->defs[0], res); 248 break; 249 250 case Instruction::MOVE_WIDE: 251 case Instruction::MOVE_WIDE_16: 252 case Instruction::MOVE_WIDE_FROM16: 253 // Just copy value number of source to value number of result. 254 res = GetOperandValueWide(mir->ssa_rep->uses[0]); 255 SetOperandValueWide(mir->ssa_rep->defs[0], res); 256 break; 257 258 case Instruction::CONST: 259 case Instruction::CONST_4: 260 case Instruction::CONST_16: 261 res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB), 262 High16Bits(mir->dalvikInsn.vB >> 16), 0); 263 SetOperandValue(mir->ssa_rep->defs[0], res); 264 break; 265 266 case Instruction::CONST_HIGH16: 267 res = LookupValue(Instruction::CONST, 0, mir->dalvikInsn.vB, 0); 268 SetOperandValue(mir->ssa_rep->defs[0], res); 269 break; 270 271 case Instruction::CONST_WIDE_16: 272 case Instruction::CONST_WIDE_32: { 273 uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB), 274 High16Bits(mir->dalvikInsn.vB >> 16), 1); 275 uint16_t high_res; 276 if (mir->dalvikInsn.vB & 0x80000000) { 277 high_res = LookupValue(Instruction::CONST, 0xffff, 0xffff, 2); 278 } else { 279 high_res = LookupValue(Instruction::CONST, 0, 0, 2); 280 } 281 res = LookupValue(Instruction::CONST, low_res, high_res, 3); 282 SetOperandValueWide(mir->ssa_rep->defs[0], res); 283 } 284 break; 285 286 case Instruction::CONST_WIDE: { 287 uint32_t low_word = Low32Bits(mir->dalvikInsn.vB_wide); 288 uint32_t high_word = High32Bits(mir->dalvikInsn.vB_wide); 289 uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(low_word), 290 High16Bits(low_word), 1); 291 uint16_t high_res = LookupValue(Instruction::CONST, Low16Bits(high_word), 292 High16Bits(high_word), 2); 293 res = LookupValue(Instruction::CONST, low_res, high_res, 3); 294 SetOperandValueWide(mir->ssa_rep->defs[0], res); 295 } 296 break; 297 298 case Instruction::CONST_WIDE_HIGH16: { 299 uint16_t low_res = LookupValue(Instruction::CONST, 0, 0, 1); 300 uint16_t high_res = LookupValue(Instruction::CONST, 0, Low16Bits(mir->dalvikInsn.vB), 2); 301 res = LookupValue(Instruction::CONST, low_res, high_res, 3); 302 SetOperandValueWide(mir->ssa_rep->defs[0], res); 303 } 304 break; 305 306 case Instruction::ARRAY_LENGTH: 307 case Instruction::NEG_INT: 308 case Instruction::NOT_INT: 309 case Instruction::NEG_FLOAT: 310 case Instruction::INT_TO_BYTE: 311 case Instruction::INT_TO_SHORT: 312 case Instruction::INT_TO_CHAR: 313 case Instruction::INT_TO_FLOAT: 314 case Instruction::FLOAT_TO_INT: { 315 // res = op + 1 operand 316 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); 317 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); 318 SetOperandValue(mir->ssa_rep->defs[0], res); 319 } 320 break; 321 322 case Instruction::LONG_TO_FLOAT: 323 case Instruction::LONG_TO_INT: 324 case Instruction::DOUBLE_TO_FLOAT: 325 case Instruction::DOUBLE_TO_INT: { 326 // res = op + 1 wide operand 327 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); 328 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); 329 SetOperandValue(mir->ssa_rep->defs[0], res); 330 } 331 break; 332 333 334 case Instruction::DOUBLE_TO_LONG: 335 case Instruction::LONG_TO_DOUBLE: 336 case Instruction::NEG_LONG: 337 case Instruction::NOT_LONG: 338 case Instruction::NEG_DOUBLE: { 339 // wide res = op + 1 wide operand 340 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); 341 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); 342 SetOperandValueWide(mir->ssa_rep->defs[0], res); 343 } 344 break; 345 346 case Instruction::FLOAT_TO_DOUBLE: 347 case Instruction::FLOAT_TO_LONG: 348 case Instruction::INT_TO_DOUBLE: 349 case Instruction::INT_TO_LONG: { 350 // wide res = op + 1 operand 351 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); 352 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); 353 SetOperandValueWide(mir->ssa_rep->defs[0], res); 354 } 355 break; 356 357 case Instruction::CMPL_DOUBLE: 358 case Instruction::CMPG_DOUBLE: 359 case Instruction::CMP_LONG: { 360 // res = op + 2 wide operands 361 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); 362 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]); 363 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 364 SetOperandValue(mir->ssa_rep->defs[0], res); 365 } 366 break; 367 368 case Instruction::CMPG_FLOAT: 369 case Instruction::CMPL_FLOAT: 370 case Instruction::ADD_INT: 371 case Instruction::ADD_INT_2ADDR: 372 case Instruction::MUL_INT: 373 case Instruction::MUL_INT_2ADDR: 374 case Instruction::AND_INT: 375 case Instruction::AND_INT_2ADDR: 376 case Instruction::OR_INT: 377 case Instruction::OR_INT_2ADDR: 378 case Instruction::XOR_INT: 379 case Instruction::XOR_INT_2ADDR: 380 case Instruction::SUB_INT: 381 case Instruction::SUB_INT_2ADDR: 382 case Instruction::DIV_INT: 383 case Instruction::DIV_INT_2ADDR: 384 case Instruction::REM_INT: 385 case Instruction::REM_INT_2ADDR: 386 case Instruction::SHL_INT: 387 case Instruction::SHL_INT_2ADDR: 388 case Instruction::SHR_INT: 389 case Instruction::SHR_INT_2ADDR: 390 case Instruction::USHR_INT: 391 case Instruction::USHR_INT_2ADDR: { 392 // res = op + 2 operands 393 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); 394 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]); 395 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 396 SetOperandValue(mir->ssa_rep->defs[0], res); 397 } 398 break; 399 400 case Instruction::ADD_LONG: 401 case Instruction::SUB_LONG: 402 case Instruction::MUL_LONG: 403 case Instruction::DIV_LONG: 404 case Instruction::REM_LONG: 405 case Instruction::AND_LONG: 406 case Instruction::OR_LONG: 407 case Instruction::XOR_LONG: 408 case Instruction::ADD_LONG_2ADDR: 409 case Instruction::SUB_LONG_2ADDR: 410 case Instruction::MUL_LONG_2ADDR: 411 case Instruction::DIV_LONG_2ADDR: 412 case Instruction::REM_LONG_2ADDR: 413 case Instruction::AND_LONG_2ADDR: 414 case Instruction::OR_LONG_2ADDR: 415 case Instruction::XOR_LONG_2ADDR: 416 case Instruction::ADD_DOUBLE: 417 case Instruction::SUB_DOUBLE: 418 case Instruction::MUL_DOUBLE: 419 case Instruction::DIV_DOUBLE: 420 case Instruction::REM_DOUBLE: 421 case Instruction::ADD_DOUBLE_2ADDR: 422 case Instruction::SUB_DOUBLE_2ADDR: 423 case Instruction::MUL_DOUBLE_2ADDR: 424 case Instruction::DIV_DOUBLE_2ADDR: 425 case Instruction::REM_DOUBLE_2ADDR: { 426 // wide res = op + 2 wide operands 427 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); 428 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]); 429 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 430 SetOperandValueWide(mir->ssa_rep->defs[0], res); 431 } 432 break; 433 434 case Instruction::SHL_LONG: 435 case Instruction::SHR_LONG: 436 case Instruction::USHR_LONG: 437 case Instruction::SHL_LONG_2ADDR: 438 case Instruction::SHR_LONG_2ADDR: 439 case Instruction::USHR_LONG_2ADDR: { 440 // wide res = op + 1 wide operand + 1 operand 441 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]); 442 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]); 443 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 444 SetOperandValueWide(mir->ssa_rep->defs[0], res); 445 } 446 break; 447 448 case Instruction::ADD_FLOAT: 449 case Instruction::SUB_FLOAT: 450 case Instruction::MUL_FLOAT: 451 case Instruction::DIV_FLOAT: 452 case Instruction::REM_FLOAT: 453 case Instruction::ADD_FLOAT_2ADDR: 454 case Instruction::SUB_FLOAT_2ADDR: 455 case Instruction::MUL_FLOAT_2ADDR: 456 case Instruction::DIV_FLOAT_2ADDR: 457 case Instruction::REM_FLOAT_2ADDR: { 458 // res = op + 2 operands 459 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); 460 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]); 461 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 462 SetOperandValue(mir->ssa_rep->defs[0], res); 463 } 464 break; 465 466 case Instruction::RSUB_INT: 467 case Instruction::ADD_INT_LIT16: 468 case Instruction::MUL_INT_LIT16: 469 case Instruction::DIV_INT_LIT16: 470 case Instruction::REM_INT_LIT16: 471 case Instruction::AND_INT_LIT16: 472 case Instruction::OR_INT_LIT16: 473 case Instruction::XOR_INT_LIT16: 474 case Instruction::ADD_INT_LIT8: 475 case Instruction::RSUB_INT_LIT8: 476 case Instruction::MUL_INT_LIT8: 477 case Instruction::DIV_INT_LIT8: 478 case Instruction::REM_INT_LIT8: 479 case Instruction::AND_INT_LIT8: 480 case Instruction::OR_INT_LIT8: 481 case Instruction::XOR_INT_LIT8: 482 case Instruction::SHL_INT_LIT8: 483 case Instruction::SHR_INT_LIT8: 484 case Instruction::USHR_INT_LIT8: { 485 // Same as res = op + 2 operands, except use vB as operand 2 486 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]); 487 uint16_t operand2 = LookupValue(Instruction::CONST, mir->dalvikInsn.vB, 0, 0); 488 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 489 SetOperandValue(mir->ssa_rep->defs[0], res); 490 } 491 break; 492 493 case Instruction::AGET_OBJECT: 494 case Instruction::AGET: 495 case Instruction::AGET_WIDE: 496 case Instruction::AGET_BOOLEAN: 497 case Instruction::AGET_BYTE: 498 case Instruction::AGET_CHAR: 499 case Instruction::AGET_SHORT: { 500 uint16_t type = opcode - Instruction::AGET; 501 uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]); 502 HandleNullCheck(mir, array); 503 uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]); 504 HandleRangeCheck(mir, array, index); 505 // Establish value number for loaded register. Note use of memory version. 506 uint16_t memory_version = GetMemoryVersion(array, NO_VALUE, type); 507 uint16_t res = LookupValue(ARRAY_REF, array, index, memory_version); 508 if (opcode == Instruction::AGET_WIDE) { 509 SetOperandValueWide(mir->ssa_rep->defs[0], res); 510 } else { 511 SetOperandValue(mir->ssa_rep->defs[0], res); 512 } 513 } 514 break; 515 516 case Instruction::APUT_OBJECT: 517 HandlePutObject(mir); 518 // Intentional fall-through. 519 case Instruction::APUT: 520 case Instruction::APUT_WIDE: 521 case Instruction::APUT_BYTE: 522 case Instruction::APUT_BOOLEAN: 523 case Instruction::APUT_SHORT: 524 case Instruction::APUT_CHAR: { 525 uint16_t type = opcode - Instruction::APUT; 526 int array_idx = (opcode == Instruction::APUT_WIDE) ? 2 : 1; 527 int index_idx = array_idx + 1; 528 uint16_t array = GetOperandValue(mir->ssa_rep->uses[array_idx]); 529 HandleNullCheck(mir, array); 530 uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]); 531 HandleRangeCheck(mir, array, index); 532 // Rev the memory version 533 AdvanceMemoryVersion(array, NO_VALUE, type); 534 } 535 break; 536 537 case Instruction::IGET_OBJECT: 538 case Instruction::IGET: 539 case Instruction::IGET_WIDE: 540 case Instruction::IGET_BOOLEAN: 541 case Instruction::IGET_BYTE: 542 case Instruction::IGET_CHAR: 543 case Instruction::IGET_SHORT: { 544 uint16_t type = opcode - Instruction::IGET; 545 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]); 546 HandleNullCheck(mir, base); 547 const MirFieldInfo& field_info = cu_->mir_graph->GetIFieldLoweringInfo(mir); 548 uint16_t memory_version; 549 uint16_t field_id; 550 if (!field_info.IsResolved() || field_info.IsVolatile()) { 551 // Volatile fields always get a new memory version; field id is irrelevant. 552 // Unresolved fields may be volatile, so handle them as such to be safe. 553 field_id = 0u; 554 memory_version = next_memory_version_; 555 ++next_memory_version_; 556 } else { 557 DCHECK(field_info.IsResolved()); 558 field_id = GetFieldId(field_info.DeclaringDexFile(), field_info.DeclaringFieldIndex()); 559 memory_version = std::max(unresolved_ifield_version_[type], 560 GetMemoryVersion(base, field_id, type)); 561 } 562 if (opcode == Instruction::IGET_WIDE) { 563 res = LookupValue(Instruction::IGET_WIDE, base, field_id, memory_version); 564 SetOperandValueWide(mir->ssa_rep->defs[0], res); 565 } else { 566 res = LookupValue(Instruction::IGET, base, field_id, memory_version); 567 SetOperandValue(mir->ssa_rep->defs[0], res); 568 } 569 } 570 break; 571 572 case Instruction::IPUT_OBJECT: 573 HandlePutObject(mir); 574 // Intentional fall-through. 575 case Instruction::IPUT: 576 case Instruction::IPUT_WIDE: 577 case Instruction::IPUT_BOOLEAN: 578 case Instruction::IPUT_BYTE: 579 case Instruction::IPUT_CHAR: 580 case Instruction::IPUT_SHORT: { 581 uint16_t type = opcode - Instruction::IPUT; 582 int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1; 583 uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]); 584 HandleNullCheck(mir, base); 585 const MirFieldInfo& field_info = cu_->mir_graph->GetIFieldLoweringInfo(mir); 586 if (!field_info.IsResolved()) { 587 // Unresolved fields always alias with everything of the same type. 588 unresolved_ifield_version_[type] = next_memory_version_; 589 ++next_memory_version_; 590 } else if (field_info.IsVolatile()) { 591 // Nothing to do, resolved volatile fields always get a new memory version anyway and 592 // can't alias with resolved non-volatile fields. 593 } else { 594 AdvanceMemoryVersion(base, GetFieldId(field_info.DeclaringDexFile(), 595 field_info.DeclaringFieldIndex()), type); 596 } 597 } 598 break; 599 600 case Instruction::SGET_OBJECT: 601 case Instruction::SGET: 602 case Instruction::SGET_WIDE: 603 case Instruction::SGET_BOOLEAN: 604 case Instruction::SGET_BYTE: 605 case Instruction::SGET_CHAR: 606 case Instruction::SGET_SHORT: { 607 uint16_t type = opcode - Instruction::SGET; 608 const MirFieldInfo& field_info = cu_->mir_graph->GetSFieldLoweringInfo(mir); 609 uint16_t memory_version; 610 uint16_t field_id; 611 if (!field_info.IsResolved() || field_info.IsVolatile()) { 612 // Volatile fields always get a new memory version; field id is irrelevant. 613 // Unresolved fields may be volatile, so handle them as such to be safe. 614 field_id = 0u; 615 memory_version = next_memory_version_; 616 ++next_memory_version_; 617 } else { 618 DCHECK(field_info.IsResolved()); 619 field_id = GetFieldId(field_info.DeclaringDexFile(), field_info.DeclaringFieldIndex()); 620 memory_version = std::max(unresolved_sfield_version_[type], 621 GetMemoryVersion(NO_VALUE, field_id, type)); 622 } 623 if (opcode == Instruction::SGET_WIDE) { 624 res = LookupValue(Instruction::SGET_WIDE, NO_VALUE, field_id, memory_version); 625 SetOperandValueWide(mir->ssa_rep->defs[0], res); 626 } else { 627 res = LookupValue(Instruction::SGET, NO_VALUE, field_id, memory_version); 628 SetOperandValue(mir->ssa_rep->defs[0], res); 629 } 630 } 631 break; 632 633 case Instruction::SPUT_OBJECT: 634 HandlePutObject(mir); 635 // Intentional fall-through. 636 case Instruction::SPUT: 637 case Instruction::SPUT_WIDE: 638 case Instruction::SPUT_BOOLEAN: 639 case Instruction::SPUT_BYTE: 640 case Instruction::SPUT_CHAR: 641 case Instruction::SPUT_SHORT: { 642 uint16_t type = opcode - Instruction::SPUT; 643 const MirFieldInfo& field_info = cu_->mir_graph->GetSFieldLoweringInfo(mir); 644 if (!field_info.IsResolved()) { 645 // Unresolved fields always alias with everything of the same type. 646 unresolved_sfield_version_[type] = next_memory_version_; 647 ++next_memory_version_; 648 } else if (field_info.IsVolatile()) { 649 // Nothing to do, resolved volatile fields always get a new memory version anyway and 650 // can't alias with resolved non-volatile fields. 651 } else { 652 AdvanceMemoryVersion(NO_VALUE, GetFieldId(field_info.DeclaringDexFile(), 653 field_info.DeclaringFieldIndex()), type); 654 } 655 } 656 break; 657 } 658 return res; 659} 660 661} // namespace art 662