use of com.android.dx.util.IntList in project J2ME-Loader by nikita36078.
the class Frame method mergeSubroutineLists.
/**
* Merges this frame's subroutine lists with another. The result
* is the deepest common nesting (effectively, the common prefix of the
* two lists).
*
* @param otherSubroutines label list of subroutine start blocks, from
* least-nested to most-nested.
* @return {@code non-null;} merged subroutine nest list as described above
*/
private IntList mergeSubroutineLists(IntList otherSubroutines) {
if (subroutines.equals(otherSubroutines)) {
return subroutines;
}
IntList resultSubroutines = new IntList();
int szSubroutines = subroutines.size();
int szOthers = otherSubroutines.size();
for (int i = 0; i < szSubroutines && i < szOthers && (subroutines.get(i) == otherSubroutines.get(i)); i++) {
resultSubroutines.add(i);
}
resultSubroutines.setImmutable();
return resultSubroutines;
}
use of com.android.dx.util.IntList in project J2ME-Loader by nikita36078.
the class Ropper method forEachNonSubBlockDepthFirst0.
/**
* Visits each block once in depth-first successor order, ignoring
* {@code jsr} targets. Worker for {@link #forEachNonSubBlockDepthFirst}.
*
* @param next next block to visit
* @param v callback interface
* @param visited set of blocks already visited
*/
private void forEachNonSubBlockDepthFirst0(BasicBlock next, BasicBlock.Visitor v, BitSet visited) {
v.visitBlock(next);
visited.set(next.getLabel());
IntList successors = next.getSuccessors();
int sz = successors.size();
for (int i = 0; i < sz; i++) {
int succ = successors.get(i);
if (visited.get(succ)) {
continue;
}
if (isSubroutineCaller(next) && i > 0) {
// ignore jsr targets
continue;
}
/*
* Ignore missing labels: they're successors of
* subroutines that never invoke a ret.
*/
int idx = labelToResultIndex(succ);
if (idx >= 0) {
forEachNonSubBlockDepthFirst0(result.get(idx), v, visited);
}
}
}
use of com.android.dx.util.IntList in project J2ME-Loader by nikita36078.
the class Ropper method deleteUnreachableBlocks.
/**
* Deletes all blocks that cannot be reached. This is run to delete
* original subroutine blocks after subroutine inlining.
*/
private void deleteUnreachableBlocks() {
final IntList reachableLabels = new IntList(result.size());
// subroutine inlining is done now and we won't update this list here
resultSubroutines.clear();
forEachNonSubBlockDepthFirst(getSpecialLabel(PARAM_ASSIGNMENT), new BasicBlock.Visitor() {
public void visitBlock(BasicBlock b) {
reachableLabels.add(b.getLabel());
}
});
reachableLabels.sort();
for (int i = result.size() - 1; i >= 0; i--) {
if (reachableLabels.indexOf(result.get(i).getLabel()) < 0) {
result.remove(i);
// unnecessary here really, since subroutine inlining is done
// resultSubroutines.remove(i);
}
}
}
use of com.android.dx.util.IntList in project J2ME-Loader by nikita36078.
the class Ropper method inlineSubroutines.
/**
* Inlines any subroutine calls.
*/
private void inlineSubroutines() {
final IntList reachableSubroutineCallerLabels = new IntList(4);
/*
* Compile a list of all subroutine calls reachable
* through the normal (non-subroutine) flow. We do this first, since
* we'll be affecting the call flow as we go.
*
* Start at label 0 -- the param assignment block has nothing for us
*/
forEachNonSubBlockDepthFirst(0, new BasicBlock.Visitor() {
public void visitBlock(BasicBlock b) {
if (isSubroutineCaller(b)) {
reachableSubroutineCallerLabels.add(b.getLabel());
}
}
});
/*
* Convert the resultSubroutines list, indexed by block index,
* to a label-to-subroutines mapping used by the inliner.
*/
int largestAllocedLabel = getAvailableLabel();
ArrayList<IntList> labelToSubroutines = new ArrayList<IntList>(largestAllocedLabel);
for (int i = 0; i < largestAllocedLabel; i++) {
labelToSubroutines.add(null);
}
for (int i = 0; i < result.size(); i++) {
BasicBlock b = result.get(i);
if (b == null) {
continue;
}
IntList subroutineList = resultSubroutines.get(i);
labelToSubroutines.set(b.getLabel(), subroutineList);
}
/*
* Inline all reachable subroutines.
* Inner subroutines will be inlined as they are encountered.
*/
int sz = reachableSubroutineCallerLabels.size();
for (int i = 0; i < sz; i++) {
int label = reachableSubroutineCallerLabels.get(i);
new SubroutineInliner(new LabelAllocator(getAvailableLabel()), labelToSubroutines).inlineSubroutineCalledFrom(labelToBlock(label));
}
// Now find the blocks that aren't reachable and remove them
deleteUnreachableBlocks();
}
use of com.android.dx.util.IntList in project J2ME-Loader by nikita36078.
the class BasicBlockList method catchesEqual.
/**
* Compares the catches of two blocks for equality. This includes
* both the catch types and target labels.
*
* @param block1 {@code non-null;} one block to compare
* @param block2 {@code non-null;} the other block to compare
* @return {@code true} if the two blocks' non-primary successors
* are identical
*/
public boolean catchesEqual(BasicBlock block1, BasicBlock block2) {
TypeList catches1 = block1.getExceptionHandlerTypes();
TypeList catches2 = block2.getExceptionHandlerTypes();
if (!StdTypeList.equalContents(catches1, catches2)) {
return false;
}
IntList succ1 = block1.getSuccessors();
IntList succ2 = block2.getSuccessors();
// Both are guaranteed to be the same size.
int size = succ1.size();
int primary1 = block1.getPrimarySuccessor();
int primary2 = block2.getPrimarySuccessor();
if (((primary1 == -1) || (primary2 == -1)) && (primary1 != primary2)) {
/*
* For the current purpose, both blocks in question must
* either both have a primary or both not have a primary to
* be considered equal, and it turns out here that that's not
* the case.
*/
return false;
}
for (int i = 0; i < size; i++) {
int label1 = succ1.get(i);
int label2 = succ2.get(i);
if (label1 == primary1) {
/*
* It should be the case that block2's primary is at the
* same index. If not, we consider the blocks unequal for
* the current purpose.
*/
if (label2 != primary2) {
return false;
}
continue;
}
if (label1 != label2) {
return false;
}
}
return true;
}
Aggregations