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
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeBearer;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ExceptionWithContext;
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.
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
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 {
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** 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    /**
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * &gt;= 0; stack pointer (points one past the end) / current stack
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * size
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int stackPtr;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param maxStack &gt;= 0; the maximum size of the stack for this
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instance
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ExecutionStack(int maxStack) {
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(maxStack != 0);
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stack = new TypeBearer[maxStack];
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr = 0;
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Makes and returns a mutable copy of this instance.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return non-null; the copy
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ExecutionStack copy() {
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ExecutionStack result = new ExecutionStack(stack.length);
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(stack, 0, result.stack, 0, stack.length);
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result.stackPtr = stackPtr;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Annotates (adds context to) the given exception with information
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * about this instance.
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ex non-null; the exception to annotate
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void annotate(ExceptionWithContext ex) {
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int limit = stackPtr - 1;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i <= limit; i++) {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String idx = (i == limit) ? "top0" : Hex.u2(limit - i);
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ex.addContext("stack[" + idx + "]: " +
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                          stackElementString(stack[i]));
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Replaces all the occurrences of the given uninitialized type in
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this stack with its initialized equivalent.
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param type non-null; type to replace
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void makeInitialized(Type type) {
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (stackPtr == 0) {
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // We have to check for this before checking for immutability.
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwIfImmutable();
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Type initializedType = type.getInitializedType();
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < stackPtr; i++) {
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (stack[i] == type) {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                stack[i] = initializedType;
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the maximum stack size for this instance.
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return &gt;= 0; the max stack size
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getMaxStack() {
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return stack.length;
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the current stack size.
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return &gt;= 0, &lt; getMaxStack(); the current stack size
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int size() {
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return stackPtr;
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Clears the stack. (That is, this method pops everything off.)
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void clear() {
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwIfImmutable();
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < stackPtr; i++) {
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stack[i] = null;
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr = 0;
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Pushes a value of the given type onto the stack.
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param type non-null; type of the value
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SimException thrown if there is insufficient room on the
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stack for the value
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void push(TypeBearer type) {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwIfImmutable();
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int category;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            type = type.getFrameType();
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            category = type.getType().getCategory();
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (NullPointerException ex) {
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Elucidate the exception.
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("type == null");
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((stackPtr + category) > stack.length) {
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwSimException("overflow");
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (category == 2) {
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stack[stackPtr] = null;
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackPtr++;
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stack[stackPtr] = type;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr++;
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Peeks at the <code>n</code>th element down from the top of the stack.
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <code>n == 0</code> means to peek at the top of the stack. Note that
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this will return <code>null</code> if the indicated element is the
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * deeper half of a category-2 value.
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param n &gt;= 0; which element to peek at
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return null-ok; the type of value stored at that element
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SimException thrown if <code>n &gt;= size()</code>
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public TypeBearer peek(int n) {
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (n < 0) {
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n < 0");
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (n >= stackPtr) {
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return throwSimException("underflow");
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return stack[stackPtr - n - 1];
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Peeks at the <code>n</code>th element down from the top of the
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stack, returning the type per se, as opposed to the
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <i>type-bearer</i>.  This method is just a convenient shorthand
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for <code>peek(n).getType()</code>.
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #peek
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Type peekType(int n) {
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return peek(n).getType();
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Pops the top element off of the stack.
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return non-null; the type formerly on the top of the stack
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SimException thrown if the stack is empty
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public TypeBearer pop() {
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwIfImmutable();
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeBearer result = peek(0);
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stack[stackPtr - 1] = null;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr -= result.getType().getCategory();
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Changes an element already on a stack. This method is useful in limited
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * contexts, particularly when merging two instances. As such, it places
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the following restriction on its behavior: You may only replace
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * values with other values of the same category.
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param n &gt;= 0; which element to change, where <code>0</code> is
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the top element of the stack
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param type non-null; type of the new value
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws SimException thrown if <code>n &gt;= size()</code> or
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the action is otherwise prohibited
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void change(int n, TypeBearer type) {
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwIfImmutable();
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            type = type.getFrameType();
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (NullPointerException ex) {
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Elucidate the exception.
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("type == null");
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int idx = stackPtr - n - 1;
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeBearer orig = stack[idx];
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((orig == null) ||
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (orig.getType().getCategory() != type.getType().getCategory())) {
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwSimException("incompatible substitution: " +
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                              stackElementString(orig) + " -> " +
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                              stackElementString(type));
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stack[idx] = type;
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Merges this stack with another stack. A new instance is returned if
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this merge results in a change. If no change results, this instance is
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * returned.  See {@link Merger#mergeStack(ExecutionStack,ExecutionStack)
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Merger.mergeStack()}
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param other non-null; a stack to merge with
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return non-null; the result of the merge
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ExecutionStack merge(ExecutionStack other) {
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return Merger.mergeStack(this, other);
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (SimException ex) {
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ex.addContext("underlay stack:");
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.annotate(ex);
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ex.addContext("overlay stack:");
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            other.annotate(ex);
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ex;
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the string form for a stack element. This is the same as
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <code>toString()</code> except that <code>null</code> is converted
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to <code>"&lt;invalid&gt;"</code>.
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param type null-ok; the stack element
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return non-null; the string form
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static String stackElementString(TypeBearer type) {
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (type == null) {
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return "<invalid>";
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type.toString();
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Throws a properly-formatted exception.
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param msg non-null; useful message
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return never (keeps compiler happy)
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static TypeBearer throwSimException(String msg) {
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new SimException("stack: " + msg);
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
306