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.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.SourcePosition;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.FixedSizeList;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * List of source position entries. This class includes a utility
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method to extract an instance out of a {@link DalvInsnList}.
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class PositionList extends FixedSizeList {
2799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} empty instance */
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final PositionList EMPTY = new PositionList(0);
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constant for {@link #make} to indicate that no actual position
32de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * information should be returned
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int NONE = 1;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constant for {@link #make} to indicate that only line number
38de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * transitions should be returned
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int LINES = 2;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constant for {@link #make} to indicate that only "important" position
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * information should be returned. This includes block starts and
45de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * instructions that might throw.
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int IMPORTANT = 3;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Extracts and returns the source position information out of an
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instruction list.
52de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
5399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insns {@code non-null;} instructions to convert
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param howMuch how much information should be included; one of the
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * static constants defined by this class
5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the positions list
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static PositionList make(DalvInsnList insns, int howMuch) {
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (howMuch) {
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case NONE: {
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return EMPTY;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case LINES:
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case IMPORTANT: {
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Valid.
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default: {
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalArgumentException("bogus howMuch");
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SourcePosition noInfo = SourcePosition.NO_INFO;
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SourcePosition cur = noInfo;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = insns.size();
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        PositionList.Entry[] arr = new PositionList.Entry[sz];
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean lastWasTarget = false;
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int at = 0;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < sz; i++) {
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DalvInsn insn = insns.get(i);
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (insn instanceof CodeAddress) {
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                lastWasTarget = true;;
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SourcePosition pos = insn.getPosition();
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pos.equals(noInfo) || pos.sameLine(cur)) {
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((howMuch == IMPORTANT) && !lastWasTarget) {
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cur = pos;
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            arr[at] = new PositionList.Entry(insn.getAddress(), pos);
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            at++;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lastWasTarget = false;
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        PositionList result = new PositionList(at);
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < at; i++) {
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.set(i, arr[i]);
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result.setImmutable();
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
11599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Constructs an instance. All indices initially contain {@code null}.
116de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
11799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param size {@code >= 0;} the size of the list
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public PositionList(int size) {
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(size);
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the element at the given index. It is an error to call
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this with the index for an element which was never set; if you
12699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * do that, this will throw {@code NullPointerException}.
127de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
12899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 0, < size();} which index
12999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} element at that index
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Entry get(int n) {
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (Entry) get0(n);
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets the entry at the given index.
137de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
13899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 0, < size();} which index
13999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param entry {@code non-null;} the entry to set at {@code n}
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void set(int n, Entry entry) {
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set0(n, entry);
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Entry in a position list.
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static class Entry {
14999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code >= 0;} address of this entry */
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final int address;
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
15299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code non-null;} corresponding source position information */
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final SourcePosition position;
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Constructs an instance.
157de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro         *
15899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param address {@code >= 0;} address of this entry
15999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param position {@code non-null;} corresponding source position information
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public Entry (int address, SourcePosition position) {
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (address < 0) {
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalArgumentException("address < 0");
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (position == null) {
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new NullPointerException("position == null");
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.address = address;
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.position = position;
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the address.
176de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro         *
17799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code >= 0;} the address
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int getAddress() {
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return address;
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the source position information.
185de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro         *
18699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code non-null;} the position information
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public SourcePosition getPosition() {
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return position;
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
193