1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.cf.code; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dex.util.ExceptionWithContext; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeBearer; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.MutabilityControl; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Representation of a Java method execution stack. 27de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p><b>Note:</b> For the most part, the documentation for this class 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ignores the distinction between {@link Type} and {@link 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TypeBearer}.</p> 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class ExecutionStack extends MutabilityControl { 3399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} array of stack contents */ 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final TypeBearer[] stack; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 37c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao * {@code non-null;} array specifying whether stack contents have entries 38c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao * in the local variable table 39c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao */ 40c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao private final boolean[] local; 41c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao /** 4299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code >= 0;} stack pointer (points one past the end) / current stack 43de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * size 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int stackPtr; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 48de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * Constructs an instance. 49de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 5099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param maxStack {@code >= 0;} the maximum size of the stack for this 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instance 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ExecutionStack(int maxStack) { 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(maxStack != 0); 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stack = new TypeBearer[maxStack]; 56c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao local = new boolean[maxStack]; 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = 0; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Makes and returns a mutable copy of this instance. 62de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 6399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the copy 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ExecutionStack copy() { 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ExecutionStack result = new ExecutionStack(stack.length); 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(stack, 0, result.stack, 0, stack.length); 69c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao System.arraycopy(local, 0, result.local, 0, local.length); 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.stackPtr = stackPtr; 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Annotates (adds context to) the given exception with information 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * about this instance. 78de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 7999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param ex {@code non-null;} the exception to annotate 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void annotate(ExceptionWithContext ex) { 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int limit = stackPtr - 1; 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i <= limit; i++) { 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String idx = (i == limit) ? "top0" : Hex.u2(limit - i); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ex.addContext("stack[" + idx + "]: " + 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackElementString(stack[i])); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Replaces all the occurrences of the given uninitialized type in 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this stack with its initialized equivalent. 95de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 9699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param type {@code non-null;} type to replace 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void makeInitialized(Type type) { 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr == 0) { 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // We have to check for this before checking for immutability. 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfImmutable(); 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Type initializedType = type.getInitializedType(); 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < stackPtr; i++) { 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stack[i] == type) { 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stack[i] = initializedType; 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the maximum stack size for this instance. 117de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 11899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >= 0;} the max stack size 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getMaxStack() { 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return stack.length; 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the current stack size. 126de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 12799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >= 0, < getMaxStack();} the current stack size 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int size() { 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return stackPtr; 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clears the stack. (That is, this method pops everything off.) 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void clear() { 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfImmutable(); 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < stackPtr; i++) { 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stack[i] = null; 141c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao local[i] = false; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = 0; 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pushes a value of the given type onto the stack. 149de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 15099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param type {@code non-null;} type of the value 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws SimException thrown if there is insufficient room on the 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack for the value 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void push(TypeBearer type) { 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfImmutable(); 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int category; 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = type.getFrameType(); 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project category = type.getType().getCategory(); 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (NullPointerException ex) { 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Elucidate the exception. 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("type == null"); 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((stackPtr + category) > stack.length) { 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwSimException("overflow"); 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (category == 2) { 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stack[stackPtr] = null; 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr++; 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stack[stackPtr] = type; 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr++; 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 182c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao * Flags the next value pushed onto the stack as having local info. 183c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao */ 184c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao public void setLocal() { 185c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao throwIfImmutable(); 186c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao 187c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao local[stackPtr] = true; 188c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao } 189c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao 190c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao /** 19199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Peeks at the {@code n}th element down from the top of the stack. 19299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code n == 0} means to peek at the top of the stack. Note that 19399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * this will return {@code null} if the indicated element is the 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * deeper half of a category-2 value. 195de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 19699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param n {@code >= 0;} which element to peek at 19799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code null-ok;} the type of value stored at that element 198de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * @throws SimException thrown if {@code n >= size()} 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public TypeBearer peek(int n) { 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (n < 0) { 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("n < 0"); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (n >= stackPtr) { 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return throwSimException("underflow"); 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return stack[stackPtr - n - 1]; 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 21399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Peeks at the {@code n}th element down from the top of the 214c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao * stack, returning whether or not it has local info. 215c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao * 216c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao * @param n {@code >= 0;} which element to peek at 217c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao * @return {@code true} if the value has local info, {@code false} otherwise 218c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao * @throws SimException thrown if {@code n >= size()} 219c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao */ 220c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao public boolean peekLocal(int n) { 221c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao if (n < 0) { 222c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao throw new IllegalArgumentException("n < 0"); 223c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao } 224c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao 225c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao if (n >= stackPtr) { 226c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao throw new SimException("stack: underflow"); 227c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao } 228c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao 229c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao return local[stackPtr - n - 1]; 230c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao } 231c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao 232c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao /** 233c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao * Peeks at the {@code n}th element down from the top of the 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack, returning the type per se, as opposed to the 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <i>type-bearer</i>. This method is just a convenient shorthand 23699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * for {@code peek(n).getType()}. 237de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see #peek 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Type peekType(int n) { 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return peek(n).getType(); 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pops the top element off of the stack. 246de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 24799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the type formerly on the top of the stack 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws SimException thrown if the stack is empty 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public TypeBearer pop() { 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfImmutable(); 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TypeBearer result = peek(0); 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stack[stackPtr - 1] = null; 256c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao local[stackPtr - 1] = false; 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= result.getType().getCategory(); 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Changes an element already on a stack. This method is useful in limited 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contexts, particularly when merging two instances. As such, it places 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the following restriction on its behavior: You may only replace 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * values with other values of the same category. 267de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 26899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param n {@code >= 0;} which element to change, where {@code 0} is 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the top element of the stack 27099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param type {@code non-null;} type of the new value 27199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @throws SimException thrown if {@code n >= size()} or 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the action is otherwise prohibited 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void change(int n, TypeBearer type) { 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfImmutable(); 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = type.getFrameType(); 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (NullPointerException ex) { 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Elucidate the exception. 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("type == null"); 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int idx = stackPtr - n - 1; 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TypeBearer orig = stack[idx]; 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((orig == null) || 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (orig.getType().getCategory() != type.getType().getCategory())) { 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwSimException("incompatible substitution: " + 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackElementString(orig) + " -> " + 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackElementString(type)); 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stack[idx] = type; 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Merges this stack with another stack. A new instance is returned if 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this merge results in a change. If no change results, this instance is 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returned. See {@link Merger#mergeStack(ExecutionStack,ExecutionStack) 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Merger.mergeStack()} 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 30399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param other {@code non-null;} a stack to merge with 30499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the result of the merge 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ExecutionStack merge(ExecutionStack other) { 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return Merger.mergeStack(this, other); 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (SimException ex) { 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ex.addContext("underlay stack:"); 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.annotate(ex); 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ex.addContext("overlay stack:"); 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project other.annotate(ex); 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ex; 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the string form for a stack element. This is the same as 32099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code toString()} except that {@code null} is converted 32199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * to {@code "<invalid>"}. 322de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 32399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param type {@code null-ok;} the stack element 32499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the string form 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static String stackElementString(TypeBearer type) { 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (type == null) { 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return "<invalid>"; 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return type.toString(); 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throws a properly-formatted exception. 336de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 33799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param msg {@code non-null;} useful message 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return never (keeps compiler happy) 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static TypeBearer throwSimException(String msg) { 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new SimException("stack: " + msg); 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 344