FileDocCategorySizeDatePackage
LocalList.javaAPI DocAndroid 5.1 API32032Thu Mar 12 22:18:28 GMT 2015com.android.dexgen.dex.code

LocalList

public final class LocalList extends com.android.dexgen.util.FixedSizeList
List of local variables. Each local variable entry indicates a range of code which it is valid for, a register number, a name, and a type.

Fields Summary
public static final LocalList
EMPTY
{@code non-null;} empty instance
private static final boolean
DEBUG
whether to run the self-check code
Constructors Summary
public LocalList(int size)
Constructs an instance. All indices initially contain {@code null}.

param
size {@code >= 0;} the size of the list


                            
       
        super(size);
    
Methods Summary
public voiddebugPrint(java.io.PrintStream out, java.lang.String prefix)
Does a human-friendly dump of this instance.

param
out {@code non-null;} where to dump
param
prefix {@code non-null;} prefix to attach to each line of output

        int sz = size();

        for (int i = 0; i < sz; i++) {
            out.print(prefix);
            out.println(get(i));
        }
    
private static voiddebugVerify(com.android.dexgen.dex.code.LocalList locals)
Debugging helper that verifies the constraint that a list doesn't contain any redundant local starts and that local ends that are due to replacements are properly annotated.

        try {
            debugVerify0(locals);
        } catch (RuntimeException ex) {
            int sz = locals.size();
            for (int i = 0; i < sz; i++) {
                System.err.println(locals.get(i));
            }
            throw ex;
        }

    
private static voiddebugVerify0(com.android.dexgen.dex.code.LocalList locals)
Helper for {@link #debugVerify} which does most of the work.

        int sz = locals.size();
        Entry[] active = new Entry[65536];

        for (int i = 0; i < sz; i++) {
            Entry e = locals.get(i);
            int reg = e.getRegister();

            if (e.isStart()) {
                Entry already = active[reg];

                if ((already != null) && e.matches(already)) {
                    throw new RuntimeException("redundant start at " +
                            Integer.toHexString(e.getAddress()) + ": got " +
                            e + "; had " + already);
                }

                active[reg] = e;
            } else {
                if (active[reg] == null) {
                    throw new RuntimeException("redundant end at " +
                            Integer.toHexString(e.getAddress()));
                }

                int addr = e.getAddress();
                boolean foundStart = false;

                for (int j = i + 1; j < sz; j++) {
                    Entry test = locals.get(j);
                    if (test.getAddress() != addr) {
                        break;
                    }
                    if (test.getRegisterSpec().getReg() == reg) {
                        if (test.isStart()) {
                            if (e.getDisposition()
                                    != Disposition.END_REPLACED) {
                                throw new RuntimeException(
                                        "improperly marked end at " +
                                        Integer.toHexString(addr));
                            }
                            foundStart = true;
                        } else {
                            throw new RuntimeException(
                                    "redundant end at " +
                                    Integer.toHexString(addr));
                        }
                    }
                }

                if (!foundStart &&
                        (e.getDisposition() == Disposition.END_REPLACED)) {
                    throw new RuntimeException(
                            "improper end replacement claim at " +
                            Integer.toHexString(addr));
                }

                active[reg] = null;
            }
        }
    
public com.android.dexgen.dex.code.LocalList$Entryget(int n)
Gets the element at the given index. It is an error to call this with the index for an element which was never set; if you do that, this will throw {@code NullPointerException}.

param
n {@code >= 0, < size();} which index
return
{@code non-null;} element at that index

        return (Entry) get0(n);
    
public static com.android.dexgen.dex.code.LocalListmake(DalvInsnList insns)
Constructs an instance for the given method, based on the given block order and intermediate local information.

param
insns {@code non-null;} instructions to convert
return
{@code non-null;} the constructed list

        int sz = insns.size();

        /*
         * Go through the insn list, looking for all the local
         * variable pseudoinstructions, splitting out LocalSnapshots
         * into separate per-variable starts, adding explicit ends
         * wherever a variable is replaced or moved, and collecting
         * these and all the other local variable "activity"
         * together into an output list (without the other insns).
         *
         * Note: As of this writing, this method won't be handed any
         * insn lists that contain local ends, but I (danfuzz) expect
         * that to change at some point, when we start feeding that
         * info explicitly into the rop layer rather than only trying
         * to infer it. So, given that expectation, this code is
         * written to deal with them.
         */

        MakeState state = new MakeState(sz);

        for (int i = 0; i < sz; i++) {
            DalvInsn insn = insns.get(i);

            if (insn instanceof LocalSnapshot) {
                RegisterSpecSet snapshot =
                    ((LocalSnapshot) insn).getLocals();
                state.snapshot(insn.getAddress(), snapshot);
            } else if (insn instanceof LocalStart) {
                RegisterSpec local = ((LocalStart) insn).getLocal();
                state.startLocal(insn.getAddress(), local);
            } else if (insn instanceof LocalEnd) {
                RegisterSpec local = ((LocalEnd) insn).getLocal();
                state.endLocal(insn.getAddress(), local);
            }
        }

        LocalList result = state.finish();

        if (DEBUG) {
            debugVerify(result);
        }

        return result;
    
public voidset(int n, com.android.dexgen.dex.code.LocalList$Entry entry)
Sets the entry at the given index.

param
n {@code >= 0, < size();} which index
param
entry {@code non-null;} the entry to set at {@code n}

        set0(n, entry);