InstructionTransformer.java revision a754fbb1555f9ac2d14de0ffd0046c780732da5a
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.setJumboStringVisitor(new JumboStringVisitor()); 3638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein this.reader.setStringVisitor(new StringVisitor()); 37e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson this.reader.setTypeVisitor(new TypeVisitor()); 38e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson this.reader.setFieldVisitor(new FieldVisitor()); 39e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson this.reader.setMethodVisitor(new MethodVisitor()); 40081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 41081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 4238b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein public short[] transform(short[] encodedInstructions) throws DexException { 4338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein DecodedInstruction[] decodedInstructions = 4438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein DecodedInstruction.decodeAll(encodedInstructions); 4538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int size = decodedInstructions.length; 4638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein 4738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein mappedInstructions = new DecodedInstruction[size]; 4838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein mappedAt = 0; 4938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein reader.visitAll(decodedInstructions); 5038b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein 5138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein ShortArrayCodeOutput out = new ShortArrayCodeOutput(size); 5238b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein for (DecodedInstruction instruction : mappedInstructions) { 5338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein if (instruction != null) { 5438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein instruction.encode(out); 5538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein } 5638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein } 5738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein 5838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein return out.getArray(); 59081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 60081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 6138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein private class GenericVisitor implements CodeReader.Visitor { 62a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein public void visit(DecodedInstruction[] all, DecodedInstruction one) { 6338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein mappedInstructions[mappedAt++] = one; 6438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein } 6538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein } 6638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein 6738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein private class StringVisitor implements CodeReader.Visitor { 68a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein public void visit(DecodedInstruction[] all, DecodedInstruction one) { 6938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int stringId = one.getIndex(); 7038b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int mappedId = indexMap.adjustString(stringId); 7138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein if (mappedId > 0xFFFF) { 72081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson throw new DexException("Cannot convert string to jumbo string!"); 73081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 7438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein 7538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein mappedInstructions[mappedAt++] = one.withIndex(mappedId); 76081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 77081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 78081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 7938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein private class JumboStringVisitor implements CodeReader.Visitor { 80a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein public void visit(DecodedInstruction[] all, DecodedInstruction one) { 81081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson throw new UnsupportedOperationException("Jumbo strings not implemented. " 82081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson + "Due to a lack of dex files requiring jumbo strings, this class doesn't " 83081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson + "bother to support jumbo strings!"); 84081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 85081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 86081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 87e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson private class FieldVisitor implements CodeReader.Visitor { 88a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein public void visit(DecodedInstruction[] all, DecodedInstruction one) { 8938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int fieldId = one.getIndex(); 9038b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int mappedId = indexMap.adjustField(fieldId); 9138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein mappedInstructions[mappedAt++] = one.withIndex(mappedId); 92081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 93081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 94081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 95e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson private class TypeVisitor implements CodeReader.Visitor { 96a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein public void visit(DecodedInstruction[] all, DecodedInstruction one) { 9738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int typeId = one.getIndex(); 9838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int mappedId = indexMap.adjustType(typeId); 9938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein mappedInstructions[mappedAt++] = one.withIndex(mappedId); 100081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 101081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 102081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 103e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson private class MethodVisitor implements CodeReader.Visitor { 104a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein public void visit(DecodedInstruction[] all, DecodedInstruction one) { 10538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int methodId = one.getIndex(); 10638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int mappedId = indexMap.adjustMethod(methodId); 10738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein mappedInstructions[mappedAt++] = one.withIndex(mappedId); 108081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 109081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 110081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson} 111