/** {@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;
auxCases = null;
auxInitValues = null;
localIndex = -1;
+ localInfo = false;
localTarget = null;
resultCount = -1;
}
}
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());
}
}
}
/** {@inheritDoc} */
+ public final void localInfo(boolean local) {
+ localInfo = local;
+ }
+
+ /** {@inheritDoc} */
public final void auxType(Type type) {
auxType = type;
}
}
/**
+ * 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
} else {
ExecutionStack stack = frame.getStack();
for (int i = 0; i < resultCount; i++) {
+ if (localInfo) {
+ stack.setLocal();
+ }
stack.push(results[i]);
}
}
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
*/
public ExecutionStack(int maxStack) {
super(maxStack != 0);
stack = new TypeBearer[maxStack];
+ local = new boolean[maxStack];
stackPtr = 0;
}
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;
for (int i = 0; i < stackPtr; i++) {
stack[i] = null;
+ local[i] = false;
}
stackPtr = 0;
}
/**
+ * 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
/**
* 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()}.
TypeBearer result = peek(0);
stack[stackPtr - 1] = null;
+ local[stackPtr - 1] = false;
stackPtr -= result.getType().getCategory();
return result;
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
* 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;
case ByteOps.ILOAD:
case ByteOps.RET: {
machine.localArg(frame, idx);
+ machine.localInfo(local != null);
machine.auxType(type);
break;
}