local_value_numbering.cc 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#include "local_value_numbering.h" 18 19#include "mir_annotations.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 AdvanceGlobalMemory(); 200 MakeArgsAliasing(mir); 201 break; 202 203 case Instruction::MOVE_RESULT: 204 case Instruction::MOVE_RESULT_OBJECT: 205 case Instruction::INSTANCE_OF: 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: 211 case Instruction::NEW_INSTANCE: 212 case Instruction::CONST_STRING: 213 case Instruction::CONST_STRING_JUMBO: 214 case Instruction::CONST_CLASS: 215 case Instruction::NEW_ARRAY: 216 // 1 result, treat as unique each time, use result s_reg - will be unique. 217 res = MarkNonAliasingNonNull(mir); 218 break; 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); 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: 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); 242 break; 243 244 case Instruction::MOVE_WIDE: 245 case Instruction::MOVE_WIDE_16: 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); 250 break; 251 252 case Instruction::CONST: 253 case Instruction::CONST_4: 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); 258 break; 259 260 case Instruction::CONST_HIGH16: 261 res = LookupValue(Instruction::CONST, 0, mir->dalvikInsn.vB, 0); 262 SetOperandValue(mir->ssa_rep->defs[0], res); 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 } 275 res = LookupValue(Instruction::CONST, low_res, high_res, 3); 276 SetOperandValueWide(mir->ssa_rep->defs[0], res); 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); 287 res = LookupValue(Instruction::CONST, low_res, high_res, 3); 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); 295 res = LookupValue(Instruction::CONST, low_res, high_res, 3); 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]); 311 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); 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]); 322 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); 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]); 335 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); 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]); 346 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE); 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]); 357 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 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]); 389 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 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]); 423 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 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]); 437 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 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]); 455 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 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); 482 res = LookupValue(opcode, operand1, operand2, NO_VALUE); 483 SetOperandValue(mir->ssa_rep->defs[0], res); 484 } 485 break; 486 487 case Instruction::AGET_OBJECT: 488 case Instruction::AGET: 489 case Instruction::AGET_WIDE: 490 case Instruction::AGET_BOOLEAN: 491 case Instruction::AGET_BYTE: 492 case Instruction::AGET_CHAR: 493 case Instruction::AGET_SHORT: { 494 uint16_t type = opcode - Instruction::AGET; 495 uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]); 496 HandleNullCheck(mir, array); 497 uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]); 498 HandleRangeCheck(mir, array, index); 499 // Establish value number for loaded register. Note use of memory version. 500 uint16_t memory_version = GetMemoryVersion(array, NO_VALUE, type); 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 510 case Instruction::APUT_OBJECT: 511 HandlePutObject(mir); 512 // Intentional fall-through. 513 case Instruction::APUT: 514 case Instruction::APUT_WIDE: 515 case Instruction::APUT_BYTE: 516 case Instruction::APUT_BOOLEAN: 517 case Instruction::APUT_SHORT: 518 case Instruction::APUT_CHAR: { 519 uint16_t type = opcode - Instruction::APUT; 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]); 523 HandleNullCheck(mir, array); 524 uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]); 525 HandleRangeCheck(mir, array, index); 526 // Rev the memory version 527 AdvanceMemoryVersion(array, NO_VALUE, type); 528 } 529 break; 530 531 case Instruction::IGET_OBJECT: 532 case Instruction::IGET: 533 case Instruction::IGET_WIDE: 534 case Instruction::IGET_BOOLEAN: 535 case Instruction::IGET_BYTE: 536 case Instruction::IGET_CHAR: 537 case Instruction::IGET_SHORT: { 538 uint16_t type = opcode - Instruction::IGET; 539 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]); 540 HandleNullCheck(mir, base); 541 const IFieldAnnotation& annotation = cu_->mir_graph->GetIFieldAnnotation(mir); 542 uint16_t memory_version; 543 uint16_t field_id; 544 if (annotation.IsVolatile()) { 545 // Volatile fields always get a new memory version; field id is irrelevant. 546 // Unresolved fields are always marked as volatile and handled the same way here. 547 field_id = 0u; 548 memory_version = next_memory_version_; 549 ++next_memory_version_; 550 } else { 551 DCHECK(annotation.IsResolved()); 552 field_id = GetFieldId(annotation.DeclaringDexFile(), annotation.DeclaringFieldIndex()); 553 memory_version = std::max(unresolved_ifield_version_[type], 554 GetMemoryVersion(base, field_id, type)); 555 } 556 if (opcode == Instruction::IGET_WIDE) { 557 res = LookupValue(Instruction::IGET_WIDE, base, field_id, memory_version); 558 SetOperandValueWide(mir->ssa_rep->defs[0], res); 559 } else { 560 res = LookupValue(Instruction::IGET, base, field_id, memory_version); 561 SetOperandValue(mir->ssa_rep->defs[0], res); 562 } 563 } 564 break; 565 566 case Instruction::IPUT_OBJECT: 567 HandlePutObject(mir); 568 // Intentional fall-through. 569 case Instruction::IPUT: 570 case Instruction::IPUT_WIDE: 571 case Instruction::IPUT_BOOLEAN: 572 case Instruction::IPUT_BYTE: 573 case Instruction::IPUT_CHAR: 574 case Instruction::IPUT_SHORT: { 575 uint16_t type = opcode - Instruction::IPUT; 576 int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1; 577 uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]); 578 HandleNullCheck(mir, base); 579 const IFieldAnnotation& annotation = cu_->mir_graph->GetIFieldAnnotation(mir); 580 if (!annotation.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 (annotation.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(annotation.DeclaringDexFile(), 589 annotation.DeclaringFieldIndex()), type); 590 } 591 } 592 break; 593 594 case Instruction::SGET_OBJECT: 595 case Instruction::SGET: 596 case Instruction::SGET_WIDE: 597 case Instruction::SGET_BOOLEAN: 598 case Instruction::SGET_BYTE: 599 case Instruction::SGET_CHAR: 600 case Instruction::SGET_SHORT: { 601 uint16_t type = opcode - Instruction::SGET; 602 const SFieldAnnotation& annotation = cu_->mir_graph->GetSFieldAnnotation(mir); 603 uint16_t memory_version; 604 uint16_t field_id; 605 if (annotation.IsVolatile()) { 606 // Volatile fields always get a new memory version; field id is irrelevant. 607 // Unresolved fields are always marked as volatile and handled the same way here. 608 field_id = 0u; 609 memory_version = next_memory_version_; 610 ++next_memory_version_; 611 } else { 612 DCHECK(annotation.IsResolved()); 613 field_id = GetFieldId(annotation.DeclaringDexFile(), annotation.DeclaringFieldIndex()); 614 memory_version = std::max(unresolved_sfield_version_[type], 615 GetMemoryVersion(NO_VALUE, field_id, type)); 616 } 617 if (opcode == Instruction::SGET_WIDE) { 618 res = LookupValue(Instruction::SGET_WIDE, NO_VALUE, field_id, memory_version); 619 SetOperandValueWide(mir->ssa_rep->defs[0], res); 620 } else { 621 res = LookupValue(Instruction::SGET, NO_VALUE, field_id, memory_version); 622 SetOperandValue(mir->ssa_rep->defs[0], res); 623 } 624 } 625 break; 626 627 case Instruction::SPUT_OBJECT: 628 HandlePutObject(mir); 629 // Intentional fall-through. 630 case Instruction::SPUT: 631 case Instruction::SPUT_WIDE: 632 case Instruction::SPUT_BOOLEAN: 633 case Instruction::SPUT_BYTE: 634 case Instruction::SPUT_CHAR: 635 case Instruction::SPUT_SHORT: { 636 uint16_t type = opcode - Instruction::SPUT; 637 const SFieldAnnotation& annotation = cu_->mir_graph->GetSFieldAnnotation(mir); 638 if (!annotation.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 (annotation.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(annotation.DeclaringDexFile(), 647 annotation.DeclaringFieldIndex()), type); 648 } 649 } 650 break; 651 } 652 return res; 653} 654 655} // namespace art 656