SsaMethod.java revision f6c387128427e121477c1b32ad35cdcaa5101ba3
1/* 2 * Copyright (C) 2007 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 17package com.android.dx.ssa; 18 19import com.android.dx.rop.code.BasicBlockList; 20import com.android.dx.rop.code.PlainInsn; 21import com.android.dx.rop.code.RegisterSpec; 22import com.android.dx.rop.code.RegisterSpecList; 23import com.android.dx.rop.code.RopMethod; 24import com.android.dx.rop.code.Rops; 25import com.android.dx.rop.code.SourcePosition; 26import com.android.dx.rop.code.Insn; 27import com.android.dx.rop.code.RegOps; 28import com.android.dx.rop.code.Rop; 29import com.android.dx.util.IntList; 30 31import java.util.ArrayList; 32import java.util.BitSet; 33import java.util.Collections; 34import java.util.List; 35import java.util.Stack; 36import java.util.Set; 37 38/** 39 * A method in SSA form 40 */ 41public final class SsaMethod { 42 43 /** basic blocks, indexed by block index */ 44 private ArrayList<SsaBasicBlock> blocks; 45 46 /** Index of first executed block in method */ 47 private int entryBlockIndex; 48 49 /** 50 * Index of exit block, which exists only in SSA form, 51 * or or -1 if there is none 52 */ 53 private int exitBlockIndex; 54 55 private int registerCount; 56 private int spareRegisterBase; 57 private int borrowedSpareRegisters; 58 59 /** really one greater than the max label */ 60 private int maxLabel; 61 62 /** the total width, in register-units, of the method's parameters */ 63 private final int paramWidth; 64 65 /** true if this method has no 'this' pointer argument */ 66 private final boolean isStatic; 67 68 /** 69 * indexed by register: the insn where said register is defined or null 70 * if undefined. null until (lazily) created. 71 */ 72 private SsaInsn[] definitionList; 73 74 /** indexed by register: the list of all insns that use a register */ 75 private ArrayList<SsaInsn>[] useList; 76 /** A version of useList with each List unmodifiable */ 77 private List<SsaInsn>[] unmodifiableUseList; 78 79 /** 80 * "back-convert mode". Set during back-conversion when registers 81 * are about to be mapped into a non-SSA namespace. When true, 82 * use and def lists are unavailable. 83 * 84 * TODO remove this mode, plase the functionality elsewhere 85 */ 86 private boolean backMode = false; 87 88 /** 89 * @param rmeth RopMethod to convert from 90 * @param paramWidth the total width, in register-units, of the 91 * method's parameters 92 * @param isStatic true if this method has no 'this' pointer argument 93 * @return SsaMethod representation 94 */ 95 static SsaMethod newFromRopMethod(RopMethod rmeth, int paramWidth, 96 boolean isStatic) { 97 SsaMethod result; 98 99 result = new SsaMethod(paramWidth, isStatic); 100 101 result.maxLabel = rmeth.getBlocks().getMaxLabel(); 102 result.registerCount = rmeth.getBlocks().getRegCount(); 103 result.spareRegisterBase = result.registerCount; 104 105 result.convertRopToSsaBlocks(rmeth); 106 107 return result; 108 } 109 110 /** 111 * Builds a BitSet of block indices from a basic block list and a list 112 * of labels taken from Rop form 113 * @param blocks Rop blocks 114 * @param labelList list of rop block labels 115 * @return BitSet of block indices 116 */ 117 static BitSet bitSetFromLabelList(BasicBlockList blocks, 118 IntList labelList) { 119 120 BitSet result; 121 122 result = new BitSet(blocks.size()); 123 124 for (int i = 0, sz = labelList.size() ; i < sz ; i++) { 125 result.set(blocks.indexOfLabel(labelList.get(i))); 126 } 127 128 return result; 129 } 130 131 /** 132 * Builds an IntList of block indices from a basic block list and a list 133 * of labels taken from Rop form 134 * @param ropBlocks Rop blocks 135 * @param labelList list of rop block labels 136 * @return IntList of block indices 137 */ 138 public static IntList indexListFromLabelList(BasicBlockList ropBlocks, 139 IntList labelList) { 140 141 IntList result; 142 143 result = new IntList(labelList.size()); 144 145 for (int i = 0, sz = labelList.size() ; i < sz ; i++) { 146 result.add(ropBlocks.indexOfLabel(labelList.get(i))); 147 } 148 149 return result; 150 } 151 152 private void convertRopToSsaBlocks( 153 RopMethod rmeth) { 154 155 BasicBlockList ropBlocks; 156 157 ropBlocks = rmeth.getBlocks(); 158 159 blocks = new ArrayList<SsaBasicBlock>(ropBlocks.size() + 2); 160 161 for (int i = 0, sz = ropBlocks.size() ; i < sz ; i++) { 162 SsaBasicBlock sbb; 163 164 sbb = SsaBasicBlock.newFromRop(rmeth, i, this); 165 166 blocks.add(sbb); 167 } 168 169 // Add an no-op entry block 170 int origEntryBlockIndex = rmeth.getBlocks() 171 .indexOfLabel(rmeth.getFirstLabel()); 172 173 SsaBasicBlock entryBlock 174 = blocks.get(origEntryBlockIndex).insertNewPredecessor(); 175 176 entryBlockIndex = entryBlock.getIndex(); 177 exitBlockIndex = -1; // this gets made later 178 179 } 180 181 182 /** 183 * Creates an exit block and attaches it to the CFG if this method 184 * exits. Methods that never exit will not have an exit block. This 185 * is called after edge-splitting and phi insertion, since the edges 186 * going into the exit block should not be considered in those steps. 187 */ 188 void makeExitBlock() { 189 if (exitBlockIndex >= 0) { 190 throw new RuntimeException("must be called at most once"); 191 } 192 193 exitBlockIndex = blocks.size(); 194 SsaBasicBlock exitBlock 195 = new SsaBasicBlock(exitBlockIndex, maxLabel++, this); 196 197 blocks.add(exitBlock); 198 199 for (SsaBasicBlock block: blocks) { 200 block.exitBlockFixup(exitBlock); 201 } 202 203 if (exitBlock.getPredecessors().cardinality() == 0) { 204 // In cases where there is no exit... 205 blocks.remove(exitBlockIndex); 206 exitBlockIndex = -1; 207 maxLabel--; 208 } 209 } 210 211 /** 212 * Constructor 213 * 214 * @param paramWidth the total width, in register-units, of the 215 * method's parameters 216 * @param isStatic true if this method has no 'this' pointer argument 217 */ 218 private SsaMethod(int paramWidth, boolean isStatic) { 219 this.paramWidth = paramWidth; 220 this.isStatic = isStatic; 221 } 222 223 /** 224 * Gets a new GOTO insn. 225 * 226 * @param block block to which this GOTO will be added 227 * (not it's destination!) 228 * @return an appropriately-constructed instance. 229 */ 230 private static SsaInsn getGoto(SsaBasicBlock block) { 231 return new NormalSsaInsn ( 232 new PlainInsn(Rops.GOTO, SourcePosition.NO_INFO, 233 null, RegisterSpecList.EMPTY), block); 234 } 235 236 /** 237 * Makes a new basic block for this method, 238 * which is empty besides a single <code>GOTO</code>. Successors and 239 * predecessors are not yet set. 240 * 241 * @return new block 242 */ 243 public SsaBasicBlock makeNewGotoBlock() { 244 int newIndex = blocks.size(); 245 SsaBasicBlock newBlock = new SsaBasicBlock(newIndex, maxLabel++, this); 246 247 newBlock.getInsns().add(getGoto(newBlock)); 248 blocks.add(newBlock); 249 250 return newBlock; 251 } 252 253 /** 254 * @return block index of first execution block 255 */ 256 public int getEntryBlockIndex() { 257 return entryBlockIndex; 258 } 259 260 /** 261 * @return first execution block 262 */ 263 public SsaBasicBlock getEntryBlock() { 264 return blocks.get(entryBlockIndex); 265 } 266 267 /** 268 * @return block index of exit block or -1 if there is none 269 */ 270 public int getExitBlockIndex() { 271 return exitBlockIndex; 272 } 273 274 /** 275 * @return null-ok; block of exit block or null if there is none 276 */ 277 public SsaBasicBlock getExitBlock() { 278 return exitBlockIndex < 0 ? null : blocks.get(exitBlockIndex); 279 } 280 281 /** 282 * @param bi block index or -1 for none 283 * @return rop label or -1 if bi was -1 284 */ 285 public int blockIndexToRopLabel(int bi) { 286 if (bi < 0) { 287 return -1; 288 } 289 return blocks.get(bi).getRopLabel(); 290 } 291 292 /** 293 * @return count of registers used in this method 294 */ 295 public int getRegCount() { 296 return registerCount; 297 } 298 299 /** 300 * @return the total width, in register units, of the method's 301 * parameters 302 */ 303 public int getParamWidth() { 304 return paramWidth; 305 } 306 307 /** 308 * Returns true if this is a static method. 309 * 310 * @return true if this is a static method 311 */ 312 public boolean isStatic() { 313 return isStatic; 314 } 315 316 /** 317 * Borrow a register to use as a temp. Used in the phi removal process. 318 * Call returnSpareRegisters() when done. 319 * @param category width (1 or 2) of the register 320 * @return register number to use 321 */ 322 public int borrowSpareRegister(int category) { 323 int result; 324 325 result = spareRegisterBase + borrowedSpareRegisters; 326 327 borrowedSpareRegisters += category; 328 329 registerCount = Math.max(registerCount, result + category); 330 331 return result; 332 } 333 334 /** 335 * Returns all borrowed registers. 336 */ 337 public void returnSpareRegisters() { 338 borrowedSpareRegisters = 0; 339 } 340 341 /** 342 * @return non-null; basic block list, do not modify. 343 */ 344 public ArrayList<SsaBasicBlock> getBlocks() { 345 return blocks; 346 } 347 348 /** 349 * Returns the count of reachable blocks in this method: blocks that have 350 * predecessors (or are the start block) 351 * 352 * @return >= 0; number of reachable basic blocks 353 */ 354 public int getCountReachableBlocks() { 355 int ret = 0; 356 357 for (SsaBasicBlock b: blocks) { 358 // Blocks that have been disconnected don't count. 359 if (b.isReachable()) { 360 ret++; 361 } 362 } 363 364 return ret; 365 } 366 367 /** 368 * Remaps unversioned registers. 369 * @param mapper maps old registers to new. 370 */ 371 public void mapRegisters(RegisterMapper mapper) { 372 373 for (SsaBasicBlock block: getBlocks()) { 374 for (SsaInsn insn: block.getInsns()) { 375 insn.mapRegisters(mapper); 376 } 377 } 378 379 registerCount = mapper.getNewRegisterCount(); 380 spareRegisterBase = registerCount; 381 } 382 383 /** 384 * Returns the insn that defines the given register 385 * @param reg register in question 386 * @return insn (actual instance from code) that defined this reg or null 387 * if reg is not defined. 388 */ 389 public SsaInsn getDefinitionForRegister(int reg) { 390 if (backMode) { 391 throw new RuntimeException("No def list in back mode"); 392 } 393 394 if (definitionList != null) { 395 return definitionList[reg]; 396 } 397 398 definitionList = new SsaInsn[getRegCount()]; 399 400 forEachInsn(new SsaInsn.Visitor() { 401 public void visitMoveInsn (NormalSsaInsn insn) { 402 definitionList[insn.getResult().getReg()] = insn; 403 } 404 public void visitPhiInsn (PhiInsn phi) { 405 definitionList[phi.getResult().getReg()] = phi; 406 } 407 public void visitNonMoveInsn (NormalSsaInsn insn) { 408 RegisterSpec result = insn.getResult(); 409 if (result != null) { 410 definitionList[insn.getResult().getReg()] = insn; 411 } 412 } 413 }); 414 415 return definitionList[reg]; 416 } 417 418 /** 419 * Builds useList and unmodifiableUseList. 420 */ 421 private void buildUseList() { 422 if (backMode) { 423 throw new RuntimeException("No use list in back mode"); 424 } 425 426 useList = new ArrayList[registerCount]; 427 428 for (int i = 0 ; i < registerCount; i++) { 429 useList[i] = new ArrayList(); 430 } 431 432 forEachInsn(new SsaInsn.Visitor() { 433 /** {@inheritDoc} */ 434 public void visitMoveInsn (NormalSsaInsn insn) { 435 addToUses(insn); 436 } 437 /** {@inheritDoc} */ 438 public void visitPhiInsn (PhiInsn phi) { 439 addToUses(phi); 440 } 441 /** {@inheritDoc} */ 442 public void visitNonMoveInsn (NormalSsaInsn insn) { 443 addToUses(insn); 444 } 445 /** 446 * Adds specified insn to the uses list for all of its sources. 447 * @param insn non-null; insn to process 448 */ 449 private void addToUses(SsaInsn insn) { 450 RegisterSpecList rl = insn.getSources(); 451 int sz = rl.size(); 452 453 for (int i = 0; i < sz; i++) { 454 useList[rl.get(i).getReg()].add(insn); 455 } 456 } 457 }); 458 459 unmodifiableUseList = new List[registerCount]; 460 461 for (int i = 0 ; i < registerCount; i++) { 462 unmodifiableUseList[i] = Collections.unmodifiableList(useList[i]); 463 } 464 } 465 466 /** 467 * Updates the use list for a single change in source register. 468 * 469 * @param insn non-null; insn being changed 470 * @param oldSource null-ok; The source that was used, if applicable 471 * @param newSource non-null; the new source being used 472 */ 473 void onSourceChanged(SsaInsn insn, 474 RegisterSpec oldSource, RegisterSpec newSource) { 475 476 if (useList == null) return; 477 478 if (oldSource != null) { 479 int reg = oldSource.getReg(); 480 useList[reg].remove(insn); 481 } 482 483 int reg = newSource.getReg(); 484 if (useList.length <= reg) { 485 useList = null; 486 return; 487 } 488 useList[reg].add(insn); 489 } 490 491 /** 492 * Updates the use list for a source list change. 493 * 494 * @param insn insn non-null; insn being changed. insn.getSources() 495 * must return the new source list. 496 * @param oldSources null-ok; list of sources that were previously used. 497 */ 498 void onSourcesChanged(SsaInsn insn, RegisterSpecList oldSources) { 499 if (useList == null) return; 500 501 if (oldSources != null) { 502 removeFromUseList(insn, oldSources); 503 } 504 505 RegisterSpecList sources = insn.getSources(); 506 int szNew = sources.size(); 507 508 for(int i = 0; i < szNew; i++) { 509 int reg = sources.get(i).getReg(); 510 useList[reg].add(insn); 511 } 512 } 513 514 /** 515 * Removes a given <code>insn</code> from the use lists for the given 516 * <code>oldSources</code> (rather than the sources currently 517 * returned by insn.getSources()). 518 * 519 * @param insn non-null; insn in question 520 * @param oldSources null-ok; registers whose use lists <code>insn</code> 521 * should be removed form. 522 */ 523 private void removeFromUseList(SsaInsn insn, RegisterSpecList oldSources) { 524 if (oldSources == null) { 525 return; 526 } 527 int szNew = oldSources.size(); 528 for(int i = 0; i < szNew; i++) { 529 if (!useList[oldSources.get(i).getReg()].remove(insn)) { 530 throw new RuntimeException("use not found"); 531 } 532 } 533 } 534 535 /** 536 * Adds an insn to both the use and def lists. For use when adding 537 * a new insn to the method. 538 * 539 * @param insn non-null; insn to add 540 */ 541 void onInsnAdded(SsaInsn insn) { 542 onSourcesChanged(insn, null); 543 updateOneDefinition(insn, null); 544 } 545 546 /** 547 * Removes an instruction from use and def lists. For use during 548 * instruction removal. 549 * 550 * @param insn non-null; insn to remove. 551 */ 552 void onInsnRemoved(SsaInsn insn) { 553 if (useList != null) { 554 removeFromUseList(insn, insn.getSources()); 555 } 556 557 RegisterSpec resultReg = insn.getResult(); 558 if (definitionList != null && resultReg != null) { 559 definitionList[resultReg.getReg()] = null; 560 } 561 } 562 563 /** 564 * Indicates that the instruction list has changed or the SSA register 565 * count has increased, so that internal datastructures that rely on 566 * it should be rebuild. In general, the various other on* methods 567 * should be called in preference when changes occur if they are 568 * applicable. 569 */ 570 public void onInsnsChanged() { 571 // Definition list will need to be recomputed 572 definitionList = null; 573 574 // Use list will need to be recomputed 575 useList = null; 576 unmodifiableUseList = null; 577 } 578 579 /** 580 * Updates a single definition. 581 * 582 * @param insn non-null; insn who's result should be recorded as 583 * a definition 584 * @param oldResult null-ok; a previous result that should be no longer 585 * considered a definition by this insn 586 */ 587 void updateOneDefinition(SsaInsn insn, RegisterSpec oldResult) { 588 if (definitionList == null) return; 589 if (oldResult != null) { 590 int reg = oldResult.getReg(); 591 definitionList[reg] = null; 592 } 593 594 RegisterSpec resultReg = insn.getResult(); 595 if (resultReg != null) { 596 int reg = resultReg.getReg(); 597 598 if (definitionList[reg] != null) { 599 throw new RuntimeException("Duplicate add of insn"); 600 } else { 601 definitionList[resultReg.getReg()] = insn; 602 } 603 } 604 } 605 606 /** 607 * Returns the list of all source uses (not results) for a register 608 * @param reg register in question 609 * @return unmodifiable instruction list 610 */ 611 public List<SsaInsn> getUseListForRegister(int reg) { 612 613 if (unmodifiableUseList == null) { 614 buildUseList(); 615 } 616 617 return unmodifiableUseList[reg]; 618 } 619 620 /** 621 * Returns a modifiable copy of the register use list. 622 * @return modifiable copy of the use-list, indexed by register 623 */ 624 public ArrayList<SsaInsn>[] getUseListCopy() { 625 if (useList == null) { 626 buildUseList(); 627 } 628 629 ArrayList<SsaInsn>[] useListCopy 630 = (ArrayList<SsaInsn>[])(new ArrayList[registerCount]); 631 632 for (int i = 0; i < registerCount; i++) { 633 useListCopy[i] = (ArrayList<SsaInsn>)(new ArrayList(useList[i])); 634 } 635 636 return useListCopy; 637 } 638 639 /** 640 * Checks to see if the given SSA reg is ever associated with a local 641 * local variable. Each SSA reg may be associated with at most one 642 * local var. 643 * 644 * @param spec non-null; ssa reg 645 * @return true if reg is ever associated with a local 646 */ 647 public boolean isRegALocal(RegisterSpec spec) { 648 SsaInsn defn = getDefinitionForRegister(spec.getReg()); 649 650 if (defn == null) { 651 // version 0 registers are never used as locals 652 return false; 653 } 654 655 // Does the definition have a local associated with it? 656 if (defn.getLocalAssignment() != null) return true; 657 658 // If not, is there a mark-local insn? 659 for (SsaInsn use: getUseListForRegister(spec.getReg())) { 660 Insn insn = use.getOriginalRopInsn(); 661 662 if (insn != null 663 && insn.getOpcode().getOpcode() == RegOps.MARK_LOCAL) { 664 return true; 665 } 666 } 667 668 return false; 669 } 670 671 /** 672 * Sets the new register count after renaming. 673 * @param newRegCount new register count 674 */ 675 /*package*/ void setNewRegCount(int newRegCount) { 676 registerCount = newRegCount; 677 spareRegisterBase = registerCount; 678 onInsnsChanged(); 679 } 680 681 /** 682 * Makes a new SSA register. For use after renaming has completed. 683 * 684 * @return >=0 new SSA register. 685 */ 686 public int makeNewSsaReg() { 687 int reg = registerCount++; 688 spareRegisterBase = registerCount; 689 onInsnsChanged(); 690 return reg; 691 } 692 693 /** 694 * Visit all insns in this method 695 * @param visitor non-null; callback interface 696 */ 697 public void forEachInsn(SsaInsn.Visitor visitor) { 698 for (SsaBasicBlock block: blocks) { 699 block.forEachInsn(visitor); 700 } 701 } 702 703 /** 704 * Visits each phi insn in this method 705 * @param v non-null; callback 706 */ 707 public void forEachPhiInsn(PhiInsn.Visitor v) { 708 for (SsaBasicBlock block: blocks) { 709 block.forEachPhiInsn(v); 710 } 711 } 712 713 714 /** 715 * Walk the basic block tree in depth-first order, calling the visitor 716 * method once for every block. This depth-first walk may be run forward 717 * from the method entry point or backwards from the method exit points. 718 * @param reverse true if this should walk backwards from the exit points 719 * @param v non-null; callback interface. <code>parent</code>is set 720 * unless this is the root node 721 */ 722 public void forEachBlockDepthFirst(boolean reverse, 723 SsaBasicBlock.Visitor v) { 724 BitSet visited = new BitSet(blocks.size()); 725 // We push the parent first, then the child on the stack 726 Stack<SsaBasicBlock> stack = new Stack<SsaBasicBlock>(); 727 728 SsaBasicBlock rootBlock = reverse ? getExitBlock() : getEntryBlock(); 729 730 if (rootBlock == null) { 731 // in the case there's no exit block 732 return; 733 } 734 735 stack.add(null); // start with null parent 736 stack.add(rootBlock); 737 738 while (stack.size() > 0) { 739 SsaBasicBlock cur = stack.pop(); 740 SsaBasicBlock parent = stack.pop(); 741 742 if (!visited.get(cur.getIndex())) { 743 BitSet children 744 = reverse ? cur.getPredecessors() : cur.getSuccessors(); 745 for (int i = children.nextSetBit(0); i >= 0 746 ; i = children.nextSetBit(i + 1)) { 747 stack.add(cur); 748 stack.add(blocks.get(i)); 749 } 750 visited.set(cur.getIndex()); 751 v.visitBlock(cur, parent); 752 } 753 } 754 } 755 756 /** 757 * Visits blocks in dom-tree order, starting at the current node. 758 * The <code>parent</code> parameter of the Visitor.visitBlock callback 759 * is currently always set to null. 760 * 761 * @param v non-null; callback interface 762 */ 763 public void forEachBlockDepthFirstDom(SsaBasicBlock.Visitor v) { 764 BitSet visited = new BitSet(getBlocks().size()); 765 Stack<SsaBasicBlock> stack = new Stack<SsaBasicBlock>(); 766 767 stack.add(getEntryBlock()); 768 769 while (stack.size() > 0) { 770 SsaBasicBlock cur = stack.pop(); 771 ArrayList<SsaBasicBlock> curDomChildren = cur.getDomChildren(); 772 773 if (!visited.get(cur.getIndex())) { 774 // We walk the tree this way for historical reasons... 775 for (int i = curDomChildren.size() - 1; i >= 0; i--) { 776 SsaBasicBlock child = curDomChildren.get(i); 777 stack.add(child); 778 } 779 visited.set(cur.getIndex()); 780 v.visitBlock(cur, null); 781 } 782 } 783 } 784 785 /** 786 * Deletes all insns in the set from this method 787 * 788 * @param deletedInsns non-null; insns to delete 789 */ 790 public void deleteInsns(Set<SsaInsn> deletedInsns) { 791 for (SsaBasicBlock block: getBlocks()) { 792 ArrayList<SsaInsn> insns = block.getInsns(); 793 794 for (int i = insns.size() - 1; i >= 0; i--) { 795 SsaInsn insn = insns.get(i); 796 797 if (deletedInsns.contains(insn)) { 798 onInsnRemoved(insn); 799 insns.remove(i); 800 } 801 } 802 803 // Check to see if we need to add a GOTO 804 805 int insnsSz = insns.size(); 806 SsaInsn lastInsn = (insnsSz == 0) ? null : insns.get(insnsSz - 1); 807 808 if (block != getExitBlock() && (insnsSz == 0 809 || lastInsn.getOriginalRopInsn() == null 810 || lastInsn.getOriginalRopInsn().getOpcode() 811 .getBranchingness() == Rop.BRANCH_NONE)) { 812 // We managed to eat a throwable insn 813 814 Insn gotoInsn = new PlainInsn(Rops.GOTO, 815 SourcePosition.NO_INFO, null, RegisterSpecList.EMPTY); 816 insns.add(SsaInsn.makeFromRop(gotoInsn, block)); 817 } 818 } 819 } 820 821 /** 822 * Set "back-convert mode". Set during back-conversion when registers 823 * are about to be mapped into a non-SSA namespace. When true, 824 * use and def lists are unavailable. 825 */ 826 public void setBackMode() { 827 backMode = true; 828 useList = null; 829 definitionList = null; 830 } 831} 832