Search in sources :

Example 11 with TypeBearer

use of com.android.dx.rop.type.TypeBearer in project buck by facebook.

the class ExecutionStack method change.

/**
     * Changes an element already on a stack. This method is useful in limited
     * contexts, particularly when merging two instances. As such, it places
     * the following restriction on its behavior: You may only replace
     * values with other values of the same category.
     *
     * @param n {@code >= 0;} which element to change, where {@code 0} is
     * the top element of the stack
     * @param type {@code non-null;} type of the new value
     * @throws SimException thrown if {@code n >= size()} or
     * the action is otherwise prohibited
     */
public void change(int n, TypeBearer type) {
    throwIfImmutable();
    try {
        type = type.getFrameType();
    } catch (NullPointerException ex) {
        // Elucidate the exception.
        throw new NullPointerException("type == null");
    }
    int idx = stackPtr - n - 1;
    TypeBearer orig = stack[idx];
    if ((orig == null) || (orig.getType().getCategory() != type.getType().getCategory())) {
        throwSimException("incompatible substitution: " + stackElementString(orig) + " -> " + stackElementString(type));
    }
    stack[idx] = type;
}
Also used : TypeBearer(com.android.dx.rop.type.TypeBearer)

Example 12 with TypeBearer

use of com.android.dx.rop.type.TypeBearer in project buck by facebook.

the class Merger method mergeStack.

/**
     * Merges two stacks. If the merged result is the same as the first
     * argument, then return the first argument (not a copy).
     *
     * @param stack1 {@code non-null;} a stack
     * @param stack2 {@code non-null;} another stack
     * @return {@code non-null;} the result of merging the two stacks
     */
public static ExecutionStack mergeStack(ExecutionStack stack1, ExecutionStack stack2) {
    if (stack1 == stack2) {
        // Easy out.
        return stack1;
    }
    int sz = stack1.size();
    ExecutionStack result = null;
    if (stack2.size() != sz) {
        throw new SimException("mismatched stack depths");
    }
    for (int i = 0; i < sz; i++) {
        TypeBearer tb1 = stack1.peek(i);
        TypeBearer tb2 = stack2.peek(i);
        TypeBearer resultType = mergeType(tb1, tb2);
        if (resultType != tb1) {
            /*
                 * We only need to do anything when the result differs
                 * from what is in the first stack, since that's what the
                 * result gets initialized to.
                 */
            if (result == null) {
                result = stack1.copy();
            }
            try {
                if (resultType == null) {
                    throw new SimException("incompatible: " + tb1 + ", " + tb2);
                } else {
                    result.change(i, resultType);
                }
            } catch (SimException ex) {
                ex.addContext("...while merging stack[" + Hex.u2(i) + "]");
                throw ex;
            }
        }
    }
    if (result == null) {
        return stack1;
    }
    result.setImmutable();
    return result;
}
Also used : TypeBearer(com.android.dx.rop.type.TypeBearer)

Example 13 with TypeBearer

use of com.android.dx.rop.type.TypeBearer in project buck by facebook.

the class EscapeAnalysis method replaceUse.

/**
     * Replaces the use for a scalar replaceable array. Gets and puts become
     * move instructions, and array lengths and fills are handled. Can also
     * identify ArrayIndexOutOfBounds exceptions and throw them if detected.
     *
     * @param use {@code non-null;} move result instruction for array
     * @param prev {@code non-null;} instruction for instantiating new array
     * @param newRegs {@code non-null;} mapping of array indices to new
     * registers
     * @param deletedInsns {@code non-null;} set of instructions marked for
     * deletion
     */
private void replaceUse(SsaInsn use, SsaInsn prev, ArrayList<RegisterSpec> newRegs, HashSet<SsaInsn> deletedInsns) {
    int index;
    int length = newRegs.size();
    SsaInsn next;
    RegisterSpecList sources;
    RegisterSpec source, result;
    CstLiteralBits indexReg;
    switch(use.getOpcode().getOpcode()) {
        case RegOps.AGET:
            // Replace array gets with moves
            next = getMoveForInsn(use);
            sources = use.getSources();
            indexReg = ((CstLiteralBits) sources.get(1).getTypeBearer());
            index = indexReg.getIntBits();
            if (index < length) {
                source = newRegs.get(index);
                result = source.withReg(next.getResult().getReg());
                insertPlainInsnBefore(next, RegisterSpecList.make(source), result, RegOps.MOVE, null);
            } else {
                // Throw an exception if the index is out of bounds
                insertExceptionThrow(next, sources.get(1), deletedInsns);
                deletedInsns.add(next.getBlock().getInsns().get(2));
            }
            deletedInsns.add(next);
            break;
        case RegOps.APUT:
            // Replace array puts with moves
            sources = use.getSources();
            indexReg = ((CstLiteralBits) sources.get(2).getTypeBearer());
            index = indexReg.getIntBits();
            if (index < length) {
                source = sources.get(0);
                result = source.withReg(newRegs.get(index).getReg());
                insertPlainInsnBefore(use, RegisterSpecList.make(source), result, RegOps.MOVE, null);
                // Update the newReg entry to mark value as unknown now
                newRegs.set(index, result.withSimpleType());
            } else {
                // Throw an exception if the index is out of bounds
                insertExceptionThrow(use, sources.get(2), deletedInsns);
            }
            break;
        case RegOps.ARRAY_LENGTH:
            // Replace array lengths with const instructions
            TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
            //CstInteger lengthReg = CstInteger.make(length);
            next = getMoveForInsn(use);
            insertPlainInsnBefore(next, RegisterSpecList.EMPTY, next.getResult(), RegOps.CONST, (Constant) lengthReg);
            deletedInsns.add(next);
            break;
        case RegOps.MARK_LOCAL:
            // Remove mark local instructions
            break;
        case RegOps.FILL_ARRAY_DATA:
            // Create const instructions for each fill value
            Insn ropUse = use.getOriginalRopInsn();
            FillArrayDataInsn fill = (FillArrayDataInsn) ropUse;
            ArrayList<Constant> constList = fill.getInitValues();
            for (int i = 0; i < length; i++) {
                RegisterSpec newFill = RegisterSpec.make(newRegs.get(i).getReg(), (TypeBearer) constList.get(i));
                insertPlainInsnBefore(use, RegisterSpecList.EMPTY, newFill, RegOps.CONST, constList.get(i));
                // Update the newRegs to hold the new const value
                newRegs.set(i, newFill);
            }
            break;
        default:
    }
}
Also used : ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) FillArrayDataInsn(com.android.dx.rop.code.FillArrayDataInsn) Insn(com.android.dx.rop.code.Insn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) CstLiteralBits(com.android.dx.rop.cst.CstLiteralBits) FillArrayDataInsn(com.android.dx.rop.code.FillArrayDataInsn) Constant(com.android.dx.rop.cst.Constant) TypedConstant(com.android.dx.rop.cst.TypedConstant) TypeBearer(com.android.dx.rop.type.TypeBearer) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 14 with TypeBearer

use of com.android.dx.rop.type.TypeBearer in project buck by facebook.

the class PlainInsn method withSourceLiteral.

/** {@inheritDoc} */
@Override
public Insn withSourceLiteral() {
    RegisterSpecList sources = getSources();
    int szSources = sources.size();
    if (szSources == 0) {
        return this;
    }
    TypeBearer lastType = sources.get(szSources - 1).getTypeBearer();
    if (!lastType.isConstant()) {
        // Check for reverse subtraction, where first source is constant
        TypeBearer firstType = sources.get(0).getTypeBearer();
        if (szSources == 2 && firstType.isConstant()) {
            Constant cst = (Constant) firstType;
            RegisterSpecList newSources = sources.withoutFirst();
            Rop newRop = Rops.ropFor(getOpcode().getOpcode(), getResult(), newSources, cst);
            return new PlainCstInsn(newRop, getPosition(), getResult(), newSources, cst);
        }
        return this;
    } else {
        Constant cst = (Constant) lastType;
        RegisterSpecList newSources = sources.withoutLast();
        Rop newRop;
        try {
            // Check for constant subtraction and flip it to be addition
            int opcode = getOpcode().getOpcode();
            if (opcode == RegOps.SUB && cst instanceof CstInteger) {
                opcode = RegOps.ADD;
                cst = CstInteger.make(-((CstInteger) cst).getValue());
            }
            newRop = Rops.ropFor(opcode, getResult(), newSources, cst);
        } catch (IllegalArgumentException ex) {
            // There's no rop for this case
            return this;
        }
        return new PlainCstInsn(newRop, getPosition(), getResult(), newSources, cst);
    }
}
Also used : Constant(com.android.dx.rop.cst.Constant) CstInteger(com.android.dx.rop.cst.CstInteger) TypeBearer(com.android.dx.rop.type.TypeBearer)

Example 15 with TypeBearer

use of com.android.dx.rop.type.TypeBearer in project buck by facebook.

the class RegisterSpec method intersect.

/**
     * Returns an instance that is the intersection between this instance
     * and the given one, if any. The intersection is defined as follows:
     *
     * <ul>
     *   <li>If {@code other} is {@code null}, then the result
     *     is {@code null}.
     *   <li>If the register numbers don't match, then the intersection
     *     is {@code null}. Otherwise, the register number of the
     *     intersection is the same as the one in the two instances.</li>
     *   <li>If the types returned by {@code getType()} are not
     *     {@code equals()}, then the intersection is null.</li>
     *   <li>If the type bearers returned by {@code getTypeBearer()}
     *     are {@code equals()}, then the intersection's type bearer
     *     is the one from this instance. Otherwise, the intersection's
     *     type bearer is the {@code getType()} of this instance.</li>
     *   <li>If the locals are {@code equals()}, then the local info
     *     of the intersection is the local info of this instance. Otherwise,
     *     the local info of the intersection is {@code null}.</li>
     * </ul>
     *
     * @param other {@code null-ok;} instance to intersect with (or {@code null})
     * @param localPrimary whether local variables are primary to the
     * intersection; if {@code true}, then the only non-null
     * results occur when registers being intersected have equal local
     * infos (or both have {@code null} local infos)
     * @return {@code null-ok;} the intersection
     */
public RegisterSpec intersect(RegisterSpec other, boolean localPrimary) {
    if (this == other) {
        // Easy out.
        return this;
    }
    if ((other == null) || (reg != other.getReg())) {
        return null;
    }
    LocalItem resultLocal = ((local == null) || !local.equals(other.getLocalItem())) ? null : local;
    boolean sameName = (resultLocal == local);
    if (localPrimary && !sameName) {
        return null;
    }
    Type thisType = getType();
    Type otherType = other.getType();
    // Note: Types are always interned.
    if (thisType != otherType) {
        return null;
    }
    TypeBearer resultTypeBearer = type.equals(other.getTypeBearer()) ? type : thisType;
    if ((resultTypeBearer == type) && sameName) {
        // It turns out that the intersection is "this" after all.
        return this;
    }
    return (resultLocal == null) ? make(reg, resultTypeBearer) : make(reg, resultTypeBearer, resultLocal);
}
Also used : Type(com.android.dx.rop.type.Type) TypeBearer(com.android.dx.rop.type.TypeBearer)

Aggregations

TypeBearer (com.android.dx.rop.type.TypeBearer)20 RegisterSpec (com.android.dx.rop.code.RegisterSpec)8 Type (com.android.dx.rop.type.Type)5 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)4 Constant (com.android.dx.rop.cst.Constant)4 TypedConstant (com.android.dx.rop.cst.TypedConstant)4 Insn (com.android.dx.rop.code.Insn)3 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)3 PlainInsn (com.android.dx.rop.code.PlainInsn)3 ArrayList (java.util.ArrayList)3 HashSet (java.util.HashSet)3 FillArrayDataInsn (com.android.dx.rop.code.FillArrayDataInsn)2 Rop (com.android.dx.rop.code.Rop)2 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)2 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)2 CstInteger (com.android.dx.rop.cst.CstInteger)2 CstLiteralBits (com.android.dx.rop.cst.CstLiteralBits)2 LocalItem (com.android.dx.rop.code.LocalItem)1 SourcePosition (com.android.dx.rop.code.SourcePosition)1 SwitchInsn (com.android.dx.rop.code.SwitchInsn)1