1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.file;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.CatchTable;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.CstInsn;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.DalvCode;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.DalvInsn;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.DalvInsnList;
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.LocalList;
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.PositionList;
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant;
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstMemberRef;
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstMethodRef;
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstType;
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.StdTypeList;
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Type;
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.TypeList;
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput;
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ExceptionWithContext;
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Hex;
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.PrintWriter;
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.HashSet;
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Representation of all the parts needed for concrete methods in a
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code dex} file.
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class CodeItem extends OffsettedItem {
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** file alignment of this class, in bytes */
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int ALIGNMENT = 4;
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** write size of the header of this class, in bytes */
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int HEADER_SIZE = 16;
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} method that this code implements */
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final CstMethodRef ref;
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} the bytecode instructions and associated data */
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final DalvCode code;
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code null-ok;} the catches, if needed; set in {@link #addContents} */
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private CatchStructs catches;
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** whether this instance is for a {@code static} method */
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final boolean isStatic;
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code non-null;} list of possibly-thrown exceptions; just used in
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * generating debugging output (listings)
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final TypeList throwsList;
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code null-ok;} the debug info or {@code null} if there is none;
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * set in {@link #addContents}
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private DebugInfoItem debugInfo;
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance.
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param ref {@code non-null;} method that this code implements
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param code {@code non-null;} the underlying code
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param isStatic whether this instance is for a {@code static}
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * method
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param throwsList {@code non-null;} list of possibly-thrown exceptions,
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * just used in generating debugging output (listings)
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public CodeItem(CstMethodRef ref, DalvCode code, boolean isStatic,
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            TypeList throwsList) {
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        super(ALIGNMENT, -1);
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (ref == null) {
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("ref == null");
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (code == null) {
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("code == null");
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (throwsList == null) {
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("throwsList == null");
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.ref = ref;
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.code = code;
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.isStatic = isStatic;
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.throwsList = throwsList;
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.catches = null;
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.debugInfo = null;
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public ItemType itemType() {
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return ItemType.TYPE_CODE_ITEM;
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void addContents(DexFile file) {
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        MixedItemSection byteData = file.getByteData();
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        TypeIdsSection typeIds = file.getTypeIds();
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (code.hasPositions() || code.hasLocals()) {
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            debugInfo = new DebugInfoItem(code, isStatic, ref);
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            byteData.add(debugInfo);
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (code.hasAnyCatches()) {
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (Type type : code.getCatchTypes()) {
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                typeIds.intern(type);
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            catches = new CatchStructs(code);
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (Constant c : code.getInsnConstants()) {
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            file.internIfAppropriate(c);
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toString() {
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return "CodeItem{" + toHuman() + "}";
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toHuman() {
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return ref.toHuman();
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the reference to the method this instance implements.
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the method reference
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public CstMethodRef getRef() {
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return ref;
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Does a human-friendly dump of this instance.
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} where to dump
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param prefix {@code non-null;} per-line prefix to use
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param verbose whether to be verbose with the output
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void debugPrint(PrintWriter out, String prefix, boolean verbose) {
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.println(ref.toHuman() + ":");
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        DalvInsnList insns = code.getInsns();
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.println("regs: " + Hex.u2(getRegistersSize()) +
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                "; ins: " + Hex.u2(getInsSize()) + "; outs: " +
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                Hex.u2(getOutsSize()));
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        insns.debugPrint(out, prefix, verbose);
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        String prefix2 = prefix + "  ";
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (catches != null) {
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.print(prefix);
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.println("catches");
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            catches.debugPrint(out, prefix2);
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (debugInfo != null) {
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.print(prefix);
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.println("debug info");
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            debugInfo.debugPrint(out, prefix2);
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected void place0(Section addedTo, int offset) {
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        final DexFile file = addedTo.getFile();
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int catchesSize;
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /*
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * In order to get the catches and insns, all the code's
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * constants need to be assigned indices.
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        code.assignIndices(new DalvCode.AssignIndicesCallback() {
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                public int getIndex(Constant cst) {
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    IndexedItem item = file.findItemOrNull(cst);
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    if (item == null) {
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                        return -1;
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    }
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    return item.getIndex();
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                }
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            });
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (catches != null) {
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            catches.encode(file);
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            catchesSize = catches.writeSize();
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            catchesSize = 0;
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /*
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * The write size includes the header, two bytes per code
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * unit, post-code padding if necessary, and however much
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * space the catches need.
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int insnsSize = code.getInsns().codeSize();
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if ((insnsSize & 1) != 0) {
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            insnsSize++;
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        setWriteSize(HEADER_SIZE + (insnsSize * 2) + catchesSize);
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected void writeTo0(DexFile file, AnnotatedOutput out) {
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean annotates = out.annotates();
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int regSz = getRegistersSize();
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int outsSz = getOutsSize();
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int insSz = getInsSize();
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int insnsSz = code.getInsns().codeSize();
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean needPadding = (insnsSz & 1) != 0;
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int triesSz = (catches == null) ? 0 : catches.triesSize();
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int debugOff = (debugInfo == null) ? 0 : debugInfo.getAbsoluteOffset();
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotates) {
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(0, offsetString() + ' ' + ref.toHuman());
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(2, "  registers_size: " + Hex.u2(regSz));
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(2, "  ins_size:       " + Hex.u2(insSz));
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(2, "  outs_size:      " + Hex.u2(outsSz));
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(2, "  tries_size:     " + Hex.u2(triesSz));
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(4, "  debug_off:      " + Hex.u4(debugOff));
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(4, "  insns_size:     " + Hex.u4(insnsSz));
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // This isn't represented directly here, but it is useful to see.
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int size = throwsList.size();
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (size != 0) {
255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate(0, "  throws " + StdTypeList.toHuman(throwsList));
256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeShort(regSz);
260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeShort(insSz);
261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeShort(outsSz);
262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeShort(triesSz);
263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeInt(debugOff);
264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeInt(insnsSz);
265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        writeCodes(file, out);
267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (catches != null) {
269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (needPadding) {
270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                if (annotates) {
271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    out.annotate(2, "  padding: 0");
272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                }
273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.writeShort(0);
274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            catches.writeTo(file, out);
277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotates) {
280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            /*
281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul             * These are pointed at in the code header (above), but it's less
282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul             * distracting to expand on them at the bottom of the code.
283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul             */
284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (debugInfo != null) {
285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate(0, "  debug info");
286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                debugInfo.annotateTo(file, out, "    ");
287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper for {@link #writeTo0} which writes out the actual bytecode.
293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param file {@code non-null;} file we are part of
295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} where to write to
296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private void writeCodes(DexFile file, AnnotatedOutput out) {
298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        DalvInsnList insns = code.getInsns();
299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        try {
301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            insns.writeTo(out);
302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } catch (RuntimeException ex) {
303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw ExceptionWithContext.withContext(ex, "...while writing " +
304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    "instructions for " + ref.toHuman());
305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Get the in registers count.
310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return the count
312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private int getInsSize() {
314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return ref.getParameterWordCount(isStatic);
315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Get the out registers count.
319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return the count
321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private int getOutsSize() {
323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return code.getInsns().getOutsSize();
324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Get the total registers count.
328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return the count
330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private int getRegistersSize() {
332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return code.getInsns().getRegistersSize();
333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
335