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 "compiler_internals.h" 18 #include "dataflow_iterator-inl.h" 19 #include "utils/scoped_arena_containers.h" 20 21 #define NOTVISITED (-1) 22 23 namespace art { 24 25 void MIRGraph::ClearAllVisitedFlags() { 26 AllNodesIterator iter(this); 27 for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { 28 bb->visited = false; 29 } 30 } 31 32 BasicBlock* MIRGraph::NeedsVisit(BasicBlock* bb) { 33 if (bb != NULL) { 34 if (bb->visited || bb->hidden) { 35 bb = NULL; 36 } 37 } 38 return bb; 39 } 40 41 BasicBlock* MIRGraph::NextUnvisitedSuccessor(BasicBlock* bb) { 42 BasicBlock* res = NeedsVisit(GetBasicBlock(bb->fall_through)); 43 if (res == NULL) { 44 res = NeedsVisit(GetBasicBlock(bb->taken)); 45 if (res == NULL) { 46 if (bb->successor_block_list_type != kNotUsed) { 47 GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_blocks); 48 while (true) { 49 SuccessorBlockInfo *sbi = iterator.Next(); 50 if (sbi == NULL) { 51 break; 52 } 53 res = NeedsVisit(GetBasicBlock(sbi->block)); 54 if (res != NULL) { 55 break; 56 } 57 } 58 } 59 } 60 } 61 return res; 62 } 63 64 void MIRGraph::MarkPreOrder(BasicBlock* block) { 65 block->visited = true; 66 /* Enqueue the pre_order block id */ 67 if (block->id != NullBasicBlockId) { 68 dfs_order_->Insert(block->id); 69 } 70 } 71 72 void MIRGraph::RecordDFSOrders(BasicBlock* block) { 73 DCHECK(temp_scoped_alloc_.get() != nullptr); 74 ScopedArenaVector<BasicBlock*> succ(temp_scoped_alloc_->Adapter()); 75 MarkPreOrder(block); 76 succ.push_back(block); 77 while (!succ.empty()) { 78 BasicBlock* curr = succ.back(); 79 BasicBlock* next_successor = NextUnvisitedSuccessor(curr); 80 if (next_successor != NULL) { 81 MarkPreOrder(next_successor); 82 succ.push_back(next_successor); 83 continue; 84 } 85 curr->dfs_id = dfs_post_order_->Size(); 86 if (curr->id != NullBasicBlockId) { 87 dfs_post_order_->Insert(curr->id); 88 } 89 succ.pop_back(); 90 } 91 } 92 93 /* Sort the blocks by the Depth-First-Search */ 94 void MIRGraph::ComputeDFSOrders() { 95 /* Initialize or reset the DFS pre_order list */ 96 if (dfs_order_ == NULL) { 97 dfs_order_ = new (arena_) GrowableArray<BasicBlockId>(arena_, GetNumBlocks(), 98 kGrowableArrayDfsOrder); 99 } else { 100 /* Just reset the used length on the counter */ 101 dfs_order_->Reset(); 102 } 103 104 /* Initialize or reset the DFS post_order list */ 105 if (dfs_post_order_ == NULL) { 106 dfs_post_order_ = new (arena_) GrowableArray<BasicBlockId>(arena_, GetNumBlocks(), 107 kGrowableArrayDfsPostOrder); 108 } else { 109 /* Just reset the used length on the counter */ 110 dfs_post_order_->Reset(); 111 } 112 113 // Reset visited flags from all nodes 114 ClearAllVisitedFlags(); 115 116 // Record dfs orders 117 RecordDFSOrders(GetEntryBlock()); 118 119 num_reachable_blocks_ = dfs_order_->Size(); 120 121 if (num_reachable_blocks_ != num_blocks_) { 122 // Hide all unreachable blocks. 123 AllNodesIterator iter(this); 124 for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { 125 if (!bb->visited) { 126 bb->Hide(cu_); 127 } 128 } 129 } 130 } 131 132 /* 133 * Mark block bit on the per-Dalvik register vector to denote that Dalvik 134 * register idx is defined in BasicBlock bb. 135 */ 136 bool MIRGraph::FillDefBlockMatrix(BasicBlock* bb) { 137 if (bb->data_flow_info == NULL) { 138 return false; 139 } 140 141 for (uint32_t idx : bb->data_flow_info->def_v->Indexes()) { 142 /* Block bb defines register idx */ 143 def_block_matrix_[idx]->SetBit(bb->id); 144 } 145 return true; 146 } 147 148 void MIRGraph::ComputeDefBlockMatrix() { 149 int num_registers = cu_->num_dalvik_registers; 150 /* Allocate num_dalvik_registers bit vector pointers */ 151 def_block_matrix_ = static_cast<ArenaBitVector**> 152 (arena_->Alloc(sizeof(ArenaBitVector *) * num_registers, 153 kArenaAllocDFInfo)); 154 int i; 155 156 /* Initialize num_register vectors with num_blocks bits each */ 157 for (i = 0; i < num_registers; i++) { 158 def_block_matrix_[i] = 159 new (arena_) ArenaBitVector(arena_, GetNumBlocks(), false, kBitMapBMatrix); 160 } 161 AllNodesIterator iter(this); 162 for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { 163 FindLocalLiveIn(bb); 164 } 165 AllNodesIterator iter2(this); 166 for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) { 167 FillDefBlockMatrix(bb); 168 } 169 170 /* 171 * Also set the incoming parameters as defs in the entry block. 172 * Only need to handle the parameters for the outer method. 173 */ 174 int num_regs = cu_->num_dalvik_registers; 175 int in_reg = num_regs - cu_->num_ins; 176 for (; in_reg < num_regs; in_reg++) { 177 def_block_matrix_[in_reg]->SetBit(GetEntryBlock()->id); 178 } 179 } 180 181 void MIRGraph::ComputeDomPostOrderTraversal(BasicBlock* bb) { 182 if (dom_post_order_traversal_ == NULL || max_num_reachable_blocks_ < num_reachable_blocks_) { 183 // First time or too small - create the array. 184 dom_post_order_traversal_ = 185 new (arena_) GrowableArray<BasicBlockId>(arena_, num_reachable_blocks_, 186 kGrowableArrayDomPostOrderTraversal); 187 } else { 188 dom_post_order_traversal_->Reset(); 189 } 190 ClearAllVisitedFlags(); 191 DCHECK(temp_scoped_alloc_.get() != nullptr); 192 ScopedArenaVector<std::pair<BasicBlock*, ArenaBitVector::IndexIterator>> work_stack( 193 temp_scoped_alloc_->Adapter()); 194 bb->visited = true; 195 work_stack.push_back(std::make_pair(bb, bb->i_dominated->Indexes().begin())); 196 while (!work_stack.empty()) { 197 std::pair<BasicBlock*, ArenaBitVector::IndexIterator>* curr = &work_stack.back(); 198 BasicBlock* curr_bb = curr->first; 199 ArenaBitVector::IndexIterator* curr_idom_iter = &curr->second; 200 while (!curr_idom_iter->Done() && (NeedsVisit(GetBasicBlock(**curr_idom_iter)) == nullptr)) { 201 ++*curr_idom_iter; 202 } 203 // NOTE: work_stack.push_back()/pop_back() invalidate curr and curr_idom_iter. 204 if (!curr_idom_iter->Done()) { 205 BasicBlock* new_bb = GetBasicBlock(**curr_idom_iter); 206 ++*curr_idom_iter; 207 new_bb->visited = true; 208 work_stack.push_back(std::make_pair(new_bb, new_bb->i_dominated->Indexes().begin())); 209 } else { 210 // no successor/next 211 if (curr_bb->id != NullBasicBlockId) { 212 dom_post_order_traversal_->Insert(curr_bb->id); 213 } 214 work_stack.pop_back(); 215 216 /* hacky loop detection */ 217 if ((curr_bb->taken != NullBasicBlockId) && curr_bb->dominators->IsBitSet(curr_bb->taken)) { 218 curr_bb->nesting_depth++; 219 attributes_ |= METHOD_HAS_LOOP; 220 } 221 } 222 } 223 } 224 225 void MIRGraph::CheckForDominanceFrontier(BasicBlock* dom_bb, 226 const BasicBlock* succ_bb) { 227 /* 228 * TODO - evaluate whether phi will ever need to be inserted into exit 229 * blocks. 230 */ 231 if (succ_bb->i_dom != dom_bb->id && 232 succ_bb->block_type == kDalvikByteCode && 233 succ_bb->hidden == false) { 234 dom_bb->dom_frontier->SetBit(succ_bb->id); 235 } 236 } 237 238 /* Worker function to compute the dominance frontier */ 239 bool MIRGraph::ComputeDominanceFrontier(BasicBlock* bb) { 240 /* Calculate DF_local */ 241 if (bb->taken != NullBasicBlockId) { 242 CheckForDominanceFrontier(bb, GetBasicBlock(bb->taken)); 243 } 244 if (bb->fall_through != NullBasicBlockId) { 245 CheckForDominanceFrontier(bb, GetBasicBlock(bb->fall_through)); 246 } 247 if (bb->successor_block_list_type != kNotUsed) { 248 GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_blocks); 249 while (true) { 250 SuccessorBlockInfo *successor_block_info = iterator.Next(); 251 if (successor_block_info == NULL) { 252 break; 253 } 254 BasicBlock* succ_bb = GetBasicBlock(successor_block_info->block); 255 CheckForDominanceFrontier(bb, succ_bb); 256 } 257 } 258 259 /* Calculate DF_up */ 260 for (uint32_t dominated_idx : bb->i_dominated->Indexes()) { 261 BasicBlock* dominated_bb = GetBasicBlock(dominated_idx); 262 for (uint32_t df_up_block_idx : dominated_bb->dom_frontier->Indexes()) { 263 BasicBlock* df_up_block = GetBasicBlock(df_up_block_idx); 264 CheckForDominanceFrontier(bb, df_up_block); 265 } 266 } 267 268 return true; 269 } 270 271 /* Worker function for initializing domination-related data structures */ 272 void MIRGraph::InitializeDominationInfo(BasicBlock* bb) { 273 int num_total_blocks = GetBasicBlockListCount(); 274 275 if (bb->dominators == NULL) { 276 bb->dominators = new (arena_) ArenaBitVector(arena_, num_total_blocks, 277 false /* expandable */, kBitMapDominators); 278 bb->i_dominated = new (arena_) ArenaBitVector(arena_, num_total_blocks, 279 false /* expandable */, kBitMapIDominated); 280 bb->dom_frontier = new (arena_) ArenaBitVector(arena_, num_total_blocks, 281 false /* expandable */, kBitMapDomFrontier); 282 } else { 283 bb->dominators->ClearAllBits(); 284 bb->i_dominated->ClearAllBits(); 285 bb->dom_frontier->ClearAllBits(); 286 } 287 /* Set all bits in the dominator vector */ 288 bb->dominators->SetInitialBits(num_total_blocks); 289 290 return; 291 } 292 293 /* 294 * Walk through the ordered i_dom list until we reach common parent. 295 * Given the ordering of i_dom_list, this common parent represents the 296 * last element of the intersection of block1 and block2 dominators. 297 */ 298 int MIRGraph::FindCommonParent(int block1, int block2) { 299 while (block1 != block2) { 300 while (block1 < block2) { 301 block1 = i_dom_list_[block1]; 302 DCHECK_NE(block1, NOTVISITED); 303 } 304 while (block2 < block1) { 305 block2 = i_dom_list_[block2]; 306 DCHECK_NE(block2, NOTVISITED); 307 } 308 } 309 return block1; 310 } 311 312 /* Worker function to compute each block's immediate dominator */ 313 bool MIRGraph::ComputeblockIDom(BasicBlock* bb) { 314 /* Special-case entry block */ 315 if ((bb->id == NullBasicBlockId) || (bb == GetEntryBlock())) { 316 return false; 317 } 318 319 /* Iterate through the predecessors */ 320 GrowableArray<BasicBlockId>::Iterator iter(bb->predecessors); 321 322 /* Find the first processed predecessor */ 323 int idom = -1; 324 while (true) { 325 BasicBlock* pred_bb = GetBasicBlock(iter.Next()); 326 CHECK(pred_bb != NULL); 327 if (i_dom_list_[pred_bb->dfs_id] != NOTVISITED) { 328 idom = pred_bb->dfs_id; 329 break; 330 } 331 } 332 333 /* Scan the rest of the predecessors */ 334 while (true) { 335 BasicBlock* pred_bb = GetBasicBlock(iter.Next()); 336 if (!pred_bb) { 337 break; 338 } 339 if (i_dom_list_[pred_bb->dfs_id] == NOTVISITED) { 340 continue; 341 } else { 342 idom = FindCommonParent(pred_bb->dfs_id, idom); 343 } 344 } 345 346 DCHECK_NE(idom, NOTVISITED); 347 348 /* Did something change? */ 349 if (i_dom_list_[bb->dfs_id] != idom) { 350 i_dom_list_[bb->dfs_id] = idom; 351 return true; 352 } 353 return false; 354 } 355 356 /* Worker function to compute each block's domintors */ 357 bool MIRGraph::ComputeBlockDominators(BasicBlock* bb) { 358 if (bb == GetEntryBlock()) { 359 bb->dominators->ClearAllBits(); 360 } else { 361 bb->dominators->Copy(GetBasicBlock(bb->i_dom)->dominators); 362 } 363 bb->dominators->SetBit(bb->id); 364 return false; 365 } 366 367 bool MIRGraph::SetDominators(BasicBlock* bb) { 368 if (bb != GetEntryBlock()) { 369 int idom_dfs_idx = i_dom_list_[bb->dfs_id]; 370 DCHECK_NE(idom_dfs_idx, NOTVISITED); 371 int i_dom_idx = dfs_post_order_->Get(idom_dfs_idx); 372 BasicBlock* i_dom = GetBasicBlock(i_dom_idx); 373 bb->i_dom = i_dom->id; 374 /* Add bb to the i_dominated set of the immediate dominator block */ 375 i_dom->i_dominated->SetBit(bb->id); 376 } 377 return false; 378 } 379 380 /* Compute dominators, immediate dominator, and dominance fronter */ 381 void MIRGraph::ComputeDominators() { 382 int num_reachable_blocks = num_reachable_blocks_; 383 384 /* Initialize domination-related data structures */ 385 PreOrderDfsIterator iter(this); 386 for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { 387 InitializeDominationInfo(bb); 388 } 389 390 /* Initialize & Clear i_dom_list */ 391 if (max_num_reachable_blocks_ < num_reachable_blocks_) { 392 i_dom_list_ = static_cast<int*>(arena_->Alloc(sizeof(int) * num_reachable_blocks, 393 kArenaAllocDFInfo)); 394 } 395 for (int i = 0; i < num_reachable_blocks; i++) { 396 i_dom_list_[i] = NOTVISITED; 397 } 398 399 /* For post-order, last block is entry block. Set its i_dom to istelf */ 400 DCHECK_EQ(GetEntryBlock()->dfs_id, num_reachable_blocks-1); 401 i_dom_list_[GetEntryBlock()->dfs_id] = GetEntryBlock()->dfs_id; 402 403 /* Compute the immediate dominators */ 404 RepeatingReversePostOrderDfsIterator iter2(this); 405 bool change = false; 406 for (BasicBlock* bb = iter2.Next(false); bb != NULL; bb = iter2.Next(change)) { 407 change = ComputeblockIDom(bb); 408 } 409 410 /* Set the dominator for the root node */ 411 GetEntryBlock()->dominators->ClearAllBits(); 412 GetEntryBlock()->dominators->SetBit(GetEntryBlock()->id); 413 414 GetEntryBlock()->i_dom = 0; 415 416 PreOrderDfsIterator iter3(this); 417 for (BasicBlock* bb = iter3.Next(); bb != NULL; bb = iter3.Next()) { 418 SetDominators(bb); 419 } 420 421 ReversePostOrderDfsIterator iter4(this); 422 for (BasicBlock* bb = iter4.Next(); bb != NULL; bb = iter4.Next()) { 423 ComputeBlockDominators(bb); 424 } 425 426 // Compute the dominance frontier for each block. 427 ComputeDomPostOrderTraversal(GetEntryBlock()); 428 PostOrderDOMIterator iter5(this); 429 for (BasicBlock* bb = iter5.Next(); bb != NULL; bb = iter5.Next()) { 430 ComputeDominanceFrontier(bb); 431 } 432 } 433 434 /* 435 * Perform dest U= src1 ^ ~src2 436 * This is probably not general enough to be placed in BitVector.[ch]. 437 */ 438 void MIRGraph::ComputeSuccLineIn(ArenaBitVector* dest, const ArenaBitVector* src1, 439 const ArenaBitVector* src2) { 440 if (dest->GetStorageSize() != src1->GetStorageSize() || 441 dest->GetStorageSize() != src2->GetStorageSize() || 442 dest->IsExpandable() != src1->IsExpandable() || 443 dest->IsExpandable() != src2->IsExpandable()) { 444 LOG(FATAL) << "Incompatible set properties"; 445 } 446 447 unsigned int idx; 448 for (idx = 0; idx < dest->GetStorageSize(); idx++) { 449 dest->GetRawStorage()[idx] |= src1->GetRawStorageWord(idx) & ~(src2->GetRawStorageWord(idx)); 450 } 451 } 452 453 /* 454 * Iterate through all successor blocks and propagate up the live-in sets. 455 * The calculated result is used for phi-node pruning - where we only need to 456 * insert a phi node if the variable is live-in to the block. 457 */ 458 bool MIRGraph::ComputeBlockLiveIns(BasicBlock* bb) { 459 DCHECK_EQ(temp_bit_vector_size_, cu_->num_dalvik_registers); 460 ArenaBitVector* temp_dalvik_register_v = temp_bit_vector_; 461 462 if (bb->data_flow_info == NULL) { 463 return false; 464 } 465 temp_dalvik_register_v->Copy(bb->data_flow_info->live_in_v); 466 BasicBlock* bb_taken = GetBasicBlock(bb->taken); 467 BasicBlock* bb_fall_through = GetBasicBlock(bb->fall_through); 468 if (bb_taken && bb_taken->data_flow_info) 469 ComputeSuccLineIn(temp_dalvik_register_v, bb_taken->data_flow_info->live_in_v, 470 bb->data_flow_info->def_v); 471 if (bb_fall_through && bb_fall_through->data_flow_info) 472 ComputeSuccLineIn(temp_dalvik_register_v, bb_fall_through->data_flow_info->live_in_v, 473 bb->data_flow_info->def_v); 474 if (bb->successor_block_list_type != kNotUsed) { 475 GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_blocks); 476 while (true) { 477 SuccessorBlockInfo *successor_block_info = iterator.Next(); 478 if (successor_block_info == NULL) { 479 break; 480 } 481 BasicBlock* succ_bb = GetBasicBlock(successor_block_info->block); 482 if (succ_bb->data_flow_info) { 483 ComputeSuccLineIn(temp_dalvik_register_v, succ_bb->data_flow_info->live_in_v, 484 bb->data_flow_info->def_v); 485 } 486 } 487 } 488 if (!temp_dalvik_register_v->Equal(bb->data_flow_info->live_in_v)) { 489 bb->data_flow_info->live_in_v->Copy(temp_dalvik_register_v); 490 return true; 491 } 492 return false; 493 } 494 495 /* Insert phi nodes to for each variable to the dominance frontiers */ 496 void MIRGraph::InsertPhiNodes() { 497 int dalvik_reg; 498 ArenaBitVector* phi_blocks = new (temp_scoped_alloc_.get()) ArenaBitVector( 499 temp_scoped_alloc_.get(), GetNumBlocks(), false, kBitMapPhi); 500 ArenaBitVector* input_blocks = new (temp_scoped_alloc_.get()) ArenaBitVector( 501 temp_scoped_alloc_.get(), GetNumBlocks(), false, kBitMapInputBlocks); 502 503 RepeatingPostOrderDfsIterator iter(this); 504 bool change = false; 505 for (BasicBlock* bb = iter.Next(false); bb != NULL; bb = iter.Next(change)) { 506 change = ComputeBlockLiveIns(bb); 507 } 508 509 /* Iterate through each Dalvik register */ 510 for (dalvik_reg = cu_->num_dalvik_registers - 1; dalvik_reg >= 0; dalvik_reg--) { 511 input_blocks->Copy(def_block_matrix_[dalvik_reg]); 512 phi_blocks->ClearAllBits(); 513 do { 514 // TUNING: When we repeat this, we could skip indexes from the previous pass. 515 for (uint32_t idx : input_blocks->Indexes()) { 516 BasicBlock* def_bb = GetBasicBlock(idx); 517 if (def_bb->dom_frontier != nullptr) { 518 phi_blocks->Union(def_bb->dom_frontier); 519 } 520 } 521 } while (input_blocks->Union(phi_blocks)); 522 523 /* 524 * Insert a phi node for dalvik_reg in the phi_blocks if the Dalvik 525 * register is in the live-in set. 526 */ 527 for (uint32_t idx : phi_blocks->Indexes()) { 528 BasicBlock* phi_bb = GetBasicBlock(idx); 529 /* Variable will be clobbered before being used - no need for phi */ 530 if (!phi_bb->data_flow_info->live_in_v->IsBitSet(dalvik_reg)) { 531 continue; 532 } 533 MIR *phi = NewMIR(); 534 phi->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpPhi); 535 phi->dalvikInsn.vA = dalvik_reg; 536 phi->offset = phi_bb->start_offset; 537 phi->m_unit_index = 0; // Arbitrarily assign all Phi nodes to outermost method. 538 phi_bb->PrependMIR(phi); 539 } 540 } 541 } 542 543 /* 544 * Worker function to insert phi-operands with latest SSA names from 545 * predecessor blocks 546 */ 547 bool MIRGraph::InsertPhiNodeOperands(BasicBlock* bb) { 548 /* Phi nodes are at the beginning of each block */ 549 for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { 550 if (mir->dalvikInsn.opcode != static_cast<Instruction::Code>(kMirOpPhi)) 551 return true; 552 int ssa_reg = mir->ssa_rep->defs[0]; 553 DCHECK_GE(ssa_reg, 0); // Shouldn't see compiler temps here 554 int v_reg = SRegToVReg(ssa_reg); 555 556 /* Iterate through the predecessors */ 557 GrowableArray<BasicBlockId>::Iterator iter(bb->predecessors); 558 size_t num_uses = bb->predecessors->Size(); 559 AllocateSSAUseData(mir, num_uses); 560 int* uses = mir->ssa_rep->uses; 561 BasicBlockId* incoming = 562 static_cast<BasicBlockId*>(arena_->Alloc(sizeof(BasicBlockId) * num_uses, 563 kArenaAllocDFInfo)); 564 mir->meta.phi_incoming = incoming; 565 int idx = 0; 566 while (true) { 567 BasicBlock* pred_bb = GetBasicBlock(iter.Next()); 568 if (!pred_bb) { 569 break; 570 } 571 int ssa_reg = pred_bb->data_flow_info->vreg_to_ssa_map_exit[v_reg]; 572 uses[idx] = ssa_reg; 573 incoming[idx] = pred_bb->id; 574 idx++; 575 } 576 } 577 578 return true; 579 } 580 581 void MIRGraph::DoDFSPreOrderSSARename(BasicBlock* block) { 582 if (block->visited || block->hidden) { 583 return; 584 } 585 block->visited = true; 586 587 /* Process this block */ 588 DoSSAConversion(block); 589 int map_size = sizeof(int) * cu_->num_dalvik_registers; 590 591 /* Save SSA map snapshot */ 592 ScopedArenaAllocator allocator(&cu_->arena_stack); 593 int* saved_ssa_map = 594 static_cast<int*>(allocator.Alloc(map_size, kArenaAllocDalvikToSSAMap)); 595 memcpy(saved_ssa_map, vreg_to_ssa_map_, map_size); 596 597 if (block->fall_through != NullBasicBlockId) { 598 DoDFSPreOrderSSARename(GetBasicBlock(block->fall_through)); 599 /* Restore SSA map snapshot */ 600 memcpy(vreg_to_ssa_map_, saved_ssa_map, map_size); 601 } 602 if (block->taken != NullBasicBlockId) { 603 DoDFSPreOrderSSARename(GetBasicBlock(block->taken)); 604 /* Restore SSA map snapshot */ 605 memcpy(vreg_to_ssa_map_, saved_ssa_map, map_size); 606 } 607 if (block->successor_block_list_type != kNotUsed) { 608 GrowableArray<SuccessorBlockInfo*>::Iterator iterator(block->successor_blocks); 609 while (true) { 610 SuccessorBlockInfo *successor_block_info = iterator.Next(); 611 if (successor_block_info == NULL) { 612 break; 613 } 614 BasicBlock* succ_bb = GetBasicBlock(successor_block_info->block); 615 DoDFSPreOrderSSARename(succ_bb); 616 /* Restore SSA map snapshot */ 617 memcpy(vreg_to_ssa_map_, saved_ssa_map, map_size); 618 } 619 } 620 return; 621 } 622 623 } // namespace art 624