1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.file;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dex.util.ExceptionWithContext;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.DalvCode;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.DalvInsnList;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstMethodRef;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.StdTypeList;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeList;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.AnnotatedOutput;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.PrintWriter;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Representation of all the parts needed for concrete methods in a
3399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code dex} file.
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class CodeItem extends OffsettedItem {
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** file alignment of this class, in bytes */
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int ALIGNMENT = 4;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** write size of the header of this class, in bytes */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int HEADER_SIZE = 16;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} method that this code implements */
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final CstMethodRef ref;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} the bytecode instructions and associated data */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final DalvCode code;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} the catches, if needed; set in {@link #addContents} */
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private CatchStructs catches;
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** whether this instance is for a {@code static} method */
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final boolean isStatic;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
5599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code non-null;} list of possibly-thrown exceptions; just used in
56de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * generating debugging output (listings)
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final TypeList throwsList;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
6199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code null-ok;} the debug info or {@code null} if there is none;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * set in {@link #addContents}
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private DebugInfoItem debugInfo;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
68de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param ref {@code non-null;} method that this code implements
7099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param code {@code non-null;} the underlying code
7199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param isStatic whether this instance is for a {@code static}
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * method
7399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param throwsList {@code non-null;} list of possibly-thrown exceptions,
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * just used in generating debugging output (listings)
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public CodeItem(CstMethodRef ref, DalvCode code, boolean isStatic,
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TypeList throwsList) {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(ALIGNMENT, -1);
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ref == null) {
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("ref == null");
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (code == null) {
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("code == null");
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (throwsList == null) {
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("throwsList == null");
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.ref = ref;
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.code = code;
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.isStatic = isStatic;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.throwsList = throwsList;
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.catches = null;
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.debugInfo = null;
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ItemType itemType() {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ItemType.TYPE_CODE_ITEM;
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void addContents(DexFile file) {
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MixedItemSection byteData = file.getByteData();
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeIdsSection typeIds = file.getTypeIds();
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (code.hasPositions() || code.hasLocals()) {
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            debugInfo = new DebugInfoItem(code, isStatic, ref);
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            byteData.add(debugInfo);
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (code.hasAnyCatches()) {
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (Type type : code.getCatchTypes()) {
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                typeIds.intern(type);
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            catches = new CatchStructs(code);
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (Constant c : code.getInsnConstants()) {
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            file.internIfAppropriate(c);
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toString() {
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return "CodeItem{" + toHuman() + "}";
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toHuman() {
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ref.toHuman();
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the reference to the method this instance implements.
142de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
14399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the method reference
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public CstMethodRef getRef() {
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ref;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Does a human-friendly dump of this instance.
151de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
15299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} where to dump
15399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param prefix {@code non-null;} per-line prefix to use
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param verbose whether to be verbose with the output
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void debugPrint(PrintWriter out, String prefix, boolean verbose) {
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.println(ref.toHuman() + ":");
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DalvInsnList insns = code.getInsns();
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.println("regs: " + Hex.u2(getRegistersSize()) +
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "; ins: " + Hex.u2(getInsSize()) + "; outs: " +
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Hex.u2(getOutsSize()));
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        insns.debugPrint(out, prefix, verbose);
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String prefix2 = prefix + "  ";
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (catches != null) {
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.print(prefix);
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.println("catches");
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            catches.debugPrint(out, prefix2);
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (debugInfo != null) {
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.print(prefix);
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.println("debug info");
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            debugInfo.debugPrint(out, prefix2);
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void place0(Section addedTo, int offset) {
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        final DexFile file = addedTo.getFile();
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int catchesSize;
186de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * In order to get the catches and insns, all the code's
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * constants need to be assigned indices.
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        code.assignIndices(new DalvCode.AssignIndicesCallback() {
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                public int getIndex(Constant cst) {
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    IndexedItem item = file.findItemOrNull(cst);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (item == null) {
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        return -1;
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return item.getIndex();
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            });
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (catches != null) {
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            catches.encode(file);
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            catchesSize = catches.writeSize();
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            catchesSize = 0;
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The write size includes the header, two bytes per code
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * unit, post-code padding if necessary, and however much
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * space the catches need.
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int insnsSize = code.getInsns().codeSize();
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((insnsSize & 1) != 0) {
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnsSize++;
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setWriteSize(HEADER_SIZE + (insnsSize * 2) + catchesSize);
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void writeTo0(DexFile file, AnnotatedOutput out) {
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean annotates = out.annotates();
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int regSz = getRegistersSize();
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int outsSz = getOutsSize();
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int insSz = getInsSize();
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int insnsSz = code.getInsns().codeSize();
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean needPadding = (insnsSz & 1) != 0;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int triesSz = (catches == null) ? 0 : catches.triesSize();
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int debugOff = (debugInfo == null) ? 0 : debugInfo.getAbsoluteOffset();
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotates) {
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate(0, offsetString() + ' ' + ref.toHuman());
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate(2, "  registers_size: " + Hex.u2(regSz));
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate(2, "  ins_size:       " + Hex.u2(insSz));
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate(2, "  outs_size:      " + Hex.u2(outsSz));
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate(2, "  tries_size:     " + Hex.u2(triesSz));
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate(4, "  debug_off:      " + Hex.u4(debugOff));
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate(4, "  insns_size:     " + Hex.u4(insnsSz));
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // This isn't represented directly here, but it is useful to see.
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int size = throwsList.size();
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (size != 0) {
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.annotate(0, "  throws " + StdTypeList.toHuman(throwsList));
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(regSz);
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(insSz);
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(outsSz);
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(triesSz);
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeInt(debugOff);
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeInt(insnsSz);
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        writeCodes(file, out);
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (catches != null) {
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (needPadding) {
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (annotates) {
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    out.annotate(2, "  padding: 0");
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.writeShort(0);
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            catches.writeTo(file, out);
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotates) {
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * These are pointed at in the code header (above), but it's less
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * distracting to expand on them at the bottom of the code.
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (debugInfo != null) {
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.annotate(0, "  debug info");
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                debugInfo.annotateTo(file, out, "    ");
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #writeTo0} which writes out the actual bytecode.
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
28599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param file {@code non-null;} file we are part of
28699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} where to write to
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void writeCodes(DexFile file, AnnotatedOutput out) {
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DalvInsnList insns = code.getInsns();
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.writeTo(out);
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (RuntimeException ex) {
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ExceptionWithContext.withContext(ex, "...while writing " +
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "instructions for " + ref.toHuman());
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Get the in registers count.
301de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the count
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int getInsSize() {
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ref.getParameterWordCount(isStatic);
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Get the out registers count.
310de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the count
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int getOutsSize() {
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return code.getInsns().getOutsSize();
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Get the total registers count.
319de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the count
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int getRegistersSize() {
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return code.getInsns().getRegistersSize();
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
326