1 /* 2 * Copyright (C) 2011 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 "mir_to_lir-inl.h" 18 19 #include "dex/dataflow_iterator-inl.h" 20 #include "dex/quick/dex_file_method_inliner.h" 21 #include "driver/compiler_driver.h" 22 #include "primitive.h" 23 #include "thread-inl.h" 24 25 namespace art { 26 27 class Mir2Lir::SpecialSuspendCheckSlowPath : public Mir2Lir::LIRSlowPath { 28 public: 29 SpecialSuspendCheckSlowPath(Mir2Lir* m2l, LIR* branch, LIR* cont) 30 : LIRSlowPath(m2l, branch, cont), 31 num_used_args_(0u) { 32 } 33 34 void PreserveArg(int in_position) { 35 // Avoid duplicates. 36 for (size_t i = 0; i != num_used_args_; ++i) { 37 if (used_args_[i] == in_position) { 38 return; 39 } 40 } 41 DCHECK_LT(num_used_args_, kMaxArgsToPreserve); 42 used_args_[num_used_args_] = in_position; 43 ++num_used_args_; 44 } 45 46 void Compile() OVERRIDE { 47 m2l_->ResetRegPool(); 48 m2l_->ResetDefTracking(); 49 GenerateTargetLabel(kPseudoSuspendTarget); 50 51 m2l_->LockCallTemps(); 52 53 // Generate frame. 54 m2l_->GenSpecialEntryForSuspend(); 55 56 // Spill all args. 57 for (size_t i = 0, end = m2l_->in_to_reg_storage_mapping_.GetEndMappedIn(); i < end; 58 i += m2l_->in_to_reg_storage_mapping_.GetShorty(i).IsWide() ? 2u : 1u) { 59 m2l_->SpillArg(i); 60 } 61 62 m2l_->FreeCallTemps(); 63 64 // Do the actual suspend call to runtime. 65 m2l_->CallRuntimeHelper(kQuickTestSuspend, true); 66 67 m2l_->LockCallTemps(); 68 69 // Unspill used regs. (Don't unspill unused args.) 70 for (size_t i = 0; i != num_used_args_; ++i) { 71 m2l_->UnspillArg(used_args_[i]); 72 } 73 74 // Pop the frame. 75 m2l_->GenSpecialExitForSuspend(); 76 77 // Branch to the continue label. 78 DCHECK(cont_ != nullptr); 79 m2l_->OpUnconditionalBranch(cont_); 80 81 m2l_->FreeCallTemps(); 82 } 83 84 private: 85 static constexpr size_t kMaxArgsToPreserve = 2u; 86 size_t num_used_args_; 87 int used_args_[kMaxArgsToPreserve]; 88 }; 89 90 RegisterClass Mir2Lir::ShortyToRegClass(char shorty_type) { 91 RegisterClass res; 92 switch (shorty_type) { 93 case 'L': 94 res = kRefReg; 95 break; 96 case 'F': 97 // Expected fallthrough. 98 case 'D': 99 res = kFPReg; 100 break; 101 default: 102 res = kCoreReg; 103 } 104 return res; 105 } 106 107 void Mir2Lir::LockArg(size_t in_position) { 108 RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position); 109 110 if (reg_arg.Valid()) { 111 LockTemp(reg_arg); 112 } 113 } 114 115 RegStorage Mir2Lir::LoadArg(size_t in_position, RegisterClass reg_class, bool wide) { 116 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 117 int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set); 118 119 if (cu_->instruction_set == kX86) { 120 /* 121 * When doing a call for x86, it moves the stack pointer in order to push return. 122 * Thus, we add another 4 bytes to figure out the out of caller (in of callee). 123 */ 124 offset += sizeof(uint32_t); 125 } 126 127 if (cu_->instruction_set == kX86_64) { 128 /* 129 * When doing a call for x86, it moves the stack pointer in order to push return. 130 * Thus, we add another 8 bytes to figure out the out of caller (in of callee). 131 */ 132 offset += sizeof(uint64_t); 133 } 134 135 RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position); 136 137 // TODO: REVISIT: This adds a spill of low part while we could just copy it. 138 if (reg_arg.Valid() && wide && (reg_arg.GetWideKind() == kNotWide)) { 139 // For wide register we've got only half of it. 140 // Flush it to memory then. 141 StoreBaseDisp(TargetPtrReg(kSp), offset, reg_arg, k32, kNotVolatile); 142 reg_arg = RegStorage::InvalidReg(); 143 } 144 145 if (!reg_arg.Valid()) { 146 reg_arg = wide ? AllocTypedTempWide(false, reg_class) : AllocTypedTemp(false, reg_class); 147 LoadBaseDisp(TargetPtrReg(kSp), offset, reg_arg, wide ? k64 : k32, kNotVolatile); 148 } else { 149 // Check if we need to copy the arg to a different reg_class. 150 if (!RegClassMatches(reg_class, reg_arg)) { 151 if (wide) { 152 RegStorage new_reg = AllocTypedTempWide(false, reg_class); 153 OpRegCopyWide(new_reg, reg_arg); 154 reg_arg = new_reg; 155 } else { 156 RegStorage new_reg = AllocTypedTemp(false, reg_class); 157 OpRegCopy(new_reg, reg_arg); 158 reg_arg = new_reg; 159 } 160 } 161 } 162 return reg_arg; 163 } 164 165 void Mir2Lir::LoadArgDirect(size_t in_position, RegLocation rl_dest) { 166 DCHECK_EQ(rl_dest.location, kLocPhysReg); 167 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 168 int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set); 169 if (cu_->instruction_set == kX86) { 170 /* 171 * When doing a call for x86, it moves the stack pointer in order to push return. 172 * Thus, we add another 4 bytes to figure out the out of caller (in of callee). 173 */ 174 offset += sizeof(uint32_t); 175 } 176 177 if (cu_->instruction_set == kX86_64) { 178 /* 179 * When doing a call for x86, it moves the stack pointer in order to push return. 180 * Thus, we add another 8 bytes to figure out the out of caller (in of callee). 181 */ 182 offset += sizeof(uint64_t); 183 } 184 185 RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position); 186 187 // TODO: REVISIT: This adds a spill of low part while we could just copy it. 188 if (reg_arg.Valid() && rl_dest.wide && (reg_arg.GetWideKind() == kNotWide)) { 189 // For wide register we've got only half of it. 190 // Flush it to memory then. 191 StoreBaseDisp(TargetPtrReg(kSp), offset, reg_arg, k32, kNotVolatile); 192 reg_arg = RegStorage::InvalidReg(); 193 } 194 195 if (!reg_arg.Valid()) { 196 OpSize op_size = rl_dest.wide ? k64 : (rl_dest.ref ? kReference : k32); 197 LoadBaseDisp(TargetPtrReg(kSp), offset, rl_dest.reg, op_size, kNotVolatile); 198 } else { 199 if (rl_dest.wide) { 200 OpRegCopyWide(rl_dest.reg, reg_arg); 201 } else { 202 OpRegCopy(rl_dest.reg, reg_arg); 203 } 204 } 205 } 206 207 void Mir2Lir::SpillArg(size_t in_position) { 208 RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position); 209 210 if (reg_arg.Valid()) { 211 int offset = frame_size_ + StackVisitor::GetOutVROffset(in_position, cu_->instruction_set); 212 ShortyArg arg = in_to_reg_storage_mapping_.GetShorty(in_position); 213 OpSize size = arg.IsRef() ? kReference : 214 (arg.IsWide() && reg_arg.GetWideKind() == kWide) ? k64 : k32; 215 StoreBaseDisp(TargetPtrReg(kSp), offset, reg_arg, size, kNotVolatile); 216 } 217 } 218 219 void Mir2Lir::UnspillArg(size_t in_position) { 220 RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position); 221 222 if (reg_arg.Valid()) { 223 int offset = frame_size_ + StackVisitor::GetOutVROffset(in_position, cu_->instruction_set); 224 ShortyArg arg = in_to_reg_storage_mapping_.GetShorty(in_position); 225 OpSize size = arg.IsRef() ? kReference : 226 (arg.IsWide() && reg_arg.GetWideKind() == kWide) ? k64 : k32; 227 LoadBaseDisp(TargetPtrReg(kSp), offset, reg_arg, size, kNotVolatile); 228 } 229 } 230 231 Mir2Lir::SpecialSuspendCheckSlowPath* Mir2Lir::GenSpecialSuspendTest() { 232 LockCallTemps(); 233 LIR* branch = OpTestSuspend(nullptr); 234 FreeCallTemps(); 235 LIR* cont = NewLIR0(kPseudoTargetLabel); 236 SpecialSuspendCheckSlowPath* slow_path = 237 new (arena_) SpecialSuspendCheckSlowPath(this, branch, cont); 238 AddSlowPath(slow_path); 239 return slow_path; 240 } 241 242 bool Mir2Lir::GenSpecialIGet(MIR* mir, const InlineMethod& special) { 243 // FastInstance() already checked by DexFileMethodInliner. 244 const InlineIGetIPutData& data = special.d.ifield_data; 245 if (data.method_is_static != 0u || data.object_arg != 0u) { 246 // The object is not "this" and has to be null-checked. 247 return false; 248 } 249 250 OpSize size; 251 switch (data.op_variant) { 252 case InlineMethodAnalyser::IGetVariant(Instruction::IGET): 253 size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kSingle : k32; 254 break; 255 case InlineMethodAnalyser::IGetVariant(Instruction::IGET_WIDE): 256 size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kDouble : k64; 257 break; 258 case InlineMethodAnalyser::IGetVariant(Instruction::IGET_OBJECT): 259 size = kReference; 260 break; 261 case InlineMethodAnalyser::IGetVariant(Instruction::IGET_SHORT): 262 size = kSignedHalf; 263 break; 264 case InlineMethodAnalyser::IGetVariant(Instruction::IGET_CHAR): 265 size = kUnsignedHalf; 266 break; 267 case InlineMethodAnalyser::IGetVariant(Instruction::IGET_BYTE): 268 size = kSignedByte; 269 break; 270 case InlineMethodAnalyser::IGetVariant(Instruction::IGET_BOOLEAN): 271 size = kUnsignedByte; 272 break; 273 default: 274 LOG(FATAL) << "Unknown variant: " << data.op_variant; 275 UNREACHABLE(); 276 } 277 278 // Point of no return - no aborts after this 279 if (!kLeafOptimization) { 280 auto* slow_path = GenSpecialSuspendTest(); 281 slow_path->PreserveArg(data.object_arg); 282 } 283 LockArg(data.object_arg); 284 GenPrintLabel(mir); 285 RegStorage reg_obj = LoadArg(data.object_arg, kRefReg); 286 RegisterClass reg_class = RegClassForFieldLoadStore(size, data.is_volatile); 287 RegisterClass ret_reg_class = ShortyToRegClass(cu_->shorty[0]); 288 RegLocation rl_dest = IsWide(size) ? GetReturnWide(ret_reg_class) : GetReturn(ret_reg_class); 289 RegStorage r_result = rl_dest.reg; 290 if (!RegClassMatches(reg_class, r_result)) { 291 r_result = IsWide(size) ? AllocTypedTempWide(rl_dest.fp, reg_class) 292 : AllocTypedTemp(rl_dest.fp, reg_class); 293 } 294 if (IsRef(size)) { 295 LoadRefDisp(reg_obj, data.field_offset, r_result, data.is_volatile ? kVolatile : kNotVolatile); 296 } else { 297 LoadBaseDisp(reg_obj, data.field_offset, r_result, size, data.is_volatile ? kVolatile : 298 kNotVolatile); 299 } 300 if (r_result.NotExactlyEquals(rl_dest.reg)) { 301 if (IsWide(size)) { 302 OpRegCopyWide(rl_dest.reg, r_result); 303 } else { 304 OpRegCopy(rl_dest.reg, r_result); 305 } 306 } 307 return true; 308 } 309 310 bool Mir2Lir::GenSpecialIPut(MIR* mir, const InlineMethod& special) { 311 // FastInstance() already checked by DexFileMethodInliner. 312 const InlineIGetIPutData& data = special.d.ifield_data; 313 if (data.method_is_static != 0u || data.object_arg != 0u) { 314 // The object is not "this" and has to be null-checked. 315 return false; 316 } 317 if (data.return_arg_plus1 != 0u) { 318 // The setter returns a method argument which we don't support here. 319 return false; 320 } 321 322 OpSize size; 323 switch (data.op_variant) { 324 case InlineMethodAnalyser::IPutVariant(Instruction::IPUT): 325 size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kSingle : k32; 326 break; 327 case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_WIDE): 328 size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kDouble : k64; 329 break; 330 case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_OBJECT): 331 size = kReference; 332 break; 333 case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT): 334 size = kSignedHalf; 335 break; 336 case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_CHAR): 337 size = kUnsignedHalf; 338 break; 339 case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BYTE): 340 size = kSignedByte; 341 break; 342 case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BOOLEAN): 343 size = kUnsignedByte; 344 break; 345 default: 346 LOG(FATAL) << "Unknown variant: " << data.op_variant; 347 UNREACHABLE(); 348 } 349 350 // Point of no return - no aborts after this 351 if (!kLeafOptimization) { 352 auto* slow_path = GenSpecialSuspendTest(); 353 slow_path->PreserveArg(data.object_arg); 354 slow_path->PreserveArg(data.src_arg); 355 } 356 LockArg(data.object_arg); 357 LockArg(data.src_arg); 358 GenPrintLabel(mir); 359 RegStorage reg_obj = LoadArg(data.object_arg, kRefReg); 360 RegisterClass reg_class = RegClassForFieldLoadStore(size, data.is_volatile); 361 RegStorage reg_src = LoadArg(data.src_arg, reg_class, IsWide(size)); 362 if (IsRef(size)) { 363 StoreRefDisp(reg_obj, data.field_offset, reg_src, data.is_volatile ? kVolatile : kNotVolatile); 364 } else { 365 StoreBaseDisp(reg_obj, data.field_offset, reg_src, size, data.is_volatile ? kVolatile : 366 kNotVolatile); 367 } 368 if (IsRef(size)) { 369 MarkGCCard(0, reg_src, reg_obj); 370 } 371 return true; 372 } 373 374 bool Mir2Lir::GenSpecialIdentity(MIR* mir, const InlineMethod& special) { 375 const InlineReturnArgData& data = special.d.return_data; 376 bool wide = (data.is_wide != 0u); 377 378 // Point of no return - no aborts after this 379 if (!kLeafOptimization) { 380 auto* slow_path = GenSpecialSuspendTest(); 381 slow_path->PreserveArg(data.arg); 382 } 383 LockArg(data.arg); 384 GenPrintLabel(mir); 385 RegisterClass reg_class = ShortyToRegClass(cu_->shorty[0]); 386 RegLocation rl_dest = wide ? GetReturnWide(reg_class) : GetReturn(reg_class); 387 LoadArgDirect(data.arg, rl_dest); 388 return true; 389 } 390 391 /* 392 * Special-case code generation for simple non-throwing leaf methods. 393 */ 394 bool Mir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special) { 395 DCHECK(special.flags & kInlineSpecial); 396 current_dalvik_offset_ = mir->offset; 397 DCHECK(current_mir_ == nullptr); // Safepoints attributed to prologue. 398 MIR* return_mir = nullptr; 399 bool successful = false; 400 EnsureInitializedArgMappingToPhysicalReg(); 401 402 switch (special.opcode) { 403 case kInlineOpNop: 404 successful = true; 405 DCHECK_EQ(mir->dalvikInsn.opcode, Instruction::RETURN_VOID); 406 if (!kLeafOptimization) { 407 GenSpecialSuspendTest(); 408 } 409 return_mir = mir; 410 break; 411 case kInlineOpNonWideConst: { 412 successful = true; 413 if (!kLeafOptimization) { 414 GenSpecialSuspendTest(); 415 } 416 RegLocation rl_dest = GetReturn(ShortyToRegClass(cu_->shorty[0])); 417 GenPrintLabel(mir); 418 LoadConstant(rl_dest.reg, static_cast<int>(special.d.data)); 419 return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir); 420 break; 421 } 422 case kInlineOpReturnArg: 423 successful = GenSpecialIdentity(mir, special); 424 return_mir = mir; 425 break; 426 case kInlineOpIGet: 427 successful = GenSpecialIGet(mir, special); 428 return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir); 429 break; 430 case kInlineOpIPut: 431 successful = GenSpecialIPut(mir, special); 432 return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir); 433 break; 434 default: 435 break; 436 } 437 438 if (successful) { 439 if (kIsDebugBuild) { 440 // Clear unreachable catch entries. 441 mir_graph_->catches_.clear(); 442 } 443 444 // Handle verbosity for return MIR. 445 if (return_mir != nullptr) { 446 current_dalvik_offset_ = return_mir->offset; 447 // Not handling special identity case because it already generated code as part 448 // of the return. The label should have been added before any code was generated. 449 if (special.opcode != kInlineOpReturnArg) { 450 GenPrintLabel(return_mir); 451 } 452 } 453 GenSpecialExitSequence(); 454 455 if (!kLeafOptimization) { 456 HandleSlowPaths(); 457 } else { 458 core_spill_mask_ = 0; 459 num_core_spills_ = 0; 460 fp_spill_mask_ = 0; 461 num_fp_spills_ = 0; 462 frame_size_ = 0; 463 core_vmap_table_.clear(); 464 fp_vmap_table_.clear(); 465 } 466 } 467 468 return successful; 469 } 470 471 /* 472 * Target-independent code generation. Use only high-level 473 * load/store utilities here, or target-dependent genXX() handlers 474 * when necessary. 475 */ 476 void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list) { 477 RegLocation rl_src[3]; 478 RegLocation rl_dest = mir_graph_->GetBadLoc(); 479 RegLocation rl_result = mir_graph_->GetBadLoc(); 480 const Instruction::Code opcode = mir->dalvikInsn.opcode; 481 const int opt_flags = mir->optimization_flags; 482 const uint32_t vB = mir->dalvikInsn.vB; 483 const uint32_t vC = mir->dalvikInsn.vC; 484 DCHECK(CheckCorePoolSanity()) << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " @ 0x:" 485 << std::hex << current_dalvik_offset_; 486 487 // Prep Src and Dest locations. 488 int next_sreg = 0; 489 int next_loc = 0; 490 uint64_t attrs = MIRGraph::GetDataFlowAttributes(opcode); 491 rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc(); 492 if (attrs & DF_UA) { 493 if (attrs & DF_A_WIDE) { 494 rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg); 495 next_sreg+= 2; 496 } else { 497 rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg); 498 next_sreg++; 499 } 500 } 501 if (attrs & DF_UB) { 502 if (attrs & DF_B_WIDE) { 503 rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg); 504 next_sreg+= 2; 505 } else { 506 rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg); 507 next_sreg++; 508 } 509 } 510 if (attrs & DF_UC) { 511 if (attrs & DF_C_WIDE) { 512 rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg); 513 } else { 514 rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg); 515 } 516 } 517 if (attrs & DF_DA) { 518 if (attrs & DF_A_WIDE) { 519 rl_dest = mir_graph_->GetDestWide(mir); 520 } else { 521 rl_dest = mir_graph_->GetDest(mir); 522 } 523 } 524 switch (opcode) { 525 case Instruction::NOP: 526 break; 527 528 case Instruction::MOVE_EXCEPTION: 529 GenMoveException(rl_dest); 530 break; 531 532 case Instruction::RETURN_VOID_NO_BARRIER: 533 case Instruction::RETURN_VOID: 534 if (((cu_->access_flags & kAccConstructor) != 0) && 535 cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(), cu_->dex_file, 536 cu_->class_def_idx)) { 537 GenMemBarrier(kStoreStore); 538 } 539 if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) { 540 GenSuspendTest(opt_flags); 541 } 542 break; 543 544 case Instruction::RETURN_OBJECT: 545 DCHECK(rl_src[0].ref); 546 FALLTHROUGH_INTENDED; 547 case Instruction::RETURN: 548 if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) { 549 GenSuspendTest(opt_flags); 550 } 551 StoreValue(GetReturn(ShortyToRegClass(cu_->shorty[0])), rl_src[0]); 552 break; 553 554 case Instruction::RETURN_WIDE: 555 if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) { 556 GenSuspendTest(opt_flags); 557 } 558 StoreValueWide(GetReturnWide(ShortyToRegClass(cu_->shorty[0])), rl_src[0]); 559 break; 560 561 case Instruction::MOVE_RESULT: 562 case Instruction::MOVE_RESULT_WIDE: 563 case Instruction::MOVE_RESULT_OBJECT: 564 // Already processed with invoke or filled-new-array. 565 break; 566 567 case Instruction::MOVE: 568 case Instruction::MOVE_OBJECT: 569 case Instruction::MOVE_16: 570 case Instruction::MOVE_OBJECT_16: 571 case Instruction::MOVE_FROM16: 572 case Instruction::MOVE_OBJECT_FROM16: 573 StoreValue(rl_dest, rl_src[0]); 574 break; 575 576 case Instruction::MOVE_WIDE: 577 case Instruction::MOVE_WIDE_16: 578 case Instruction::MOVE_WIDE_FROM16: 579 StoreValueWide(rl_dest, rl_src[0]); 580 break; 581 582 case Instruction::CONST: 583 case Instruction::CONST_4: 584 case Instruction::CONST_16: 585 GenConst(rl_dest, vB); 586 break; 587 588 case Instruction::CONST_HIGH16: 589 GenConst(rl_dest, vB << 16); 590 break; 591 592 case Instruction::CONST_WIDE_16: 593 case Instruction::CONST_WIDE_32: 594 GenConstWide(rl_dest, static_cast<int64_t>(static_cast<int32_t>(vB))); 595 break; 596 597 case Instruction::CONST_WIDE: 598 GenConstWide(rl_dest, mir->dalvikInsn.vB_wide); 599 break; 600 601 case Instruction::CONST_WIDE_HIGH16: 602 rl_result = EvalLoc(rl_dest, kAnyReg, true); 603 LoadConstantWide(rl_result.reg, static_cast<int64_t>(vB) << 48); 604 StoreValueWide(rl_dest, rl_result); 605 break; 606 607 case Instruction::MONITOR_ENTER: 608 GenMonitorEnter(opt_flags, rl_src[0]); 609 break; 610 611 case Instruction::MONITOR_EXIT: 612 GenMonitorExit(opt_flags, rl_src[0]); 613 break; 614 615 case Instruction::CHECK_CAST: { 616 GenCheckCast(opt_flags, mir->offset, vB, rl_src[0]); 617 break; 618 } 619 case Instruction::INSTANCE_OF: 620 GenInstanceof(vC, rl_dest, rl_src[0]); 621 break; 622 623 case Instruction::NEW_INSTANCE: 624 GenNewInstance(vB, rl_dest); 625 break; 626 627 case Instruction::THROW: 628 GenThrow(rl_src[0]); 629 break; 630 631 case Instruction::ARRAY_LENGTH: { 632 int len_offset; 633 len_offset = mirror::Array::LengthOffset().Int32Value(); 634 rl_src[0] = LoadValue(rl_src[0], kRefReg); 635 GenNullCheck(rl_src[0].reg, opt_flags); 636 rl_result = EvalLoc(rl_dest, kCoreReg, true); 637 Load32Disp(rl_src[0].reg, len_offset, rl_result.reg); 638 MarkPossibleNullPointerException(opt_flags); 639 StoreValue(rl_dest, rl_result); 640 break; 641 } 642 case Instruction::CONST_STRING: 643 case Instruction::CONST_STRING_JUMBO: 644 GenConstString(vB, rl_dest); 645 break; 646 647 case Instruction::CONST_CLASS: 648 GenConstClass(vB, rl_dest); 649 break; 650 651 case Instruction::FILL_ARRAY_DATA: 652 GenFillArrayData(mir, vB, rl_src[0]); 653 break; 654 655 case Instruction::FILLED_NEW_ARRAY: 656 GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic, 657 false /* not range */)); 658 break; 659 660 case Instruction::FILLED_NEW_ARRAY_RANGE: 661 GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic, 662 true /* range */)); 663 break; 664 665 case Instruction::NEW_ARRAY: 666 GenNewArray(vC, rl_dest, rl_src[0]); 667 break; 668 669 case Instruction::GOTO: 670 case Instruction::GOTO_16: 671 case Instruction::GOTO_32: 672 if (mir_graph_->IsBackEdge(bb, bb->taken)) { 673 GenSuspendTestAndBranch(opt_flags, &label_list[bb->taken]); 674 } else { 675 OpUnconditionalBranch(&label_list[bb->taken]); 676 } 677 break; 678 679 case Instruction::PACKED_SWITCH: 680 GenPackedSwitch(mir, vB, rl_src[0]); 681 break; 682 683 case Instruction::SPARSE_SWITCH: 684 GenSparseSwitch(mir, vB, rl_src[0]); 685 break; 686 687 case Instruction::CMPL_FLOAT: 688 case Instruction::CMPG_FLOAT: 689 case Instruction::CMPL_DOUBLE: 690 case Instruction::CMPG_DOUBLE: 691 GenCmpFP(opcode, rl_dest, rl_src[0], rl_src[1]); 692 break; 693 694 case Instruction::CMP_LONG: 695 GenCmpLong(rl_dest, rl_src[0], rl_src[1]); 696 break; 697 698 case Instruction::IF_EQ: 699 case Instruction::IF_NE: 700 case Instruction::IF_LT: 701 case Instruction::IF_GE: 702 case Instruction::IF_GT: 703 case Instruction::IF_LE: { 704 if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) { 705 GenSuspendTest(opt_flags); 706 } 707 LIR* taken = &label_list[bb->taken]; 708 GenCompareAndBranch(opcode, rl_src[0], rl_src[1], taken); 709 break; 710 } 711 case Instruction::IF_EQZ: 712 case Instruction::IF_NEZ: 713 case Instruction::IF_LTZ: 714 case Instruction::IF_GEZ: 715 case Instruction::IF_GTZ: 716 case Instruction::IF_LEZ: { 717 if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) { 718 GenSuspendTest(opt_flags); 719 } 720 LIR* taken = &label_list[bb->taken]; 721 GenCompareZeroAndBranch(opcode, rl_src[0], taken); 722 break; 723 } 724 725 case Instruction::AGET_WIDE: 726 GenArrayGet(opt_flags, rl_dest.fp ? kDouble : k64, rl_src[0], rl_src[1], rl_dest, 3); 727 break; 728 case Instruction::AGET_OBJECT: 729 GenArrayGet(opt_flags, kReference, rl_src[0], rl_src[1], rl_dest, 2); 730 break; 731 case Instruction::AGET: 732 GenArrayGet(opt_flags, rl_dest.fp ? kSingle : k32, rl_src[0], rl_src[1], rl_dest, 2); 733 break; 734 case Instruction::AGET_BOOLEAN: 735 GenArrayGet(opt_flags, kUnsignedByte, rl_src[0], rl_src[1], rl_dest, 0); 736 break; 737 case Instruction::AGET_BYTE: 738 GenArrayGet(opt_flags, kSignedByte, rl_src[0], rl_src[1], rl_dest, 0); 739 break; 740 case Instruction::AGET_CHAR: 741 GenArrayGet(opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], rl_dest, 1); 742 break; 743 case Instruction::AGET_SHORT: 744 GenArrayGet(opt_flags, kSignedHalf, rl_src[0], rl_src[1], rl_dest, 1); 745 break; 746 case Instruction::APUT_WIDE: 747 GenArrayPut(opt_flags, rl_src[0].fp ? kDouble : k64, rl_src[1], rl_src[2], rl_src[0], 3, false); 748 break; 749 case Instruction::APUT: 750 GenArrayPut(opt_flags, rl_src[0].fp ? kSingle : k32, rl_src[1], rl_src[2], rl_src[0], 2, false); 751 break; 752 case Instruction::APUT_OBJECT: { 753 bool is_null = mir_graph_->IsConstantNullRef(rl_src[0]); 754 bool is_safe = is_null; // Always safe to store null. 755 if (!is_safe) { 756 // Check safety from verifier type information. 757 const DexCompilationUnit* unit = mir_graph_->GetCurrentDexCompilationUnit(); 758 is_safe = cu_->compiler_driver->IsSafeCast(unit, mir->offset); 759 } 760 if (is_null || is_safe) { 761 // Store of constant null doesn't require an assignability test and can be generated inline 762 // without fixed register usage or a card mark. 763 GenArrayPut(opt_flags, kReference, rl_src[1], rl_src[2], rl_src[0], 2, !is_null); 764 } else { 765 GenArrayObjPut(opt_flags, rl_src[1], rl_src[2], rl_src[0]); 766 } 767 break; 768 } 769 case Instruction::APUT_SHORT: 770 case Instruction::APUT_CHAR: 771 GenArrayPut(opt_flags, kUnsignedHalf, rl_src[1], rl_src[2], rl_src[0], 1, false); 772 break; 773 case Instruction::APUT_BYTE: 774 case Instruction::APUT_BOOLEAN: 775 GenArrayPut(opt_flags, kUnsignedByte, rl_src[1], rl_src[2], rl_src[0], 0, false); 776 break; 777 778 case Instruction::IGET_OBJECT_QUICK: 779 case Instruction::IGET_OBJECT: 780 GenIGet(mir, opt_flags, kReference, Primitive::kPrimNot, rl_dest, rl_src[0]); 781 break; 782 783 case Instruction::IGET_WIDE_QUICK: 784 case Instruction::IGET_WIDE: 785 // kPrimLong and kPrimDouble share the same entrypoints. 786 if (rl_dest.fp) { 787 GenIGet(mir, opt_flags, kDouble, Primitive::kPrimDouble, rl_dest, rl_src[0]); 788 } else { 789 GenIGet(mir, opt_flags, k64, Primitive::kPrimLong, rl_dest, rl_src[0]); 790 } 791 break; 792 793 case Instruction::IGET_QUICK: 794 case Instruction::IGET: 795 if (rl_dest.fp) { 796 GenIGet(mir, opt_flags, kSingle, Primitive::kPrimFloat, rl_dest, rl_src[0]); 797 } else { 798 GenIGet(mir, opt_flags, k32, Primitive::kPrimInt, rl_dest, rl_src[0]); 799 } 800 break; 801 802 case Instruction::IGET_CHAR_QUICK: 803 case Instruction::IGET_CHAR: 804 GenIGet(mir, opt_flags, kUnsignedHalf, Primitive::kPrimChar, rl_dest, rl_src[0]); 805 break; 806 807 case Instruction::IGET_SHORT_QUICK: 808 case Instruction::IGET_SHORT: 809 GenIGet(mir, opt_flags, kSignedHalf, Primitive::kPrimShort, rl_dest, rl_src[0]); 810 break; 811 812 case Instruction::IGET_BOOLEAN_QUICK: 813 case Instruction::IGET_BOOLEAN: 814 GenIGet(mir, opt_flags, kUnsignedByte, Primitive::kPrimBoolean, rl_dest, rl_src[0]); 815 break; 816 817 case Instruction::IGET_BYTE_QUICK: 818 case Instruction::IGET_BYTE: 819 GenIGet(mir, opt_flags, kSignedByte, Primitive::kPrimByte, rl_dest, rl_src[0]); 820 break; 821 822 case Instruction::IPUT_WIDE_QUICK: 823 case Instruction::IPUT_WIDE: 824 GenIPut(mir, opt_flags, rl_src[0].fp ? kDouble : k64, rl_src[0], rl_src[1]); 825 break; 826 827 case Instruction::IPUT_OBJECT_QUICK: 828 case Instruction::IPUT_OBJECT: 829 GenIPut(mir, opt_flags, kReference, rl_src[0], rl_src[1]); 830 break; 831 832 case Instruction::IPUT_QUICK: 833 case Instruction::IPUT: 834 GenIPut(mir, opt_flags, rl_src[0].fp ? kSingle : k32, rl_src[0], rl_src[1]); 835 break; 836 837 case Instruction::IPUT_BYTE_QUICK: 838 case Instruction::IPUT_BOOLEAN_QUICK: 839 case Instruction::IPUT_BYTE: 840 case Instruction::IPUT_BOOLEAN: 841 GenIPut(mir, opt_flags, kUnsignedByte, rl_src[0], rl_src[1]); 842 break; 843 844 case Instruction::IPUT_CHAR_QUICK: 845 case Instruction::IPUT_CHAR: 846 GenIPut(mir, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1]); 847 break; 848 849 case Instruction::IPUT_SHORT_QUICK: 850 case Instruction::IPUT_SHORT: 851 GenIPut(mir, opt_flags, kSignedHalf, rl_src[0], rl_src[1]); 852 break; 853 854 case Instruction::SGET_OBJECT: 855 GenSget(mir, rl_dest, kReference, Primitive::kPrimNot); 856 break; 857 858 case Instruction::SGET: 859 GenSget(mir, rl_dest, rl_dest.fp ? kSingle : k32, Primitive::kPrimInt); 860 break; 861 862 case Instruction::SGET_CHAR: 863 GenSget(mir, rl_dest, kUnsignedHalf, Primitive::kPrimChar); 864 break; 865 866 case Instruction::SGET_SHORT: 867 GenSget(mir, rl_dest, kSignedHalf, Primitive::kPrimShort); 868 break; 869 870 case Instruction::SGET_BOOLEAN: 871 GenSget(mir, rl_dest, kUnsignedByte, Primitive::kPrimBoolean); 872 break; 873 874 case Instruction::SGET_BYTE: 875 GenSget(mir, rl_dest, kSignedByte, Primitive::kPrimByte); 876 break; 877 878 case Instruction::SGET_WIDE: 879 // kPrimLong and kPrimDouble share the same entrypoints. 880 GenSget(mir, rl_dest, rl_dest.fp ? kDouble : k64, Primitive::kPrimDouble); 881 break; 882 883 case Instruction::SPUT_OBJECT: 884 GenSput(mir, rl_src[0], kReference); 885 break; 886 887 case Instruction::SPUT: 888 GenSput(mir, rl_src[0], rl_src[0].fp ? kSingle : k32); 889 break; 890 891 case Instruction::SPUT_BYTE: 892 case Instruction::SPUT_BOOLEAN: 893 GenSput(mir, rl_src[0], kUnsignedByte); 894 break; 895 896 case Instruction::SPUT_CHAR: 897 GenSput(mir, rl_src[0], kUnsignedHalf); 898 break; 899 900 case Instruction::SPUT_SHORT: 901 GenSput(mir, rl_src[0], kSignedHalf); 902 break; 903 904 905 case Instruction::SPUT_WIDE: 906 GenSput(mir, rl_src[0], rl_src[0].fp ? kDouble : k64); 907 break; 908 909 case Instruction::INVOKE_STATIC_RANGE: 910 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, true)); 911 break; 912 case Instruction::INVOKE_STATIC: 913 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, false)); 914 break; 915 916 case Instruction::INVOKE_DIRECT: 917 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, false)); 918 break; 919 case Instruction::INVOKE_DIRECT_RANGE: 920 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, true)); 921 break; 922 923 case Instruction::INVOKE_VIRTUAL_QUICK: 924 case Instruction::INVOKE_VIRTUAL: 925 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, false)); 926 break; 927 928 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: 929 case Instruction::INVOKE_VIRTUAL_RANGE: 930 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, true)); 931 break; 932 933 case Instruction::INVOKE_SUPER: 934 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, false)); 935 break; 936 case Instruction::INVOKE_SUPER_RANGE: 937 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, true)); 938 break; 939 940 case Instruction::INVOKE_INTERFACE: 941 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, false)); 942 break; 943 case Instruction::INVOKE_INTERFACE_RANGE: 944 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, true)); 945 break; 946 947 case Instruction::NEG_INT: 948 case Instruction::NOT_INT: 949 GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[0], opt_flags); 950 break; 951 952 case Instruction::NEG_LONG: 953 case Instruction::NOT_LONG: 954 GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[0], opt_flags); 955 break; 956 957 case Instruction::NEG_FLOAT: 958 GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[0]); 959 break; 960 961 case Instruction::NEG_DOUBLE: 962 GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[0]); 963 break; 964 965 case Instruction::INT_TO_LONG: 966 GenIntToLong(rl_dest, rl_src[0]); 967 break; 968 969 case Instruction::LONG_TO_INT: 970 GenLongToInt(rl_dest, rl_src[0]); 971 break; 972 973 case Instruction::INT_TO_BYTE: 974 case Instruction::INT_TO_SHORT: 975 case Instruction::INT_TO_CHAR: 976 GenIntNarrowing(opcode, rl_dest, rl_src[0]); 977 break; 978 979 case Instruction::INT_TO_FLOAT: 980 case Instruction::INT_TO_DOUBLE: 981 case Instruction::LONG_TO_FLOAT: 982 case Instruction::LONG_TO_DOUBLE: 983 case Instruction::FLOAT_TO_INT: 984 case Instruction::FLOAT_TO_LONG: 985 case Instruction::FLOAT_TO_DOUBLE: 986 case Instruction::DOUBLE_TO_INT: 987 case Instruction::DOUBLE_TO_LONG: 988 case Instruction::DOUBLE_TO_FLOAT: 989 GenConversion(opcode, rl_dest, rl_src[0]); 990 break; 991 992 993 case Instruction::ADD_INT: 994 case Instruction::ADD_INT_2ADDR: 995 case Instruction::MUL_INT: 996 case Instruction::MUL_INT_2ADDR: 997 case Instruction::AND_INT: 998 case Instruction::AND_INT_2ADDR: 999 case Instruction::OR_INT: 1000 case Instruction::OR_INT_2ADDR: 1001 case Instruction::XOR_INT: 1002 case Instruction::XOR_INT_2ADDR: 1003 if (rl_src[0].is_const && 1004 InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[0]), opcode)) { 1005 GenArithOpIntLit(opcode, rl_dest, rl_src[1], 1006 mir_graph_->ConstantValue(rl_src[0].orig_sreg)); 1007 } else if (rl_src[1].is_const && 1008 InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]), opcode)) { 1009 GenArithOpIntLit(opcode, rl_dest, rl_src[0], 1010 mir_graph_->ConstantValue(rl_src[1].orig_sreg)); 1011 } else { 1012 GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); 1013 } 1014 break; 1015 1016 case Instruction::SUB_INT: 1017 case Instruction::SUB_INT_2ADDR: 1018 case Instruction::DIV_INT: 1019 case Instruction::DIV_INT_2ADDR: 1020 case Instruction::REM_INT: 1021 case Instruction::REM_INT_2ADDR: 1022 case Instruction::SHL_INT: 1023 case Instruction::SHL_INT_2ADDR: 1024 case Instruction::SHR_INT: 1025 case Instruction::SHR_INT_2ADDR: 1026 case Instruction::USHR_INT: 1027 case Instruction::USHR_INT_2ADDR: 1028 if (rl_src[1].is_const && 1029 InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]), opcode)) { 1030 GenArithOpIntLit(opcode, rl_dest, rl_src[0], mir_graph_->ConstantValue(rl_src[1])); 1031 } else { 1032 GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); 1033 } 1034 break; 1035 1036 case Instruction::ADD_LONG: 1037 case Instruction::SUB_LONG: 1038 case Instruction::AND_LONG: 1039 case Instruction::OR_LONG: 1040 case Instruction::XOR_LONG: 1041 case Instruction::ADD_LONG_2ADDR: 1042 case Instruction::SUB_LONG_2ADDR: 1043 case Instruction::AND_LONG_2ADDR: 1044 case Instruction::OR_LONG_2ADDR: 1045 case Instruction::XOR_LONG_2ADDR: 1046 if (rl_src[0].is_const || rl_src[1].is_const) { 1047 GenArithImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); 1048 break; 1049 } 1050 FALLTHROUGH_INTENDED; 1051 case Instruction::MUL_LONG: 1052 case Instruction::DIV_LONG: 1053 case Instruction::REM_LONG: 1054 case Instruction::MUL_LONG_2ADDR: 1055 case Instruction::DIV_LONG_2ADDR: 1056 case Instruction::REM_LONG_2ADDR: 1057 GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); 1058 break; 1059 1060 case Instruction::SHL_LONG: 1061 case Instruction::SHR_LONG: 1062 case Instruction::USHR_LONG: 1063 case Instruction::SHL_LONG_2ADDR: 1064 case Instruction::SHR_LONG_2ADDR: 1065 case Instruction::USHR_LONG_2ADDR: 1066 if (rl_src[1].is_const) { 1067 GenShiftImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); 1068 } else { 1069 GenShiftOpLong(opcode, rl_dest, rl_src[0], rl_src[1]); 1070 } 1071 break; 1072 1073 case Instruction::DIV_FLOAT: 1074 case Instruction::DIV_FLOAT_2ADDR: 1075 if (HandleEasyFloatingPointDiv(rl_dest, rl_src[0], rl_src[1])) { 1076 break; 1077 } 1078 FALLTHROUGH_INTENDED; 1079 case Instruction::ADD_FLOAT: 1080 case Instruction::SUB_FLOAT: 1081 case Instruction::MUL_FLOAT: 1082 case Instruction::REM_FLOAT: 1083 case Instruction::ADD_FLOAT_2ADDR: 1084 case Instruction::SUB_FLOAT_2ADDR: 1085 case Instruction::MUL_FLOAT_2ADDR: 1086 case Instruction::REM_FLOAT_2ADDR: 1087 GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[1]); 1088 break; 1089 1090 case Instruction::DIV_DOUBLE: 1091 case Instruction::DIV_DOUBLE_2ADDR: 1092 if (HandleEasyFloatingPointDiv(rl_dest, rl_src[0], rl_src[1])) { 1093 break; 1094 } 1095 FALLTHROUGH_INTENDED; 1096 case Instruction::ADD_DOUBLE: 1097 case Instruction::SUB_DOUBLE: 1098 case Instruction::MUL_DOUBLE: 1099 case Instruction::REM_DOUBLE: 1100 case Instruction::ADD_DOUBLE_2ADDR: 1101 case Instruction::SUB_DOUBLE_2ADDR: 1102 case Instruction::MUL_DOUBLE_2ADDR: 1103 case Instruction::REM_DOUBLE_2ADDR: 1104 GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[1]); 1105 break; 1106 1107 case Instruction::RSUB_INT: 1108 case Instruction::ADD_INT_LIT16: 1109 case Instruction::MUL_INT_LIT16: 1110 case Instruction::DIV_INT_LIT16: 1111 case Instruction::REM_INT_LIT16: 1112 case Instruction::AND_INT_LIT16: 1113 case Instruction::OR_INT_LIT16: 1114 case Instruction::XOR_INT_LIT16: 1115 case Instruction::ADD_INT_LIT8: 1116 case Instruction::RSUB_INT_LIT8: 1117 case Instruction::MUL_INT_LIT8: 1118 case Instruction::DIV_INT_LIT8: 1119 case Instruction::REM_INT_LIT8: 1120 case Instruction::AND_INT_LIT8: 1121 case Instruction::OR_INT_LIT8: 1122 case Instruction::XOR_INT_LIT8: 1123 case Instruction::SHL_INT_LIT8: 1124 case Instruction::SHR_INT_LIT8: 1125 case Instruction::USHR_INT_LIT8: 1126 GenArithOpIntLit(opcode, rl_dest, rl_src[0], vC); 1127 break; 1128 1129 default: 1130 LOG(FATAL) << "Unexpected opcode: " << opcode; 1131 } 1132 DCHECK(CheckCorePoolSanity()); 1133 } // NOLINT(readability/fn_size) 1134 1135 // Process extended MIR instructions 1136 void Mir2Lir::HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir) { 1137 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 1138 case kMirOpCopy: { 1139 RegLocation rl_src = mir_graph_->GetSrc(mir, 0); 1140 RegLocation rl_dest = mir_graph_->GetDest(mir); 1141 StoreValue(rl_dest, rl_src); 1142 break; 1143 } 1144 case kMirOpFusedCmplFloat: 1145 if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) { 1146 GenSuspendTest(mir->optimization_flags); 1147 } 1148 GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, false /*double*/); 1149 break; 1150 case kMirOpFusedCmpgFloat: 1151 if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) { 1152 GenSuspendTest(mir->optimization_flags); 1153 } 1154 GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, false /*double*/); 1155 break; 1156 case kMirOpFusedCmplDouble: 1157 if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) { 1158 GenSuspendTest(mir->optimization_flags); 1159 } 1160 GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, true /*double*/); 1161 break; 1162 case kMirOpFusedCmpgDouble: 1163 if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) { 1164 GenSuspendTest(mir->optimization_flags); 1165 } 1166 GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, true /*double*/); 1167 break; 1168 case kMirOpFusedCmpLong: 1169 if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) { 1170 GenSuspendTest(mir->optimization_flags); 1171 } 1172 GenFusedLongCmpBranch(bb, mir); 1173 break; 1174 case kMirOpSelect: 1175 GenSelect(bb, mir); 1176 break; 1177 case kMirOpNullCheck: { 1178 RegLocation rl_obj = mir_graph_->GetSrc(mir, 0); 1179 rl_obj = LoadValue(rl_obj, kRefReg); 1180 // An explicit check is done because it is not expected that when this is used, 1181 // that it will actually trip up the implicit checks (since an invalid access 1182 // is needed on the null object). 1183 GenExplicitNullCheck(rl_obj.reg, mir->optimization_flags); 1184 break; 1185 } 1186 case kMirOpPhi: 1187 case kMirOpNop: 1188 case kMirOpRangeCheck: 1189 case kMirOpDivZeroCheck: 1190 case kMirOpCheck: 1191 // Ignore these known opcodes 1192 break; 1193 default: 1194 // Give the backends a chance to handle unknown extended MIR opcodes. 1195 GenMachineSpecificExtendedMethodMIR(bb, mir); 1196 break; 1197 } 1198 } 1199 1200 void Mir2Lir::GenPrintLabel(MIR* mir) { 1201 // Mark the beginning of a Dalvik instruction for line tracking. 1202 if (cu_->verbose) { 1203 char* inst_str = mir_graph_->GetDalvikDisassembly(mir); 1204 MarkBoundary(mir->offset, inst_str); 1205 } 1206 } 1207 1208 // Handle the content in each basic block. 1209 bool Mir2Lir::MethodBlockCodeGen(BasicBlock* bb) { 1210 if (bb->block_type == kDead) return false; 1211 current_dalvik_offset_ = bb->start_offset; 1212 MIR* mir; 1213 int block_id = bb->id; 1214 1215 block_label_list_[block_id].operands[0] = bb->start_offset; 1216 1217 // Insert the block label. 1218 block_label_list_[block_id].opcode = kPseudoNormalBlockLabel; 1219 block_label_list_[block_id].flags.fixup = kFixupLabel; 1220 AppendLIR(&block_label_list_[block_id]); 1221 1222 LIR* head_lir = nullptr; 1223 1224 // If this is a catch block, export the start address. 1225 if (bb->catch_entry) { 1226 head_lir = NewLIR0(kPseudoExportedPC); 1227 } 1228 1229 // Free temp registers and reset redundant store tracking. 1230 ClobberAllTemps(); 1231 1232 if (bb->block_type == kEntryBlock) { 1233 ResetRegPool(); 1234 int start_vreg = mir_graph_->GetFirstInVR(); 1235 AppendLIR(NewLIR0(kPseudoPrologueBegin)); 1236 DCHECK_EQ(cu_->target64, Is64BitInstructionSet(cu_->instruction_set)); 1237 if (cu_->target64) { 1238 DCHECK(mir_graph_->GetMethodLoc().wide); 1239 } 1240 GenEntrySequence(&mir_graph_->reg_location_[start_vreg], mir_graph_->GetMethodLoc()); 1241 AppendLIR(NewLIR0(kPseudoPrologueEnd)); 1242 DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_); 1243 } else if (bb->block_type == kExitBlock) { 1244 ResetRegPool(); 1245 DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_); 1246 AppendLIR(NewLIR0(kPseudoEpilogueBegin)); 1247 GenExitSequence(); 1248 AppendLIR(NewLIR0(kPseudoEpilogueEnd)); 1249 DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_); 1250 } 1251 1252 for (mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) { 1253 ResetRegPool(); 1254 if (cu_->disable_opt & (1 << kTrackLiveTemps)) { 1255 ClobberAllTemps(); 1256 // Reset temp allocation to minimize differences when A/B testing. 1257 reg_pool_->ResetNextTemp(); 1258 } 1259 1260 if (cu_->disable_opt & (1 << kSuppressLoads)) { 1261 ResetDefTracking(); 1262 } 1263 1264 // Reset temp tracking sanity check. 1265 if (kIsDebugBuild) { 1266 live_sreg_ = INVALID_SREG; 1267 } 1268 1269 current_dalvik_offset_ = mir->offset; 1270 current_mir_ = mir; 1271 int opcode = mir->dalvikInsn.opcode; 1272 1273 GenPrintLabel(mir); 1274 1275 // Remember the first LIR for this block. 1276 if (head_lir == nullptr) { 1277 head_lir = &block_label_list_[bb->id]; 1278 // Set the first label as a scheduling barrier. 1279 DCHECK(!head_lir->flags.use_def_invalid); 1280 head_lir->u.m.def_mask = &kEncodeAll; 1281 } 1282 1283 if (MIR::DecodedInstruction::IsPseudoMirOp(opcode)) { 1284 HandleExtendedMethodMIR(bb, mir); 1285 continue; 1286 } 1287 1288 CompileDalvikInstruction(mir, bb, block_label_list_); 1289 } 1290 1291 if (head_lir) { 1292 // Eliminate redundant loads/stores and delay stores into later slots. 1293 ApplyLocalOptimizations(head_lir, last_lir_insn_); 1294 } 1295 return false; 1296 } 1297 1298 bool Mir2Lir::SpecialMIR2LIR(const InlineMethod& special) { 1299 cu_->NewTimingSplit("SpecialMIR2LIR"); 1300 // Find the first DalvikByteCode block. 1301 DCHECK_EQ(mir_graph_->GetNumReachableBlocks(), mir_graph_->GetDfsOrder().size()); 1302 BasicBlock*bb = nullptr; 1303 for (BasicBlockId dfs_id : mir_graph_->GetDfsOrder()) { 1304 BasicBlock* candidate = mir_graph_->GetBasicBlock(dfs_id); 1305 if (candidate->block_type == kDalvikByteCode) { 1306 bb = candidate; 1307 break; 1308 } 1309 } 1310 if (bb == nullptr) { 1311 return false; 1312 } 1313 DCHECK_EQ(bb->start_offset, 0); 1314 DCHECK(bb->first_mir_insn != nullptr); 1315 1316 // Get the first instruction. 1317 MIR* mir = bb->first_mir_insn; 1318 1319 // Free temp registers and reset redundant store tracking. 1320 ResetRegPool(); 1321 ResetDefTracking(); 1322 ClobberAllTemps(); 1323 1324 return GenSpecialCase(bb, mir, special); 1325 } 1326 1327 void Mir2Lir::MethodMIR2LIR() { 1328 cu_->NewTimingSplit("MIR2LIR"); 1329 1330 // Hold the labels of each block. 1331 block_label_list_ = arena_->AllocArray<LIR>(mir_graph_->GetNumBlocks(), kArenaAllocLIR); 1332 1333 PreOrderDfsIterator iter(mir_graph_); 1334 BasicBlock* curr_bb = iter.Next(); 1335 BasicBlock* next_bb = iter.Next(); 1336 while (curr_bb != nullptr) { 1337 MethodBlockCodeGen(curr_bb); 1338 // If the fall_through block is no longer laid out consecutively, drop in a branch. 1339 BasicBlock* curr_bb_fall_through = mir_graph_->GetBasicBlock(curr_bb->fall_through); 1340 if ((curr_bb_fall_through != nullptr) && (curr_bb_fall_through != next_bb)) { 1341 OpUnconditionalBranch(&block_label_list_[curr_bb->fall_through]); 1342 } 1343 curr_bb = next_bb; 1344 do { 1345 next_bb = iter.Next(); 1346 } while ((next_bb != nullptr) && (next_bb->block_type == kDead)); 1347 } 1348 HandleSlowPaths(); 1349 } 1350 1351 // 1352 // LIR Slow Path 1353 // 1354 1355 LIR* Mir2Lir::LIRSlowPath::GenerateTargetLabel(int opcode) { 1356 m2l_->SetCurrentDexPc(current_dex_pc_); 1357 m2l_->current_mir_ = current_mir_; 1358 LIR* target = m2l_->NewLIR0(opcode); 1359 fromfast_->target = target; 1360 return target; 1361 } 1362 1363 1364 void Mir2Lir::CheckRegStorageImpl(RegStorage rs, WidenessCheck wide, RefCheck ref, FPCheck fp, 1365 bool fail, bool report) 1366 const { 1367 if (rs.Valid()) { 1368 if (ref == RefCheck::kCheckRef) { 1369 if (cu_->target64 && !rs.Is64Bit()) { 1370 if (fail) { 1371 CHECK(false) << "Reg storage not 64b for ref."; 1372 } else if (report) { 1373 LOG(WARNING) << "Reg storage not 64b for ref."; 1374 } 1375 } 1376 } 1377 if (wide == WidenessCheck::kCheckWide) { 1378 if (!rs.Is64Bit()) { 1379 if (fail) { 1380 CHECK(false) << "Reg storage not 64b for wide."; 1381 } else if (report) { 1382 LOG(WARNING) << "Reg storage not 64b for wide."; 1383 } 1384 } 1385 } 1386 // A tighter check would be nice, but for now soft-float will not check float at all. 1387 if (fp == FPCheck::kCheckFP && cu_->instruction_set != kArm) { 1388 if (!rs.IsFloat()) { 1389 if (fail) { 1390 CHECK(false) << "Reg storage not float for fp."; 1391 } else if (report) { 1392 LOG(WARNING) << "Reg storage not float for fp."; 1393 } 1394 } 1395 } else if (fp == FPCheck::kCheckNotFP) { 1396 if (rs.IsFloat()) { 1397 if (fail) { 1398 CHECK(false) << "Reg storage float for not-fp."; 1399 } else if (report) { 1400 LOG(WARNING) << "Reg storage float for not-fp."; 1401 } 1402 } 1403 } 1404 } 1405 } 1406 1407 void Mir2Lir::CheckRegLocationImpl(RegLocation rl, bool fail, bool report) const { 1408 // Regrettably can't use the fp part of rl, as that is not really indicative of where a value 1409 // will be stored. 1410 CheckRegStorageImpl(rl.reg, rl.wide ? WidenessCheck::kCheckWide : WidenessCheck::kCheckNotWide, 1411 rl.ref ? RefCheck::kCheckRef : RefCheck::kCheckNotRef, FPCheck::kIgnoreFP, fail, report); 1412 } 1413 1414 size_t Mir2Lir::GetInstructionOffset(LIR* lir) { 1415 UNUSED(lir); 1416 UNIMPLEMENTED(FATAL) << "Unsupported GetInstructionOffset()"; 1417 UNREACHABLE(); 1418 } 1419 1420 void Mir2Lir::InToRegStorageMapping::Initialize(ShortyIterator* shorty, 1421 InToRegStorageMapper* mapper) { 1422 DCHECK(mapper != nullptr); 1423 DCHECK(shorty != nullptr); 1424 DCHECK(!IsInitialized()); 1425 DCHECK_EQ(end_mapped_in_, 0u); 1426 DCHECK(!has_arguments_on_stack_); 1427 while (shorty->Next()) { 1428 ShortyArg arg = shorty->GetArg(); 1429 RegStorage reg = mapper->GetNextReg(arg); 1430 mapping_.emplace_back(arg, reg); 1431 if (arg.IsWide()) { 1432 mapping_.emplace_back(ShortyArg(kInvalidShorty), RegStorage::InvalidReg()); 1433 } 1434 if (reg.Valid()) { 1435 end_mapped_in_ = mapping_.size(); 1436 // If the VR is wide but wasn't mapped as wide then account for it. 1437 if (arg.IsWide() && !reg.Is64Bit()) { 1438 --end_mapped_in_; 1439 } 1440 } else { 1441 has_arguments_on_stack_ = true; 1442 } 1443 } 1444 initialized_ = true; 1445 } 1446 1447 RegStorage Mir2Lir::InToRegStorageMapping::GetReg(size_t in_position) { 1448 DCHECK(IsInitialized()); 1449 DCHECK_LT(in_position, mapping_.size()); 1450 DCHECK_NE(mapping_[in_position].first.GetType(), kInvalidShorty); 1451 return mapping_[in_position].second; 1452 } 1453 1454 Mir2Lir::ShortyArg Mir2Lir::InToRegStorageMapping::GetShorty(size_t in_position) { 1455 DCHECK(IsInitialized()); 1456 DCHECK_LT(static_cast<size_t>(in_position), mapping_.size()); 1457 DCHECK_NE(mapping_[in_position].first.GetType(), kInvalidShorty); 1458 return mapping_[in_position].first; 1459 } 1460 1461 } // namespace art 1462