/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.dx.rop.code; import com.android.dx.rop.cst.CstInteger; import com.android.dx.rop.type.Type; /** * Implementation of {@link TranslationAdvice} which represents what * the dex format will be able to represent. */ public final class DexTranslationAdvice implements TranslationAdvice { /** {@code non-null;} standard instance of this class */ public static final DexTranslationAdvice THE_ONE = new DexTranslationAdvice(); /** debug advice for disabling invoke-range optimization */ public static final DexTranslationAdvice NO_SOURCES_IN_ORDER = new DexTranslationAdvice(true); /** * The minimum source width, in register units, for an invoke * instruction that requires its sources to be in order and contiguous. */ private static final int MIN_INVOKE_IN_ORDER = 6; /** when true: always returns false for requiresSourcesInOrder */ private final boolean disableSourcesInOrder; /** * This class is not publicly instantiable. Use {@link #THE_ONE}. */ private DexTranslationAdvice() { disableSourcesInOrder = false; } private DexTranslationAdvice(boolean disableInvokeRange) { this.disableSourcesInOrder = disableInvokeRange; } /** {@inheritDoc} */ public boolean hasConstantOperation(Rop opcode, RegisterSpec sourceA, RegisterSpec sourceB) { if (sourceA.getType() != Type.INT) { return false; } if (! (sourceB.getTypeBearer() instanceof CstInteger)) { return false; } CstInteger cst = (CstInteger) sourceB.getTypeBearer(); // TODO handle rsub switch (opcode.getOpcode()) { // These have 8 and 16 bit cst representations case RegOps.REM: case RegOps.ADD: case RegOps.MUL: case RegOps.DIV: case RegOps.AND: case RegOps.OR: case RegOps.XOR: return cst.fitsIn16Bits(); // These only have 8 bit cst reps case RegOps.SHL: case RegOps.SHR: case RegOps.USHR: return cst.fitsIn8Bits(); default: return false; } } /** {@inheritDoc} */ public boolean requiresSourcesInOrder(Rop opcode, RegisterSpecList sources) { return !disableSourcesInOrder && opcode.isCallLike() && totalRopWidth(sources) >= MIN_INVOKE_IN_ORDER; } /** * Calculates the total rop width of the list of SSA registers * * @param sources {@code non-null;} list of SSA registers * @return {@code >= 0;} rop-form width in register units */ private int totalRopWidth(RegisterSpecList sources) { int sz = sources.size(); int total = 0; for (int i = 0; i < sz; i++) { total += sources.get(i).getCategory(); } return total; } /** {@inheritDoc} */ public int getMaxOptimalRegisterCount() { return 16; } }