FileDocCategorySizeDatePackage
ExecutionStack.javaAPI DocAndroid 1.5 API8858Wed May 06 22:41:02 BST 2009com.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
non-null; array of stack contents
private int
stackPtr
>= 0; stack pointer (points one past the end) / current stack size
Constructors Summary
public ExecutionStack(int maxStack)
Constructs an instance.

param
maxStack >= 0; the maximum size of the stack for this instance

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

param
ex 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 >= 0; which element to change, where 0 is the top element of the stack
param
type non-null; type of the new value
throws
SimException thrown if 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;
        }

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

return
non-null; the copy

        ExecutionStack result = new ExecutionStack(stack.length);

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

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

return
>= 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 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 non-null; a stack to merge with
return
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 nth element down from the top of the stack. n == 0 means to peek at the top of the stack. Note that this will return null if the indicated element is the deeper half of a category-2 value.

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

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

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

        return stack[stackPtr - n - 1];
    
public com.android.dx.rop.type.TypepeekType(int n)
Peeks at the nth 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 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
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;
        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 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 intsize()
Gets the current stack size.

return
>= 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 toString() except that null is converted to "<invalid>".

param
type null-ok; the stack element
return
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 non-null; useful message
return
never (keeps compiler happy)

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