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.code;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.SourcePosition;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.FixedSizeList;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * List of source position entries. This class includes a utility
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * method to extract an instance out of a {@link DalvInsnList}.
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class PositionList extends FixedSizeList {
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} empty instance */
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static final PositionList EMPTY = new PositionList(0);
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * constant for {@link #make} to indicate that no actual position
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * information should be returned
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static final int NONE = 1;
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * constant for {@link #make} to indicate that only line number
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * transitions should be returned
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static final int LINES = 2;
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * constant for {@link #make} to indicate that only "important" position
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * information should be returned. This includes block starts and
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instructions that might throw.
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static final int IMPORTANT = 3;
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Extracts and returns the source position information out of an
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instruction list.
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param insns {@code non-null;} instructions to convert
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param howMuch how much information should be included; one of the
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * static constants defined by this class
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the positions list
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static PositionList make(DalvInsnList insns, int howMuch) {
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        switch (howMuch) {
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case NONE: {
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return EMPTY;
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case LINES:
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case IMPORTANT: {
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                // Valid.
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            default: {
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                throw new IllegalArgumentException("bogus howMuch");
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        SourcePosition noInfo = SourcePosition.NO_INFO;
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        SourcePosition cur = noInfo;
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int sz = insns.size();
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        PositionList.Entry[] arr = new PositionList.Entry[sz];
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean lastWasTarget = false;
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int at = 0;
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < sz; i++) {
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            DalvInsn insn = insns.get(i);
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (insn instanceof CodeAddress) {
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                lastWasTarget = true;;
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                continue;
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            SourcePosition pos = insn.getPosition();
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (pos.equals(noInfo) || pos.sameLine(cur)) {
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                continue;
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if ((howMuch == IMPORTANT) && !lastWasTarget) {
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                continue;
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            cur = pos;
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            arr[at] = new PositionList.Entry(insn.getAddress(), pos);
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            at++;
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            lastWasTarget = false;
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        PositionList result = new PositionList(at);
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < at; i++) {
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result.set(i, arr[i]);
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        result.setImmutable();
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return result;
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance. All indices initially contain {@code null}.
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param size {@code >= 0;} the size of the list
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public PositionList(int size) {
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        super(size);
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the element at the given index. It is an error to call
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * this with the index for an element which was never set; if you
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * do that, this will throw {@code NullPointerException}.
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param n {@code >= 0, < size();} which index
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} element at that index
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Entry get(int n) {
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (Entry) get0(n);
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Sets the entry at the given index.
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param n {@code >= 0, < size();} which index
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param entry {@code non-null;} the entry to set at {@code n}
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void set(int n, Entry entry) {
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        set0(n, entry);
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Entry in a position list.
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static class Entry {
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} address of this entry */
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private final int address;
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code non-null;} corresponding source position information */
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private final SourcePosition position;
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Constructs an instance.
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param address {@code >= 0;} address of this entry
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param position {@code non-null;} corresponding source position information
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public Entry (int address, SourcePosition position) {
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (address < 0) {
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                throw new IllegalArgumentException("address < 0");
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (position == null) {
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                throw new NullPointerException("position == null");
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.address = address;
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.position = position;
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Gets the address.
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return {@code >= 0;} the address
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public int getAddress() {
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return address;
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Gets the source position information.
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return {@code non-null;} the position information
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public SourcePosition getPosition() {
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return position;
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
193