use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
the class RopperMachine method getSources.
/**
* Helper for {@link #run}, which gets the list of sources for the.
* instruction.
*
* @param opcode the opcode being translated
* @param stackPointer {@code >= 0;} the stack pointer after the
* instruction's arguments have been popped
* @return {@code non-null;} the sources
*/
private RegisterSpecList getSources(int opcode, int stackPointer) {
int count = argCount();
if (count == 0) {
// We get an easy out if there aren't any sources.
return RegisterSpecList.EMPTY;
}
int localIndex = getLocalIndex();
RegisterSpecList sources;
if (localIndex >= 0) {
// The instruction is operating on a local variable.
sources = new RegisterSpecList(1);
sources.set(0, RegisterSpec.make(localIndex, arg(0)));
} else {
sources = new RegisterSpecList(count);
int regAt = stackPointer;
for (int i = 0; i < count; i++) {
RegisterSpec spec = RegisterSpec.make(regAt, arg(i));
sources.set(i, spec);
regAt += spec.getCategory();
}
switch(opcode) {
case ByteOps.IASTORE:
{
/*
* The Java argument order for array stores is
* (array, index, value), but the rop argument
* order is (value, array, index). The following
* code gets the right arguments in the right
* places.
*/
if (count != 3) {
throw new RuntimeException("shouldn't happen");
}
RegisterSpec array = sources.get(0);
RegisterSpec index = sources.get(1);
RegisterSpec value = sources.get(2);
sources.set(0, value);
sources.set(1, array);
sources.set(2, index);
break;
}
case ByteOps.PUTFIELD:
{
/*
* Similar to above: The Java argument order for
* putfield is (object, value), but the rop
* argument order is (value, object).
*/
if (count != 2) {
throw new RuntimeException("shouldn't happen");
}
RegisterSpec obj = sources.get(0);
RegisterSpec value = sources.get(1);
sources.set(0, value);
sources.set(1, obj);
break;
}
}
}
sources.setImmutable();
return sources;
}
use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
the class DalvInsn method expandedPrefix.
/**
* Gets the instruction prefix required, if any, to use in an expanded
* version of this instance. Will not generate moves for registers
* marked compatible to the format by the given BitSet.
*
* @see #expandedVersion
*
* @param compatRegs {@code non-null;} set of compatible registers
* @return {@code null-ok;} the prefix, if any
*/
public DalvInsn expandedPrefix(BitSet compatRegs) {
RegisterSpecList regs = registers;
boolean firstBit = compatRegs.get(0);
if (hasResult())
compatRegs.set(0);
regs = regs.subset(compatRegs);
if (hasResult())
compatRegs.set(0, firstBit);
if (regs.size() == 0)
return null;
return new HighRegisterPrefix(position, regs);
}
use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
the class EscapeAnalysis method processUse.
/**
* Handles non-phi uses of new objects. Checks to see how instruction is
* used and updates the escape state accordingly.
*
* @param def {@code non-null;} register holding definition of new object
* @param use {@code non-null;} use of object being processed
* @param escSet {@code non-null;} EscapeSet for the object
* @param regWorklist {@code non-null;} worklist of instructions left to
* process for this object
*/
private void processUse(RegisterSpec def, SsaInsn use, EscapeSet escSet, ArrayList<RegisterSpec> regWorklist) {
int useOpcode = use.getOpcode().getOpcode();
switch(useOpcode) {
case RegOps.MOVE:
// Follow uses of the move by adding it to the worklist
escSet.regSet.set(use.getResult().getReg());
regWorklist.add(use.getResult());
break;
case RegOps.IF_EQ:
case RegOps.IF_NE:
case RegOps.CHECK_CAST:
// Compared objects can't be replaced, so promote if necessary
if (escSet.escape.compareTo(EscapeState.METHOD) < 0) {
escSet.escape = EscapeState.METHOD;
}
break;
case RegOps.APUT:
// For array puts, check for a constant array index
RegisterSpec putIndex = use.getSources().get(2);
if (!putIndex.getTypeBearer().isConstant()) {
// If not constant, array can't be replaced
escSet.replaceableArray = false;
}
// Intentional fallthrough
case RegOps.PUT_FIELD:
// Skip non-object puts
RegisterSpec putValue = use.getSources().get(0);
if (putValue.getTypeBearer().getBasicType() != Type.BT_OBJECT) {
break;
}
escSet.replaceableArray = false;
// Raise 1st object's escape state to 2nd if 2nd is higher
RegisterSpecList sources = use.getSources();
if (sources.get(0).getReg() == def.getReg()) {
int setIndex = findSetIndex(sources.get(1));
if (setIndex != latticeValues.size()) {
EscapeSet parentSet = latticeValues.get(setIndex);
addEdge(parentSet, escSet);
if (escSet.escape.compareTo(parentSet.escape) < 0) {
escSet.escape = parentSet.escape;
}
}
} else {
int setIndex = findSetIndex(sources.get(0));
if (setIndex != latticeValues.size()) {
EscapeSet childSet = latticeValues.get(setIndex);
addEdge(escSet, childSet);
if (childSet.escape.compareTo(escSet.escape) < 0) {
childSet.escape = escSet.escape;
}
}
}
break;
case RegOps.AGET:
// For array gets, check for a constant array index
RegisterSpec getIndex = use.getSources().get(1);
if (!getIndex.getTypeBearer().isConstant()) {
// If not constant, array can't be replaced
escSet.replaceableArray = false;
}
break;
case RegOps.PUT_STATIC:
// Static puts cause an object to escape globally
escSet.escape = EscapeState.GLOBAL;
break;
case RegOps.INVOKE_STATIC:
case RegOps.INVOKE_VIRTUAL:
case RegOps.INVOKE_SUPER:
case RegOps.INVOKE_DIRECT:
case RegOps.INVOKE_INTERFACE:
case RegOps.RETURN:
case RegOps.THROW:
// These operations cause an object to escape interprocedurally
escSet.escape = EscapeState.INTER;
break;
default:
break;
}
}
use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
the class LiteralOpUpgrader method run.
/**
* Run the literal op upgrader
*/
private void run() {
final TranslationAdvice advice = Optimizer.getAdvice();
ssaMeth.forEachInsn(new SsaInsn.Visitor() {
public void visitMoveInsn(NormalSsaInsn insn) {
// do nothing
}
public void visitPhiInsn(PhiInsn insn) {
// do nothing
}
public void visitNonMoveInsn(NormalSsaInsn insn) {
Insn originalRopInsn = insn.getOriginalRopInsn();
Rop opcode = originalRopInsn.getOpcode();
RegisterSpecList sources = insn.getSources();
// Replace insns with constant results with const insns
if (tryReplacingWithConstant(insn))
return;
if (sources.size() != 2) {
// We're only dealing with two-source insns here.
return;
}
if (opcode.getBranchingness() == Rop.BRANCH_IF) {
/*
* An if instruction can become an if-*z instruction.
*/
if (isConstIntZeroOrKnownNull(sources.get(0))) {
replacePlainInsn(insn, sources.withoutFirst(), RegOps.flippedIfOpcode(opcode.getOpcode()), null);
} else if (isConstIntZeroOrKnownNull(sources.get(1))) {
replacePlainInsn(insn, sources.withoutLast(), opcode.getOpcode(), null);
}
} else if (advice.hasConstantOperation(opcode, sources.get(0), sources.get(1))) {
insn.upgradeToLiteral();
} else if (opcode.isCommutative() && advice.hasConstantOperation(opcode, sources.get(1), sources.get(0))) {
/*
* An instruction can be commuted to a literal operation
*/
insn.setNewSources(RegisterSpecList.make(sources.get(1), sources.get(0)));
insn.upgradeToLiteral();
}
}
});
}
use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
the class NormalSsaInsn method upgradeToLiteral.
/**
* Upgrades this insn to a version that represents the constant source
* literally. If the upgrade is not possible, this does nothing.
*
* @see Insn#withSourceLiteral
*/
public void upgradeToLiteral() {
RegisterSpecList oldSources = insn.getSources();
insn = insn.withSourceLiteral();
getBlock().getParent().onSourcesChanged(this, oldSources);
}
Aggregations