InstructionTransformer.java revision 17cae2df2191566bf17783cb591c9800b1efb07d
1081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson/*
2081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Copyright (C) 2011 The Android Open Source Project
3081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson *
4081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * you may not use this file except in compliance with the License.
6081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * You may obtain a copy of the License at
7081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson *
8081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson *
10081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Unless required by applicable law or agreed to in writing, software
11081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * See the License for the specific language governing permissions and
14081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * limitations under the License.
15081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson */
16081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson
17081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonpackage com.android.dx.merge;
18081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson
19081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonimport com.android.dx.dex.DexException;
20e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilsonimport com.android.dx.io.CodeReader;
2138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornsteinimport com.android.dx.io.DecodedInstruction;
22a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornsteinimport com.android.dx.io.OpcodeInfo;
2338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornsteinimport com.android.dx.io.ShortArrayCodeOutput;
24081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson
25dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilsonfinal class InstructionTransformer {
26081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson    private final IndexMap indexMap;
27e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    private final CodeReader reader;
2838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    private DecodedInstruction[] mappedInstructions;
2938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    private int mappedAt;
30081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson
31081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson    public InstructionTransformer(IndexMap indexMap) {
32081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson        this.indexMap = indexMap;
33e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson        this.reader = new CodeReader();
3438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        this.reader.setAllVisitors(new GenericVisitor());
3538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        this.reader.setStringVisitor(new StringVisitor());
36e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson        this.reader.setTypeVisitor(new TypeVisitor());
37e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson        this.reader.setFieldVisitor(new FieldVisitor());
38e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson        this.reader.setMethodVisitor(new MethodVisitor());
39081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson    }
40081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson
4138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    public short[] transform(short[] encodedInstructions) throws DexException {
4238b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        DecodedInstruction[] decodedInstructions =
4338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            DecodedInstruction.decodeAll(encodedInstructions);
4438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        int size = decodedInstructions.length;
4538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein
4638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        mappedInstructions = new DecodedInstruction[size];
4738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        mappedAt = 0;
4838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        reader.visitAll(decodedInstructions);
4938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein
5038b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        ShortArrayCodeOutput out = new ShortArrayCodeOutput(size);
5138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        for (DecodedInstruction instruction : mappedInstructions) {
5238b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            if (instruction != null) {
5338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein                instruction.encode(out);
5438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            }
5538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        }
5638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein
5738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        return out.getArray();
58081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson    }
59081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson
6038b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    private class GenericVisitor implements CodeReader.Visitor {
61a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein        public void visit(DecodedInstruction[] all, DecodedInstruction one) {
6238b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            mappedInstructions[mappedAt++] = one;
6338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        }
6438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    }
6538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein
6638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    private class StringVisitor implements CodeReader.Visitor {
67a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein        public void visit(DecodedInstruction[] all, DecodedInstruction one) {
6838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            int stringId = one.getIndex();
6938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            int mappedId = indexMap.adjustString(stringId);
7017cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein            jumboCheck(stringId, mappedId);
7138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            mappedInstructions[mappedAt++] = one.withIndex(mappedId);
72081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson        }
73081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson    }
74081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson
75e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    private class FieldVisitor implements CodeReader.Visitor {
76a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein        public void visit(DecodedInstruction[] all, DecodedInstruction one) {
7738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            int fieldId = one.getIndex();
7838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            int mappedId = indexMap.adjustField(fieldId);
7917cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein            jumboCheck(fieldId, mappedId);
8038b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            mappedInstructions[mappedAt++] = one.withIndex(mappedId);
81081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson        }
82081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson    }
83081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson
84e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    private class TypeVisitor implements CodeReader.Visitor {
85a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein        public void visit(DecodedInstruction[] all, DecodedInstruction one) {
8638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            int typeId = one.getIndex();
8738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            int mappedId = indexMap.adjustType(typeId);
8817cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein            jumboCheck(typeId, mappedId);
8938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            mappedInstructions[mappedAt++] = one.withIndex(mappedId);
90081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson        }
91081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson    }
92081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson
93e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    private class MethodVisitor implements CodeReader.Visitor {
94a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein        public void visit(DecodedInstruction[] all, DecodedInstruction one) {
9538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            int methodId = one.getIndex();
9638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            int mappedId = indexMap.adjustMethod(methodId);
9717cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein            jumboCheck(methodId, mappedId);
9838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            mappedInstructions[mappedAt++] = one.withIndex(mappedId);
99081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson        }
100081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson    }
10117cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein
10217cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein    private static void jumboCheck(int oldIndex, int newIndex) {
10317cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein        if ((oldIndex <= 0xffff) && (newIndex > 0xffff)) {
10417cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein            throw new DexException("Cannot handle conversion to jumbo index!");
10517cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein        }
10617cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein    }
10717cae2df2191566bf17783cb591c9800b1efb07dDan Bornstein
108081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson}
109