FileDocCategorySizeDatePackage
ExecutionStack.javaAPI DocAndroid 5.1 API10038Thu Mar 12 22:18:30 GMT 2015com.android.dx.cf.code

ExecutionStack

public final class ExecutionStack extends com.android.dx.util.MutabilityControl
Representation of a Java method execution stack.

Note: For the most part, the documentation for this class ignores the distinction between {@link Type} and {@link TypeBearer}.

Fields Summary
private final com.android.dx.rop.type.TypeBearer[]
stack
{@code non-null;} array of stack contents
private final boolean[]
local
{@code non-null;} array specifying whether stack contents have entries in the local variable table
private int
stackPtr
{@code >= 0;} stack pointer (points one past the end) / current stack size
Constructors Summary
public ExecutionStack(int maxStack)
Constructs an instance.

param
maxStack {@code >= 0;} the maximum size of the stack for this instance

        super(maxStack != 0);
        stack = new TypeBearer[maxStack];
        local = new boolean[maxStack];
        stackPtr = 0;
    
Methods Summary
public voidannotate(com.android.dex.util.ExceptionWithContext ex)
Annotates (adds context to) the given exception with information about this instance.

param
ex {@code non-null;} the exception to annotate

        int limit = stackPtr - 1;

        for (int i = 0; i <= limit; i++) {
            String idx = (i == limit) ? "top0" : Hex.u2(limit - i);

            ex.addContext("stack[" + idx + "]: " +
                          stackElementString(stack[i]));
        }
    
public voidchange(int n, com.android.dx.rop.type.TypeBearer type)
Changes an element already on a stack. This method is useful in limited contexts, particularly when merging two instances. As such, it places the following restriction on its behavior: You may only replace values with other values of the same category.

param
n {@code >= 0;} which element to change, where {@code 0} is the top element of the stack
param
type {@code non-null;} type of the new value
throws
SimException thrown if {@code n >= size()} or the action is otherwise prohibited

        throwIfImmutable();

        try {
            type = type.getFrameType();
        } catch (NullPointerException ex) {
            // Elucidate the exception.
            throw new NullPointerException("type == null");
        }

        int idx = stackPtr - n - 1;
        TypeBearer orig = stack[idx];

        if ((orig == null) ||
            (orig.getType().getCategory() != type.getType().getCategory())) {
            throwSimException("incompatible substitution: " +
                              stackElementString(orig) + " -> " +
                              stackElementString(type));
        }

        stack[idx] = type;
    
public voidclear()
Clears the stack. (That is, this method pops everything off.)

        throwIfImmutable();

        for (int i = 0; i < stackPtr; i++) {
            stack[i] = null;
            local[i] = false;
        }

        stackPtr = 0;
    
public com.android.dx.cf.code.ExecutionStackcopy()
Makes and returns a mutable copy of this instance.

return
{@code non-null;} the copy

        ExecutionStack result = new ExecutionStack(stack.length);

        System.arraycopy(stack, 0, result.stack, 0, stack.length);
        System.arraycopy(local, 0, result.local, 0, local.length);
        result.stackPtr = stackPtr;

        return result;
    
public intgetMaxStack()
Gets the maximum stack size for this instance.

return
{@code >= 0;} the max stack size

        return stack.length;
    
public voidmakeInitialized(com.android.dx.rop.type.Type type)
Replaces all the occurrences of the given uninitialized type in this stack with its initialized equivalent.

param
type {@code non-null;} type to replace

        if (stackPtr == 0) {
            // We have to check for this before checking for immutability.
            return;
        }

        throwIfImmutable();

        Type initializedType = type.getInitializedType();

        for (int i = 0; i < stackPtr; i++) {
            if (stack[i] == type) {
                stack[i] = initializedType;
            }
        }
    
public com.android.dx.cf.code.ExecutionStackmerge(com.android.dx.cf.code.ExecutionStack other)
Merges this stack with another stack. A new instance is returned if this merge results in a change. If no change results, this instance is returned. See {@link Merger#mergeStack(ExecutionStack,ExecutionStack) Merger.mergeStack()}

param
other {@code non-null;} a stack to merge with
return
{@code non-null;} the result of the merge

        try {
            return Merger.mergeStack(this, other);
        } catch (SimException ex) {
            ex.addContext("underlay stack:");
            this.annotate(ex);
            ex.addContext("overlay stack:");
            other.annotate(ex);
            throw ex;
        }
    
public com.android.dx.rop.type.TypeBearerpeek(int n)
Peeks at the {@code n}th element down from the top of the stack. {@code n == 0} means to peek at the top of the stack. Note that this will return {@code null} if the indicated element is the deeper half of a category-2 value.

param
n {@code >= 0;} which element to peek at
return
{@code null-ok;} the type of value stored at that element
throws
SimException thrown if {@code n >= size()}

        if (n < 0) {
            throw new IllegalArgumentException("n < 0");
        }

        if (n >= stackPtr) {
            return throwSimException("underflow");
        }

        return stack[stackPtr - n - 1];
    
public booleanpeekLocal(int n)
Peeks at the {@code n}th element down from the top of the stack, returning whether or not it has local info.

param
n {@code >= 0;} which element to peek at
return
{@code true} if the value has local info, {@code false} otherwise
throws
SimException thrown if {@code n >= size()}

        if (n < 0) {
            throw new IllegalArgumentException("n < 0");
        }

        if (n >= stackPtr) {
            throw new SimException("stack: underflow");
        }

        return local[stackPtr - n - 1];
    
public com.android.dx.rop.type.TypepeekType(int n)
Peeks at the {@code n}th element down from the top of the stack, returning the type per se, as opposed to the type-bearer. This method is just a convenient shorthand for {@code peek(n).getType()}.

see
#peek

        return peek(n).getType();
    
public com.android.dx.rop.type.TypeBearerpop()
Pops the top element off of the stack.

return
{@code non-null;} the type formerly on the top of the stack
throws
SimException thrown if the stack is empty

        throwIfImmutable();

        TypeBearer result = peek(0);

        stack[stackPtr - 1] = null;
        local[stackPtr - 1] = false;
        stackPtr -= result.getType().getCategory();

        return result;
    
public voidpush(com.android.dx.rop.type.TypeBearer type)
Pushes a value of the given type onto the stack.

param
type {@code non-null;} type of the value
throws
SimException thrown if there is insufficient room on the stack for the value

        throwIfImmutable();

        int category;

        try {
            type = type.getFrameType();
            category = type.getType().getCategory();
        } catch (NullPointerException ex) {
            // Elucidate the exception.
            throw new NullPointerException("type == null");
        }

        if ((stackPtr + category) > stack.length) {
            throwSimException("overflow");
            return;
        }

        if (category == 2) {
            stack[stackPtr] = null;
            stackPtr++;
        }

        stack[stackPtr] = type;
        stackPtr++;
    
public voidsetLocal()
Flags the next value pushed onto the stack as having local info.

        throwIfImmutable();

        local[stackPtr] = true;
    
public intsize()
Gets the current stack size.

return
{@code >= 0, < getMaxStack();} the current stack size

        return stackPtr;
    
private static java.lang.StringstackElementString(com.android.dx.rop.type.TypeBearer type)
Gets the string form for a stack element. This is the same as {@code toString()} except that {@code null} is converted to {@code ""}.

param
type {@code null-ok;} the stack element
return
{@code non-null;} the string form

        if (type == null) {
            return "<invalid>";
        }

        return type.toString();
    
private static com.android.dx.rop.type.TypeBearerthrowSimException(java.lang.String msg)
Throws a properly-formatted exception.

param
msg {@code non-null;} useful message
return
never (keeps compiler happy)

        throw new SimException("stack: " + msg);