// Typical case: a freshly marked variable initialization that
// requires some value on the stack.
int popCount = instruction.stackPopCount(clazz);
if (popCount > 0)
{
TracedStack tracedStack =
partialEvaluator.getStackBefore(offset);
int stackSize = tracedStack.size();
int requiredPopCount = 0;
int requiredPushCount = 0;
for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
{
boolean stackSimplifiedBefore =
isStackSimplifiedBefore(offset, stackIndex);
boolean stackEntryPresentBefore =
isStackEntryPresentBefore(offset, stackIndex);
if (stackSimplifiedBefore)
{
// Is this stack entry pushed by any producer
// (maybe an exception in an exception handler)?
if (isStackEntryPresentBefore(offset, stackIndex))
{
// Mark all produced stack entries.
markStackEntryProducers(offset, stackIndex);
// Remember to pop it.
requiredPopCount++;
}
}
else
{
// Is this stack entry pushed by any producer
// (because it is required by other consumers)?
if (stackEntryPresentBefore)
{
// Mark all produced stack entries.
markStackEntryProducers(offset, stackIndex);
}
else
{
// Remember to push it.
requiredPushCount++;
}
}
}
// Pop some unnecessary stack entries.
if (requiredPopCount > 0)
{
if (DEBUG) System.out.println(" Inserting before marked consumer "+instruction.toString(offset));
insertPopInstructions(offset, false, true, popCount);
}
// Push some necessary stack entries.
if (requiredPushCount > 0)
{
if (DEBUG) System.out.println(" Inserting before marked consumer "+instruction.toString(offset));
if (requiredPushCount > (instruction.isCategory2() ? 2 : 1))
{
throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"] at ["+offset+"]");
}
insertPushInstructions(offset, false, true, tracedStack.getTop(0).computationalType());
}
}
// Check all other stack entries, if this is a return
// instruction.
// Typical case: the code returns, but there are still other
// entries left on the stack. These have to be consistent.
InstructionOffsetValue branchTargets =
partialEvaluator.branchTargets(offset);
if (branchTargets != null &&
branchTargets.instructionOffsetCount() == 0)
{
TracedStack tracedStack =
partialEvaluator.getStackBefore(offset);
int unpoppedStackSize = tracedStack.size() - popCount;
for (int stackIndex = 0; stackIndex < unpoppedStackSize; stackIndex++)
{
// Is this stack entry pushed by any producer
// (because it is required by other consumers)?
if (isStackEntryPresentBefore(offset, stackIndex))
{
// Mark all produced stack entries.
markStackEntryProducers(offset, stackIndex);
}
}
}
// Check all stack entries that are pushed.
// Typical case: a return value that wasn't really required and
// that should be popped.
int pushCount = instruction.stackPushCount(clazz);
if (pushCount > 0)
{
TracedStack tracedStack =
partialEvaluator.getStackAfter(offset);
int stackSize = tracedStack.size();
int requiredPopCount = 0;
for (int stackIndex = stackSize - pushCount; stackIndex < stackSize; stackIndex++)
{
// Is the stack entry required by consumers?
if (!isStackEntryNecessaryAfter(offset, stackIndex))
{
// Remember to pop it.
requiredPopCount++;
}
}
// Pop the unnecessary stack entries.
if (requiredPopCount > 0)
{
if (DEBUG) System.out.println(" Inserting after marked producer "+instruction.toString(offset));
insertPopInstructions(offset, false, false, requiredPopCount);
}
}
}
else
{
// Check all stack entries that would be popped.
// Typical case: a stack value that is required elsewhere and
// that still has to be popped.
int popCount = instruction.stackPopCount(clazz);
if (popCount > 0)
{
TracedStack tracedStack =
partialEvaluator.getStackBefore(offset);
int stackSize = tracedStack.size();
int expectedPopCount = 0;
for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
{
// Is this stack entry pushed by any producer
// (because it is required by other consumers)?
if (isStackEntryPresentBefore(offset, stackIndex))
{
// Mark all produced stack entries.
markStackEntryProducers(offset, stackIndex);
// Remember to pop it.
expectedPopCount++;
}
}
// Pop the unnecessary stack entries.
if (expectedPopCount > 0)
{
if (DEBUG) System.out.println(" Replacing unmarked consumer "+instruction.toString(offset));
insertPopInstructions(offset, true, false, expectedPopCount);
}
}
// Check all stack entries that would be pushed.
// Typical case: never.
int pushCount = instruction.stackPushCount(clazz);
if (pushCount > 0)
{
TracedStack tracedStack =
partialEvaluator.getStackAfter(offset);
int stackSize = tracedStack.size();
int expectedPushCount = 0;
for (int stackIndex = stackSize - pushCount; stackIndex < stackSize; stackIndex++)
{
// Is the stack entry required by consumers?
if (isStackEntryNecessaryAfter(offset, stackIndex))
{
// Remember to push it.
expectedPushCount++;
}
}
// Push some necessary stack entries.
if (expectedPushCount > 0)
{
if (DEBUG) System.out.println(" Replacing unmarked producer "+instruction.toString(offset));
insertPushInstructions(offset, true, false, tracedStack.getTop(0).computationalType());
}
}
}
}