From c31f795aef67a0d6af9abe4610db5ecae8d30c19 Mon Sep 17 00:00:00 2001 From: jeffhao Date: Fri, 11 Mar 2011 16:07:48 -0800 Subject: Verifier allows certain errors so they can fail at runtime. Specifically, this relaxes array typing in the absense of local variable info. Change-Id: I1b1aeb64a0842be3cffe70c02418444457abe972 --- dx/src/com/android/dx/cf/code/BaseMachine.java | 23 +++++++++++++- dx/src/com/android/dx/cf/code/ExecutionStack.java | 38 +++++++++++++++++++++++ dx/src/com/android/dx/cf/code/Machine.java | 8 +++++ dx/src/com/android/dx/cf/code/Simulator.java | 17 +++++++--- 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/dx/src/com/android/dx/cf/code/BaseMachine.java b/dx/src/com/android/dx/cf/code/BaseMachine.java index bdb322964..c56dd3e72 100644 --- a/dx/src/com/android/dx/cf/code/BaseMachine.java +++ b/dx/src/com/android/dx/cf/code/BaseMachine.java @@ -63,6 +63,9 @@ public abstract class BaseMachine implements Machine { /** {@code >= -1;} last local accessed */ private int localIndex; + /** specifies if local has info in the local variable table */ + private boolean localInfo; + /** {@code null-ok;} local target spec, if salient and calculated */ private RegisterSpec localTarget; @@ -107,6 +110,7 @@ public abstract class BaseMachine implements Machine { auxCases = null; auxInitValues = null; localIndex = -1; + localInfo = false; localTarget = null; resultCount = -1; } @@ -196,7 +200,7 @@ public abstract class BaseMachine implements Machine { } if (! Merger.isPossiblyAssignableFrom(type3, args[2])) { - throw new SimException("expected type " + type2.toHuman() + + throw new SimException("expected type " + type3.toHuman() + " but found " + args[2].getType().toHuman()); } } @@ -209,6 +213,11 @@ public abstract class BaseMachine implements Machine { localIndex = idx; } + /** {@inheritDoc} */ + public final void localInfo(boolean local) { + localInfo = local; + } + /** {@inheritDoc} */ public final void auxType(Type type) { auxType = type; @@ -359,6 +368,15 @@ public abstract class BaseMachine implements Machine { return localIndex; } + /** + * Gets whether the loaded local has info in the local variable table. + * + * @return {@code true} if local arg has info in the local variable table + */ + protected final boolean getLocalInfo() { + return localInfo; + } + /** * Gets the target local register spec of the current operation, if any. * The local target spec is the combination of the values indicated @@ -533,6 +551,9 @@ public abstract class BaseMachine implements Machine { } else { ExecutionStack stack = frame.getStack(); for (int i = 0; i < resultCount; i++) { + if (localInfo) { + stack.setLocal(); + } stack.push(results[i]); } } diff --git a/dx/src/com/android/dx/cf/code/ExecutionStack.java b/dx/src/com/android/dx/cf/code/ExecutionStack.java index 8f5b528b2..51f633447 100644 --- a/dx/src/com/android/dx/cf/code/ExecutionStack.java +++ b/dx/src/com/android/dx/cf/code/ExecutionStack.java @@ -33,6 +33,11 @@ public final class ExecutionStack extends MutabilityControl { /** {@code non-null;} array of stack contents */ private final TypeBearer[] stack; + /** + * {@code non-null;} array specifying whether stack contents have entries + * in the local variable table + */ + private final boolean[] local; /** * {@code >= 0;} stack pointer (points one past the end) / current stack * size @@ -48,6 +53,7 @@ public final class ExecutionStack extends MutabilityControl { public ExecutionStack(int maxStack) { super(maxStack != 0); stack = new TypeBearer[maxStack]; + local = new boolean[maxStack]; stackPtr = 0; } @@ -60,6 +66,7 @@ public final class ExecutionStack extends MutabilityControl { 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; @@ -131,6 +138,7 @@ public final class ExecutionStack extends MutabilityControl { for (int i = 0; i < stackPtr; i++) { stack[i] = null; + local[i] = false; } stackPtr = 0; @@ -170,6 +178,15 @@ public final class ExecutionStack extends MutabilityControl { stackPtr++; } + /** + * Flags the next value pushed onto the stack as having local info. + */ + public void setLocal() { + throwIfImmutable(); + + local[stackPtr] = true; + } + /** * 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 @@ -192,6 +209,26 @@ public final class ExecutionStack extends MutabilityControl { return stack[stackPtr - n - 1]; } + /** + * 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()} + */ + public boolean peekLocal(int n) { + if (n < 0) { + throw new IllegalArgumentException("n < 0"); + } + + if (n >= stackPtr) { + throw new SimException("stack: underflow"); + } + + return local[stackPtr - n - 1]; + } + /** * Peeks at the {@code n}th element down from the top of the * stack, returning the type per se, as opposed to the @@ -216,6 +253,7 @@ public final class ExecutionStack extends MutabilityControl { TypeBearer result = peek(0); stack[stackPtr - 1] = null; + local[stackPtr - 1] = false; stackPtr -= result.getType().getCategory(); return result; diff --git a/dx/src/com/android/dx/cf/code/Machine.java b/dx/src/com/android/dx/cf/code/Machine.java index 72ba3b456..a81feaff3 100644 --- a/dx/src/com/android/dx/cf/code/Machine.java +++ b/dx/src/com/android/dx/cf/code/Machine.java @@ -112,6 +112,14 @@ public interface Machine { */ public void localArg(Frame frame, int idx); + /** + * Used to specify if a loaded local variable has info in the local + * variable table. + * + * @param local {@code true} if local arg has info in local variable table + */ + public void localInfo(boolean local); + /** * Indicates that the salient type of this operation is as * given. This differentiates between, for example, the various diff --git a/dx/src/com/android/dx/cf/code/Simulator.java b/dx/src/com/android/dx/cf/code/Simulator.java index 081230596..eedc37990 100644 --- a/dx/src/com/android/dx/cf/code/Simulator.java +++ b/dx/src/com/android/dx/cf/code/Simulator.java @@ -367,13 +367,21 @@ public class Simulator { * element type is category 2, we have to skip * over one extra stack slot to find the array. */ - Type foundArrayType = - frame.getStack().peekType(type.isCategory1() ? 2 : 3); + ExecutionStack stack = frame.getStack(); + int peekDepth = type.isCategory1() ? 2 : 3; + Type foundArrayType = stack.peekType(peekDepth); + boolean foundArrayLocal = stack.peekLocal(peekDepth); + Type requiredArrayType = requiredArrayTypeFor(type, foundArrayType); - // Make type agree with the discovered requiredArrayType. - type = requiredArrayType.getComponentType(); + /* + * Make type agree with the discovered requiredArrayType + * if it has local info. + */ + if (foundArrayLocal) { + type = requiredArrayType.getComponentType(); + } machine.popArgs(frame, requiredArrayType, Type.INT, type); break; @@ -578,6 +586,7 @@ public class Simulator { case ByteOps.ILOAD: case ByteOps.RET: { machine.localArg(frame, idx); + machine.localInfo(local != null); machine.auxType(type); break; } -- cgit v1.2.3