DexTranslationAdvice.java revision 579d7739c53a2707ad711a2d2cae46d7d782f061
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dx.rop.code;
18
19import com.android.dx.rop.cst.CstInteger;
20import com.android.dx.rop.type.Type;
21
22/**
23 * Implementation of {@link TranslationAdvice} which represents what
24 * the dex format will be able to represent.
25 */
26public final class DexTranslationAdvice
27        implements TranslationAdvice {
28    /** {@code non-null;} standard instance of this class */
29    public static final DexTranslationAdvice THE_ONE =
30        new DexTranslationAdvice();
31
32    /** debug advice for disabling invoke-range optimization */
33    public static final DexTranslationAdvice NO_SOURCES_IN_ORDER =
34        new DexTranslationAdvice(true);
35
36    /**
37     * The minimum source width, in register units, for an invoke
38     * instruction that requires its sources to be in order and contiguous.
39     */
40    private static final int MIN_INVOKE_IN_ORDER = 6;
41
42    /** when true: always returns false for requiresSourcesInOrder */
43    private final boolean disableSourcesInOrder;
44
45    /**
46     * This class is not publicly instantiable. Use {@link #THE_ONE}.
47     */
48    private DexTranslationAdvice() {
49        disableSourcesInOrder = false;
50    }
51
52    private DexTranslationAdvice(boolean disableInvokeRange) {
53        this.disableSourcesInOrder = disableInvokeRange;
54    }
55
56    /** {@inheritDoc} */
57    public boolean hasConstantOperation(Rop opcode,
58            RegisterSpec sourceA, RegisterSpec sourceB) {
59        if (sourceA.getType() != Type.INT) {
60            return false;
61        }
62
63        // Return false if second source isn't a constant
64        if (! (sourceB.getTypeBearer() instanceof CstInteger)) {
65            // Except for rsub-int (reverse sub) where first source is constant
66            if (sourceA.getTypeBearer() instanceof CstInteger &&
67                    opcode.getOpcode() == RegOps.SUB) {
68                CstInteger cst = (CstInteger) sourceA.getTypeBearer();
69                return cst.fitsIn16Bits();
70            } else {
71                return false;
72            }
73        }
74
75        CstInteger cst = (CstInteger) sourceB.getTypeBearer();
76
77        switch (opcode.getOpcode()) {
78            // These have 8 and 16 bit cst representations
79            case RegOps.REM:
80            case RegOps.ADD:
81            case RegOps.MUL:
82            case RegOps.DIV:
83            case RegOps.AND:
84            case RegOps.OR:
85            case RegOps.XOR:
86                return cst.fitsIn16Bits();
87            // These only have 8 bit cst reps
88            case RegOps.SHL:
89            case RegOps.SHR:
90            case RegOps.USHR:
91                return cst.fitsIn8Bits();
92            // No sub-const insn, so check if equivalent add-const fits
93            case RegOps.SUB:
94                CstInteger cst2 = CstInteger.make(-cst.getValue());
95                return cst2.fitsIn16Bits();
96            default:
97                return false;
98        }
99    }
100
101    /** {@inheritDoc} */
102    public boolean requiresSourcesInOrder(Rop opcode,
103            RegisterSpecList sources) {
104
105        return !disableSourcesInOrder && opcode.isCallLike()
106                && totalRopWidth(sources) >= MIN_INVOKE_IN_ORDER;
107    }
108
109    /**
110     * Calculates the total rop width of the list of SSA registers
111     *
112     * @param sources {@code non-null;} list of SSA registers
113     * @return {@code >= 0;} rop-form width in register units
114     */
115    private int totalRopWidth(RegisterSpecList sources) {
116        int sz = sources.size();
117        int total = 0;
118
119        for (int i = 0; i < sz; i++) {
120            total += sources.get(i).getCategory();
121        }
122
123        return total;
124    }
125
126    /** {@inheritDoc} */
127    public int getMaxOptimalRegisterCount() {
128        return 16;
129    }
130}
131