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