MethodDefinition.java revision 19b601436ac846b039318a69b5d13f4291d0bb45
1eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi/*
2eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * [The "BSD licence"]
3eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * Copyright (c) 2010 Ben Gruver (JesusFreke)
4eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * All rights reserved.
5eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi *
6eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * Redistribution and use in source and binary forms, with or without
7eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * modification, are permitted provided that the following conditions
8eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * are met:
9eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * 1. Redistributions of source code must retain the above copyright
10eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi *    notice, this list of conditions and the following disclaimer.
11eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * 2. Redistributions in binary form must reproduce the above copyright
12eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi *    notice, this list of conditions and the following disclaimer in the
13eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi *    documentation and/or other materials provided with the distribution.
14eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * 3. The name of the author may not be used to endorse or promote products
15eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi *    derived from this software without specific prior written permission.
16eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi *
17eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
202b06e20ae32388f6e1dfd088d9773c34e6b1cb45Jean-Michel Trivi * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
212b06e20ae32388f6e1dfd088d9773c34e6b1cb45Jean-Michel Trivi * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
222b06e20ae32388f6e1dfd088d9773c34e6b1cb45Jean-Michel Trivi * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232b06e20ae32388f6e1dfd088d9773c34e6b1cb45Jean-Michel Trivi * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi */
28581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi
29c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenpackage org.jf.baksmali.Adaptors;
30c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
31c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.baksmali.Adaptors.Format.*;
32c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.baksmali.IndentingWriter;
33c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.baksmali.Renderers.IntegerRenderer;
34c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.baksmali.baksmali;
35c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.dexlib.*;
36581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.*;
37581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.Analysis.AnalyzedInstruction;
38581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.Analysis.MethodAnalyzer;
39581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.Analysis.ValidationException;
40581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.Format.Format;
419d8a98601357c0669dca4de63e43196c0a70553dGlenn Kastenimport org.jf.dexlib.Debug.DebugInstructionIterator;
429d8a98601357c0669dca4de63e43196c0a70553dGlenn Kastenimport org.jf.dexlib.Util.AccessFlags;
439d8a98601357c0669dca4de63e43196c0a70553dGlenn Kastenimport org.jf.dexlib.Util.ExceptionWithContext;
449d8a98601357c0669dca4de63e43196c0a70553dGlenn Kastenimport org.jf.dexlib.Util.SparseIntArray;
45c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
46c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport java.io.IOException;
47c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport java.util.*;
48c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
49c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenpublic class MethodDefinition {
50c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    private final ClassDataItem.EncodedMethod encodedMethod;
51c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    private final MethodAnalyzer methodAnalyzer;
52581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi
53581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi    private final LabelCache labelCache = new LabelCache();
5437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi
557f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten    private final SparseIntArray packedSwitchMap;
56c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    private final SparseIntArray sparseSwitchMap;
57c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    private final SparseIntArray instructionMap;
58c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
597f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten    public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod) {
607f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten
61c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
62c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        try {
637f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten            this.encodedMethod = encodedMethod;
647f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten
657f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten            //TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh.
66c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
67c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            if (encodedMethod.codeItem != null) {
687f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex);
697f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions();
707f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten
717f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                packedSwitchMap = new SparseIntArray(1);
727f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                sparseSwitchMap = new SparseIntArray(1);
737f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                instructionMap = new SparseIntArray(instructions.size());
747f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten
757f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                int currentCodeAddress = 0;
767f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                for (int i=0; i<instructions.size(); i++) {
777f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                    AnalyzedInstruction instruction = instructions.get(i);
787f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                    if (instruction.getInstruction().opcode == Opcode.PACKED_SWITCH) {
797f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                        packedSwitchMap.append(
807f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                                currentCodeAddress +
817f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                                        ((OffsetInstruction)instruction.getInstruction()).getTargetAddressOffset(),
827f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                                currentCodeAddress);
837f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                    } else if (instruction.getInstruction().opcode == Opcode.SPARSE_SWITCH) {
847f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                        sparseSwitchMap.append(
857f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                                currentCodeAddress +
86c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                                        ((OffsetInstruction)instruction.getInstruction()).getTargetAddressOffset(),
87581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                                currentCodeAddress);
887f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                    }
89c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                    instructionMap.append(currentCodeAddress, i);
90c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                    currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress);
91c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                }
92c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            } else {
937f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten                packedSwitchMap = null;
94581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                sparseSwitchMap = null;
95c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                instructionMap = null;
9637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                methodAnalyzer = null;
9737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            }
9837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        }catch (Exception ex) {
9937dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            throw ExceptionWithContext.withContext(ex, String.format("Error while processing method %s",
10037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                    encodedMethod.method.getMethodString()));
10137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        }
10237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi    }
10337dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi
10437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi    public void writeTo(IndentingWriter writer, AnnotationSetItem annotationSet,
10537dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                        AnnotationSetRefList parameterAnnotations) throws IOException {
10637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        final CodeItem codeItem = encodedMethod.codeItem;
10737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi
10837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        writer.write(".method ");
10937dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        writeAccessFlags(writer, encodedMethod);
11037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        writer.write(encodedMethod.method.getMethodName().getStringValue());
11137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        writer.write(encodedMethod.method.getPrototype().getPrototypeString());
11237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        writer.write('\n');
11337dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi
11437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        writer.indent(4);
11537dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        if (codeItem != null) {
11637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            if (baksmali.useLocalsDirective) {
11737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                writer.write(".locals ");
11837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            } else {
119cb441acdda6f8e81d44fcdaadd4ff7ab3d3e367bGlenn Kasten                writer.write(".registers ");
12037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            }
12137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            writer.printIntAsDec(getRegisterCount(encodedMethod));
12237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            writer.write('\n');
12337dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            writeParameters(writer, codeItem, parameterAnnotations);
12437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            if (annotationSet != null) {
125e2e8fa36bd7448b59fbcdf141e0b6d21e5401d91Glenn Kasten                AnnotationFormatter.writeTo(writer, annotationSet);
12637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            }
12737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi
12837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            writer.write('\n');
12937dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi
13037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            for (MethodItem methodItem: getMethodItems()) {
13185133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi                if (methodItem.writeTo(writer)) {
13237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                    writer.write('\n');
133dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten                }
13437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            }
13537dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        } else {
13637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            if (annotationSet != null) {
13737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                AnnotationFormatter.writeTo(writer, annotationSet);
13885133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi            }
13985133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi        }
14085133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi        writer.deindent(4);
14185133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi        writer.write(".end method\n");
14285133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi    }
14385133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi
14485133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi    private static int getRegisterCount(ClassDataItem.EncodedMethod encodedMethod)
145dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten    {
146dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten        int totalRegisters = encodedMethod.codeItem.getRegisterCount();
147dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten        if (baksmali.useLocalsDirective) {
14885133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi            int parameterRegisters = encodedMethod.method.getPrototype().getParameterRegisterCount();
149581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi            if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) {
150581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                parameterRegisters++;
15137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            }
152581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi            return totalRegisters - parameterRegisters;
15392b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi        }
15492b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi        return totalRegisters;
15592b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi    }
15692b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi
15792b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi    private static void writeAccessFlags(IndentingWriter writer, ClassDataItem.EncodedMethod encodedMethod)
15892b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi                                                                                            throws IOException {
15992b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi        for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.accessFlags)) {
16092b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi            writer.write(accessFlag.toString());
16192b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi            writer.write(' ');
16292b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi        }
16392b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi    }
16492b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi
165e37c62f0691f9a137afae60f9d6dbd1a65d36aedGlenn Kasten    private static void writeParameters(IndentingWriter writer, CodeItem codeItem,
16692b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi                                        AnnotationSetRefList parameterAnnotations) throws IOException {
16792b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi        DebugInfoItem debugInfoItem = null;
16885133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi        if (baksmali.outputDebugInfo && codeItem != null) {
16992b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi            debugInfoItem = codeItem.getDebugInfo();
170dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten        }
17192b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi
17285133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi        int parameterCount = 0;
17385133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi        AnnotationSetItem[] annotations;
17485133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi        StringIdItem[] parameterNames = null;
17585133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi
176c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        if (parameterAnnotations != null) {
17785133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi            annotations = parameterAnnotations.getAnnotationSets();
17885133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi            parameterCount = annotations.length;
17992b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi        } else {
180581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi            annotations = new AnnotationSetItem[0];
18192b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi        }
18292b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi
18399b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        if (debugInfoItem != null) {
18499b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten            parameterNames = debugInfoItem.getParameterNames();
18599b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        }
18699b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        if (parameterNames == null) {
18799b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten            parameterNames = new StringIdItem[0];
18899b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        }
18999b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten
19099b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        if (parameterCount < parameterNames.length) {
19199b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten            parameterCount = parameterNames.length;
19299b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        }
19399b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten
19499b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        for (int i=0; i<parameterCount; i++) {
19599b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten            AnnotationSetItem annotationSet = null;
196c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            if (i < annotations.length) {
197c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                annotationSet = annotations[i];
198c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            }
199c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
200c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            StringIdItem parameterName = null;
201c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            if (i < parameterNames.length) {
202c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                parameterName = parameterNames[i];
203c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            }
204c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
205c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            writer.write(".parameter");
206c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
207c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            if (parameterName != null) {
208c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                writer.write('"');
209c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                writer.write(parameterName.getStringValue());
210c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                writer.write('"');
211c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            }
212c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
213c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            writer.write('\n');
214c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            if (annotationSet != null) {
215c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                writer.indent(4);
21699b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten                AnnotationFormatter.writeTo(writer, annotationSet);
21799b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten                writer.deindent(4);
21899b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten
21999b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten                writer.write(".end parameter\n");
22099b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten            }
221c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        }
222c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    }
223c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
224c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    public LabelCache getLabelCache() {
225c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        return labelCache;
226c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    }
227c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
228c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    public ValidationException getValidationException() {
229c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        if (methodAnalyzer == null) {
230c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            return null;
231c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        }
232c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
233c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        return methodAnalyzer.getValidationException();
234c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    }
235c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
236c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    public int getPackedSwitchBaseAddress(int packedSwitchDataAddress) {
237c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        int packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress, -1);
238c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
239c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        if (packedSwitchBaseAddress == -1) {
240c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten            throw new RuntimeException("Could not find the packed switch statement corresponding to the packed " +
241c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten                    "switch data at address " + packedSwitchDataAddress);
242c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten        }
243c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten
24499b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        return packedSwitchBaseAddress;
24599b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten    }
24699b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten
247bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten    public int getSparseSwitchBaseAddress(int sparseSwitchDataAddress) {
248bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten        int sparseSwitchBaseAddress = this.sparseSwitchMap.get(sparseSwitchDataAddress, -1);
249bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten
250bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten        if (sparseSwitchBaseAddress == -1) {
251bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten            throw new RuntimeException("Could not find the sparse switch statement corresponding to the sparse " +
252bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                    "switch data at address " + sparseSwitchDataAddress);
253bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten        }
254bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten
255bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten        return sparseSwitchBaseAddress;
256bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten    }
257bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten
258bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten    /**
259bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten     * @param instructions The instructions array for this method
26099b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten     * @param instruction The instruction
2615e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten     * @return true if the specified instruction is a NOP, and the next instruction is one of the variable sized
2625e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten     * switch/array data structures
2635e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten     */
2645e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten    private boolean isInstructionPaddingNop(List<AnalyzedInstruction> instructions, AnalyzedInstruction instruction) {
2655e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        if (instruction.getInstruction().opcode != Opcode.NOP ||
2665e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten            instruction.getInstruction().getFormat().variableSizeFormat) {
2675e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten
2685e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten            return false;
2695e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        }
2705e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten
2715e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        if (instruction.getInstructionIndex() == instructions.size()-1) {
2725e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten            return false;
2735e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        }
2745e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten
2755e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        AnalyzedInstruction nextInstruction = instructions.get(instruction.getInstructionIndex()+1);
2765e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        if (nextInstruction.getInstruction().getFormat().variableSizeFormat) {
2775e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten            return true;
2785e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        }
2795e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        return false;
2805e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten    }
2815e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten
2825e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten    private List<MethodItem> getMethodItems() {
2835e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        List<MethodItem> methodItems = new ArrayList<MethodItem>();
2845e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten
2855e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        if (encodedMethod.codeItem == null) {
2865e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten            return methodItems;
2875e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        }
2885e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten
2895e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten        if (baksmali.registerInfo != 0 || baksmali.deodex || baksmali.verify) {
2905e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten            methodAnalyzer.analyze();
2915e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten
29292b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi            ValidationException validationException = methodAnalyzer.getValidationException();
29392b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi            if (validationException != null) {
29492b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi                methodItems.add(new CommentMethodItem(
295581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                        String.format("ValidationException: %s" ,validationException.getMessage()),
2969d8a98601357c0669dca4de63e43196c0a70553dGlenn Kasten                        validationException.getCodeAddress(), Integer.MIN_VALUE));
2979d8a98601357c0669dca4de63e43196c0a70553dGlenn Kasten            } else if (baksmali.verify) {
298581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                methodAnalyzer.verify();
299581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi
300eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                validationException = methodAnalyzer.getValidationException();
301eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                if (validationException != null) {
302d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                    methodItems.add(new CommentMethodItem(
303d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                            String.format("ValidationException: %s" ,validationException.getMessage()),
304d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                            validationException.getCodeAddress(), Integer.MIN_VALUE));
305d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                }
306d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            }
307d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        }
308d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions();
309d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
310d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        AnalyzedInstruction lastInstruction = null;
311d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
312d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        for (int i=instructions.size()-1; i>=0; i--) {
313d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            AnalyzedInstruction instruction = instructions.get(i);
314d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
315d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            if (!instruction.isDead()) {
316d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                lastInstruction = instruction;
317d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                break;
318d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            }
319d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        }
320d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
321d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        boolean lastIsUnreachable = false;
322d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
323d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        int currentCodeAddress = 0;
324d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        for (int i=0; i<instructions.size(); i++) {
325d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            AnalyzedInstruction instruction = instructions.get(i);
326d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
327d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
328d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                    encodedMethod.codeItem, currentCodeAddress, instruction.isDead(), instruction.getInstruction(),
329d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                    instruction == lastInstruction);
330d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
331d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            if (instruction.isDead() && !instruction.getInstruction().getFormat().variableSizeFormat) {
332d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                methodItems.add(new CommentedOutMethodItem(methodItem));
333d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                lastIsUnreachable = false;
334d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            } else if ( instruction.getPredecessorCount() == 0 &&
335d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                        !instruction.getInstruction().getFormat().variableSizeFormat &&
336d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                        !isInstructionPaddingNop(instructions, instruction)) {
337d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
338d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                if (!lastIsUnreachable) {
339d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                    methodItems.add(
340d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                        new CommentMethodItem("Unreachable code", currentCodeAddress, Double.MIN_VALUE));
341d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                }
342d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
343d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                methodItems.add(new CommentedOutMethodItem(methodItem));
344d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                    lastIsUnreachable = true;
345d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            } else {
346d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                methodItems.add(methodItem);
347d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                lastIsUnreachable = false;
348d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            }
349d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
350d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            if (instruction.getInstruction().getFormat() == Format.UnresolvedNullReference) {
351d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                methodItems.add(new CommentedOutMethodItem(
352d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                        InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, encodedMethod.codeItem,
353d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                                currentCodeAddress, instruction.isDead(), instruction.getOriginalInstruction(),
354d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                                false)));
355d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            }
356d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
357d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            if (i != instructions.size() - 1) {
358d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                methodItems.add(new BlankMethodItem(currentCodeAddress));
359d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            }
360d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
361d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            if (baksmali.addCodeOffsets) {
362eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                methodItems.add(new MethodItem(currentCodeAddress) {
363eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
364eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                    @Override
365eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                    public double getSortOrder() {
366eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                        return -1000;
367eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                    }
368eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
369eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                    @Override
370eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                    public boolean writeTo(IndentingWriter writer) throws IOException {
371eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                        writer.write("#@");
372eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                        writer.printLongAsHex(codeAddress & 0xFFFFFFFF);
37397876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                        return true;
374eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                    }
37597876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                });
376f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi            }
377b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi
378eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi            if (baksmali.registerInfo != 0 && !instruction.getInstruction().getFormat().variableSizeFormat) {
379f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi                methodItems.add(
38097876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                        new PreInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress));
381b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi
38297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                methodItems.add(
383f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi                        new PostInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress));
384eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi            }
38572042d4448cee63528c619537321ba73944c6382Glenn Kasten
386a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress);
387eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        }
388eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
389eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        addTries(methodItems);
390eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        addDebugInfo(methodItems);
39164621eac543d714d4d3f7cb9c24205f2ddc59201Glenn Kasten
392f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi        if (baksmali.useSequentialLabels) {
393f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi            setLabelSequentialNumbers();
394f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi        }
395eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
39672042d4448cee63528c619537321ba73944c6382Glenn Kasten
39772042d4448cee63528c619537321ba73944c6382Glenn Kasten        for (LabelMethodItem labelMethodItem: labelCache.getLabels()) {
39872042d4448cee63528c619537321ba73944c6382Glenn Kasten            if (labelMethodItem.isCommentedOut()) {
399485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                methodItems.add(new CommentedOutMethodItem(labelMethodItem));
400485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten            } else {
401eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                methodItems.add(labelMethodItem);
402eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi            }
403eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        }
404eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
405eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        Collections.sort(methodItems);
406eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
407eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        return methodItems;
408ecc4fe22e076c4e5c891d823b01db1a683ba6690Glenn Kasten    }
409eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
410eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi    private void addTries(List<MethodItem> methodItems) {
411eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        if (encodedMethod.codeItem == null || encodedMethod.codeItem.getTries() == null) {
412eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi            return;
413eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        }
414eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
415f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi        Instruction[] instructions = encodedMethod.codeItem.getInstructions();
416f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi
417eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        for (CodeItem.TryItem tryItem: encodedMethod.codeItem.getTries()) {
418f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi            int startAddress = tryItem.getStartCodeAddress();
419b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi            int endAddress = tryItem.getStartCodeAddress() + tryItem.getTryLength();
4207133228a478e16458b659946f2180ecddd13fda7Glenn Kasten
4217133228a478e16458b659946f2180ecddd13fda7Glenn Kasten            /**
422581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi             * The end address points to the address immediately after the end of the last
423eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi             * instruction that the try block covers. We want the .catch directive and end_try
424eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi             * label to be associated with the last covered instruction, so we need to get
425b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi             * the address for that instruction
42668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi             */
42797876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi
42897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi            int index = instructionMap.get(endAddress, -1);
42997876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi            int lastInstructionAddress;
43097876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi
43197876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi            /**
43297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi             * If we couldn't find the index, then the try block probably extends to the last instruction in the
43397876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi             * method, and so endAddress would be the address immediately after the end of the last instruction.
43497876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi             * Check to make sure this is the case, if not, throw an exception.
43597876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi             */
43697876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi            if (index == -1) {
43797876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                Instruction lastInstruction = instructions[instructions.length - 1];
43897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                lastInstructionAddress = instructionMap.keyAt(instructionMap.size() - 1);
43997876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi
44097876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                if (endAddress != lastInstructionAddress + lastInstruction.getSize(lastInstructionAddress)) {
44197876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                    throw new RuntimeException("Invalid code offset " + endAddress + " for the try block end address");
44297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                }
443a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            } else {
44497876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                if (index == 0) {
44597876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                    throw new RuntimeException("Unexpected instruction index");
44697876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                }
44797876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                Instruction lastInstruction = instructions[index - 1];
44897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi
449321f2cffd7dd560bf2e5c898be6953e19bed8496Jean-Michel Trivi                if (lastInstruction.getFormat().variableSizeFormat) {
450eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                    throw new RuntimeException("This try block unexpectedly ends on a switch/array data block.");
451f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi                }
452eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
453eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                //getSize for non-variable size formats should return the same size regardless of code address, so just
454eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                //use a dummy address of "0"
455eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                lastInstructionAddress = endAddress - lastInstruction.getSize(0);
45635ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten            }
45735ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten
45835ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten            //add the catch all handler if it exists
45935ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten            int catchAllAddress = tryItem.encodedCatchHandler.getCatchAllHandlerAddress();
46035ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten            if (catchAllAddress != -1) {
46135ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten                CatchMethodItem catchAllMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress, null,
46235ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten                        startAddress, endAddress, catchAllAddress);
46335ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten                methodItems.add(catchAllMethodItem);
46435ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten            }
46535ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten
46635ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten            //add the rest of the handlers
46735ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten            for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) {
46835ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten                //use the address from the last covered instruction
46935ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten                CatchMethodItem catchMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress,
470eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                        handler.exceptionType, startAddress, endAddress, handler.getHandlerAddress());
471eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                methodItems.add(catchMethodItem);
472eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi            }
473485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten        }
474485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten    }
475485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten
476485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten    private void addDebugInfo(final List<MethodItem> methodItems) {
477b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten        if (encodedMethod.codeItem == null || encodedMethod.codeItem.getDebugInfo() == null) {
478485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten            return;
479485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten        }
480485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten
481485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten        final CodeItem codeItem = encodedMethod.codeItem;
482485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten        DebugInfoItem debugInfoItem = codeItem.getDebugInfo();
483485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten
484b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten        DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(),
485b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten                new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() {
486b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten                    @Override
487b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten                    public void ProcessStartLocal(final int codeAddress, final int length, final int registerNum,
488b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten                                                  final StringIdItem name, final TypeIdItem type) {
489485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                        methodItems.add(new DebugMethodItem(codeAddress, -1) {
490485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                            @Override
491485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                            public boolean writeTo(IndentingWriter writer) throws IOException {
49297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                                writeStartLocal(writer, codeItem, registerNum, name, type, null);
49397876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                                return true;
494ecc4fe22e076c4e5c891d823b01db1a683ba6690Glenn Kasten                            }
49597876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                        });
496485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                    }
49772042d4448cee63528c619537321ba73944c6382Glenn Kasten
49872042d4448cee63528c619537321ba73944c6382Glenn Kasten                    @Override
49972042d4448cee63528c619537321ba73944c6382Glenn Kasten                    public void ProcessStartLocalExtended(final int codeAddress, final int length,
50072042d4448cee63528c619537321ba73944c6382Glenn Kasten                                                          final int registerNum, final StringIdItem name,
501485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                                                          final TypeIdItem type, final StringIdItem signature) {
50297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                        methodItems.add(new DebugMethodItem(codeAddress, -1) {
503485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                            @Override
504485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                            public boolean writeTo(IndentingWriter writer) throws IOException {
505485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                                writeStartLocal(writer, codeItem, registerNum, name, type, signature);
506485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                                return true;
507485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten                            }
50897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                        });
509eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                    }
510ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten
511bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                    @Override
512bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                    public void ProcessEndLocal(final int codeAddress, final int length, final int registerNum,
513bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                                                final StringIdItem name, final TypeIdItem type,
514bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                                                final StringIdItem signature) {
515bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                        methodItems.add(new DebugMethodItem(codeAddress, -1) {
516bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                            @Override
517bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                            public boolean writeTo(IndentingWriter writer) throws IOException {
518bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                                writeEndLocal(writer, codeItem, registerNum, name, type, signature);
519bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten                                return true;
52070c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                            }
52170c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                        });
52270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                    }
52370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi
52470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                    @Override
525b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi                    public void ProcessRestartLocal(final int codeAddress, final int length, final int registerNum,
5263d332ff421e7179c36fb652771cc8ded53383729Glenn Kasten                                                final StringIdItem name, final TypeIdItem type,
52770c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                                                final StringIdItem signature) {
52870c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                        methodItems.add(new DebugMethodItem(codeAddress, -1) {
52970c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                            @Override
53035a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            public boolean writeTo(IndentingWriter writer) throws IOException {
53135a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                                writeRestartLocal(writer, codeItem, registerNum, name, type, signature);
53270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                                return true;
53370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                            }
53470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                        });
53570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                    }
53670c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi
5373d332ff421e7179c36fb652771cc8ded53383729Glenn Kasten                    @Override
53870c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                    public void ProcessSetPrologueEnd(int codeAddress) {
5393d332ff421e7179c36fb652771cc8ded53383729Glenn Kasten                        methodItems.add(new DebugMethodItem(codeAddress, -4) {
54035a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            @Override
54135a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            public boolean writeTo(IndentingWriter writer) throws IOException {
54235a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                                writeEndPrologue(writer);
5433d332ff421e7179c36fb652771cc8ded53383729Glenn Kasten                                return true;
54435a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            }
54535a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                        });
54635a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                    }
54735a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi
54835a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                    @Override
54935a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                    public void ProcessSetEpilogueBegin(int codeAddress) {
55035a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                        methodItems.add(new DebugMethodItem(codeAddress, -4) {
55135a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            @Override
55235a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            public boolean writeTo(IndentingWriter writer) throws IOException {
55335a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                                writeBeginEpilogue(writer);
55435a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                                return true;
55535a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            }
556136965c92c625d52a6cbad42f82a2091d7769c9cGlenn Kasten                        });
55735a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                    }
55835a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi
55935a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                    @Override
56035a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                    public void ProcessSetFile(int codeAddress, int length, final StringIdItem name) {
561136965c92c625d52a6cbad42f82a2091d7769c9cGlenn Kasten                        methodItems.add(new DebugMethodItem(codeAddress, -3) {
56235a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            @Override
56335a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            public boolean writeTo(IndentingWriter writer) throws IOException {
56435a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                                writeSetFile(writer, name.getStringValue());
56535a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                                return true;
56635a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                            }
56735a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                        });
56835a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi                    }
56935a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi
57070c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                    @Override
57170c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                    public void ProcessLineEmit(int codeAddress, final int line) {
57270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                        methodItems.add(new DebugMethodItem(codeAddress, -2) {
57370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                            @Override
57470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                            public boolean writeTo(IndentingWriter writer) throws IOException {
57570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                                writeLine(writer, line);
57637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                                return true;
57737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                            }
57837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                         });
57999b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten                    }
58037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                });
58199b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten    }
58237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi
58399b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten    private void setLabelSequentialNumbers() {
58499b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        HashMap<String, Integer> nextLabelSequenceByType = new HashMap<String, Integer>();
58599b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        ArrayList<LabelMethodItem> sortedLabels = new ArrayList<LabelMethodItem>(labelCache.getLabels());
58699b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten
58799b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        //sort the labels by their location in the method
58899b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        Collections.sort(sortedLabels);
58999b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten
59099b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten        for (LabelMethodItem labelMethodItem: sortedLabels) {
59137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            Integer labelSequence = nextLabelSequenceByType.get(labelMethodItem.getLabelPrefix());
59237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            if (labelSequence == null) {
5930e47a0657162bbff48886ea2f5c68d9edb607768Jean-Michel Trivi                labelSequence = 0;
5940e47a0657162bbff48886ea2f5c68d9edb607768Jean-Michel Trivi            }
59536b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi            labelMethodItem.setLabelSequence(labelSequence);
596f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi            nextLabelSequenceByType.put(labelMethodItem.getLabelPrefix(), labelSequence + 1);
59736b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi        }
59836b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi    }
599b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi
600eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi    public static class LabelCache {
601eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        protected HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>();
602b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi
603eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        public LabelCache() {
604eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi        }
605eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
606f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi        public LabelMethodItem internLabel(LabelMethodItem labelMethodItem) {
60736b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi            LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem);
60897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi            if (internedLabelMethodItem != null) {
60997876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi                if (!labelMethodItem.isCommentedOut()) {
610eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                    internedLabelMethodItem.setUncommented();
611f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi                }
612eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi                return internedLabelMethodItem;
613e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi            }
614581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi            labels.put(labelMethodItem, labelMethodItem);
61536b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi            return labelMethodItem;
616581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi        }
617e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
618eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
619e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi        public Collection<LabelMethodItem> getLabels() {
62036b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi            return labels.values();
621581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi        }
622eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi    }
623f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi}
624eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi