summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeffhao <jeffhao@google.com>2011-03-11 16:07:48 -0800
committerjeffhao <jeffhao@google.com>2011-03-11 16:07:48 -0800
commitc31f795aef67a0d6af9abe4610db5ecae8d30c19 (patch)
tree4a774c1417666d78b262fbc40c7387ef59c05ed3
parentd8a16d35e40e2894952bd6b04036e1d4240d0bac (diff)
downloadandroid_dalvik-c31f795aef67a0d6af9abe4610db5ecae8d30c19.tar.gz
android_dalvik-c31f795aef67a0d6af9abe4610db5ecae8d30c19.tar.bz2
android_dalvik-c31f795aef67a0d6af9abe4610db5ecae8d30c19.zip
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
-rw-r--r--dx/src/com/android/dx/cf/code/BaseMachine.java23
-rw-r--r--dx/src/com/android/dx/cf/code/ExecutionStack.java38
-rw-r--r--dx/src/com/android/dx/cf/code/Machine.java8
-rw-r--r--dx/src/com/android/dx/cf/code/Simulator.java17
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());
}
}
@@ -210,6 +214,11 @@ public abstract class BaseMachine implements Machine {
}
/** {@inheritDoc} */
+ public final void localInfo(boolean local) {
+ localInfo = local;
+ }
+
+ /** {@inheritDoc} */
public final void auxType(Type type) {
auxType = type;
}
@@ -360,6 +369,15 @@ public abstract class BaseMachine implements Machine {
}
/**
+ * 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
* by a previous call to {@link #localTarget} with the type of what
@@ -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
@@ -34,6 +34,11 @@ public final class ExecutionStack extends MutabilityControl {
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;
@@ -171,6 +179,15 @@ public final class ExecutionStack extends MutabilityControl {
}
/**
+ * 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
* this will return {@code null} if the indicated element is the
@@ -194,6 +211,26 @@ public final class ExecutionStack extends MutabilityControl {
/**
* 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
* <i>type-bearer</i>. This method is just a convenient shorthand
* for {@code peek(n).getType()}.
@@ -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
@@ -113,6 +113,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
* arithmetic opcodes, which, by the time they hit a
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;
}