| /* |
| * 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.dexgen.rop.code; |
| |
| import com.android.dexgen.rop.cst.CstInteger; |
| import com.android.dexgen.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; |
| } |
| } |