use of com.android.dx.util.IntList in project buck by facebook.
the class LocalVariableExtractor method processBlock.
/**
* Processes a single block.
*
* @param label {@code >= 0;} label of the block to process
*/
private void processBlock(int label) {
RegisterSpecSet primaryState = resultInfo.mutableCopyOfStarts(label);
BasicBlock block = blocks.labelToBlock(label);
InsnList insns = block.getInsns();
int insnSz = insns.size();
/*
* We may have to treat the last instruction specially: If it
* can (but doesn't always) throw, and the exception can be
* caught within the same method, then we need to use the
* state *before* executing it to be what is merged into
* exception targets.
*/
boolean canThrowDuringLastInsn = block.hasExceptionHandlers() && (insns.getLast().getResult() != null);
int freezeSecondaryStateAt = insnSz - 1;
RegisterSpecSet secondaryState = primaryState;
for (int i = 0; i < insnSz; i++) {
if (canThrowDuringLastInsn && (i == freezeSecondaryStateAt)) {
// Until this point, primaryState == secondaryState.
primaryState.setImmutable();
primaryState = primaryState.mutableCopy();
}
Insn insn = insns.get(i);
RegisterSpec result;
result = insn.getLocalAssignment();
if (result == null) {
/*
* If an assignment assigns over an existing local, make
* sure to mark the local as going out of scope.
*/
result = insn.getResult();
if (result != null && primaryState.get(result.getReg()) != null) {
primaryState.remove(primaryState.get(result.getReg()));
}
continue;
}
result = result.withSimpleType();
RegisterSpec already = primaryState.get(result);
/*
* The equals() check ensures we only add new info if
* the instruction causes a change to the set of
* active variables.
*/
if (!result.equals(already)) {
/*
* If this insn represents a local moving from one register
* to another, remove the association between the old register
* and the local.
*/
RegisterSpec previous = primaryState.localItemToSpec(result.getLocalItem());
if (previous != null && (previous.getReg() != result.getReg())) {
primaryState.remove(previous);
}
resultInfo.addAssignment(insn, result);
primaryState.put(result);
}
}
primaryState.setImmutable();
/*
* Merge this state into the start state for each successor,
* and update the work set where required (that is, in cases
* where the start state for a block changes).
*/
IntList successors = block.getSuccessors();
int succSz = successors.size();
int primarySuccessor = block.getPrimarySuccessor();
for (int i = 0; i < succSz; i++) {
int succ = successors.get(i);
RegisterSpecSet state = (succ == primarySuccessor) ? primaryState : secondaryState;
if (resultInfo.mergeStarts(succ, state)) {
Bits.set(workSet, succ);
}
}
}
use of com.android.dx.util.IntList in project buck by facebook.
the class RopMethod method calcPredecessors.
/**
* Calculates the predecessor sets for each block as well as for the
* exit.
*/
private void calcPredecessors() {
int maxLabel = blocks.getMaxLabel();
IntList[] predecessors = new IntList[maxLabel];
IntList exitPredecessors = new IntList(10);
int sz = blocks.size();
/*
* For each block, find its successors, and add the block's label to
* the successor's predecessors.
*/
for (int i = 0; i < sz; i++) {
BasicBlock one = blocks.get(i);
int label = one.getLabel();
IntList successors = one.getSuccessors();
int ssz = successors.size();
if (ssz == 0) {
// This block exits.
exitPredecessors.add(label);
} else {
for (int j = 0; j < ssz; j++) {
int succLabel = successors.get(j);
IntList succPreds = predecessors[succLabel];
if (succPreds == null) {
succPreds = new IntList(10);
predecessors[succLabel] = succPreds;
}
succPreds.add(label);
}
}
}
// Sort and immutablize all the predecessor lists.
for (int i = 0; i < maxLabel; i++) {
IntList preds = predecessors[i];
if (preds != null) {
preds.sort();
preds.setImmutable();
}
}
exitPredecessors.sort();
exitPredecessors.setImmutable();
/*
* The start label might not ever have had any predecessors
* added to it (probably doesn't, because of how Java gets
* translated into rop form). So, check for this and rectify
* the situation if required.
*/
if (predecessors[firstLabel] == null) {
predecessors[firstLabel] = IntList.EMPTY;
}
this.predecessors = predecessors;
this.exitPredecessors = exitPredecessors;
}
use of com.android.dx.util.IntList in project J2ME-Loader by nikita36078.
the class ByteCatchList method toTargetList.
/**
* Returns a target list corresponding to this instance. The result
* is a list of all the exception handler addresses, with the given
* {@code noException} address appended if appropriate. The
* result is automatically made immutable.
*
* @param noException {@code >= -1;} the no-exception address to append, or
* {@code -1} not to append anything
* @return {@code non-null;} list of exception targets, with
* {@code noException} appended if necessary
*/
public IntList toTargetList(int noException) {
if (noException < -1) {
throw new IllegalArgumentException("noException < -1");
}
boolean hasDefault = (noException >= 0);
int sz = size();
if (sz == 0) {
if (hasDefault) {
/*
* The list is empty, but there is a no-exception
* address; so, the result is just that address.
*/
return IntList.makeImmutable(noException);
}
/*
* The list is empty and there isn't even a no-exception
* address.
*/
return IntList.EMPTY;
}
IntList result = new IntList(sz + (hasDefault ? 1 : 0));
for (int i = 0; i < sz; i++) {
result.add(get(i).getHandlerPc());
}
if (hasDefault) {
result.add(noException);
}
result.setImmutable();
return result;
}
use of com.android.dx.util.IntList in project J2ME-Loader by nikita36078.
the class Frame method mergeWith.
/**
* Merges two frames. If the merged result is the same as this frame,
* then this instance is returned.
*
* @param other {@code non-null;} another frame
* @return {@code non-null;} the result of merging the two frames
*/
public Frame mergeWith(Frame other) {
LocalsArray resultLocals;
ExecutionStack resultStack;
IntList resultSubroutines;
resultLocals = getLocals().merge(other.getLocals());
resultStack = getStack().merge(other.getStack());
resultSubroutines = mergeSubroutineLists(other.subroutines);
resultLocals = adjustLocalsForSubroutines(resultLocals, resultSubroutines);
if ((resultLocals == getLocals()) && (resultStack == getStack()) && subroutines == resultSubroutines) {
return this;
}
return new Frame(resultLocals, resultStack, resultSubroutines);
}
use of com.android.dx.util.IntList in project J2ME-Loader by nikita36078.
the class Frame method subFrameForLabel.
/**
* Returns a Frame instance representing the frame state that should
* be used when returning from a subroutine. The stack state of all
* subroutine invocations is identical, but the locals state may differ.
*
* @param startLabel {@code >=0;} The label of the returning subroutine's
* start block
* @param subLabel {@code >=0;} A calling label of a subroutine
* @return {@code null-ok;} an appropriatly-constructed instance, or null
* if label is not in the set
*/
public Frame subFrameForLabel(int startLabel, int subLabel) {
LocalsArray subLocals = null;
if (locals instanceof LocalsArraySet) {
subLocals = ((LocalsArraySet) locals).subArrayForLabel(subLabel);
}
IntList newSubroutines;
try {
newSubroutines = subroutines.mutableCopy();
if (newSubroutines.pop() != startLabel) {
throw new RuntimeException("returning from invalid subroutine");
}
newSubroutines.setImmutable();
} catch (IndexOutOfBoundsException ex) {
throw new RuntimeException("returning from invalid subroutine");
} catch (NullPointerException ex) {
throw new NullPointerException("can't return from non-subroutine");
}
return (subLocals == null) ? null : new Frame(subLocals, stack, newSubroutines);
}
Aggregations