PositionList.java revision 579d7739c53a2707ad711a2d2cae46d7d782f061
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dx.dex.code;
18
19import com.android.dx.rop.code.SourcePosition;
20import com.android.dx.util.FixedSizeList;
21
22/**
23 * List of source position entries. This class includes a utility
24 * method to extract an instance out of a {@link DalvInsnList}.
25 */
26public final class PositionList extends FixedSizeList {
27    /** {@code non-null;} empty instance */
28    public static final PositionList EMPTY = new PositionList(0);
29
30    /**
31     * constant for {@link #make} to indicate that no actual position
32     * information should be returned
33     */
34    public static final int NONE = 1;
35
36    /**
37     * constant for {@link #make} to indicate that only line number
38     * transitions should be returned
39     */
40    public static final int LINES = 2;
41
42    /**
43     * constant for {@link #make} to indicate that only "important" position
44     * information should be returned. This includes block starts and
45     * instructions that might throw.
46     */
47    public static final int IMPORTANT = 3;
48
49    /**
50     * Extracts and returns the source position information out of an
51     * instruction list.
52     *
53     * @param insns {@code non-null;} instructions to convert
54     * @param howMuch how much information should be included; one of the
55     * static constants defined by this class
56     * @return {@code non-null;} the positions list
57     */
58    public static PositionList make(DalvInsnList insns, int howMuch) {
59        switch (howMuch) {
60            case NONE: {
61                return EMPTY;
62            }
63            case LINES:
64            case IMPORTANT: {
65                // Valid.
66                break;
67            }
68            default: {
69                throw new IllegalArgumentException("bogus howMuch");
70            }
71        }
72
73        SourcePosition noInfo = SourcePosition.NO_INFO;
74        SourcePosition cur = noInfo;
75        int sz = insns.size();
76        PositionList.Entry[] arr = new PositionList.Entry[sz];
77        boolean lastWasTarget = false;
78        int at = 0;
79
80        for (int i = 0; i < sz; i++) {
81            DalvInsn insn = insns.get(i);
82
83            if (insn instanceof CodeAddress) {
84                lastWasTarget = true;;
85                continue;
86            }
87
88            SourcePosition pos = insn.getPosition();
89
90            if (pos.equals(noInfo) || pos.sameLine(cur)) {
91                continue;
92            }
93
94            if ((howMuch == IMPORTANT) && !lastWasTarget) {
95                continue;
96            }
97
98            cur = pos;
99            arr[at] = new PositionList.Entry(insn.getAddress(), pos);
100            at++;
101
102            lastWasTarget = false;
103        }
104
105        PositionList result = new PositionList(at);
106        for (int i = 0; i < at; i++) {
107            result.set(i, arr[i]);
108        }
109
110        result.setImmutable();
111        return result;
112    }
113
114    /**
115     * Constructs an instance. All indices initially contain {@code null}.
116     *
117     * @param size {@code >= 0;} the size of the list
118     */
119    public PositionList(int size) {
120        super(size);
121    }
122
123    /**
124     * Gets the element at the given index. It is an error to call
125     * this with the index for an element which was never set; if you
126     * do that, this will throw {@code NullPointerException}.
127     *
128     * @param n {@code >= 0, < size();} which index
129     * @return {@code non-null;} element at that index
130     */
131    public Entry get(int n) {
132        return (Entry) get0(n);
133    }
134
135    /**
136     * Sets the entry at the given index.
137     *
138     * @param n {@code >= 0, < size();} which index
139     * @param entry {@code non-null;} the entry to set at {@code n}
140     */
141    public void set(int n, Entry entry) {
142        set0(n, entry);
143    }
144
145    /**
146     * Entry in a position list.
147     */
148    public static class Entry {
149        /** {@code >= 0;} address of this entry */
150        private final int address;
151
152        /** {@code non-null;} corresponding source position information */
153        private final SourcePosition position;
154
155        /**
156         * Constructs an instance.
157         *
158         * @param address {@code >= 0;} address of this entry
159         * @param position {@code non-null;} corresponding source position information
160         */
161        public Entry (int address, SourcePosition position) {
162            if (address < 0) {
163                throw new IllegalArgumentException("address < 0");
164            }
165
166            if (position == null) {
167                throw new NullPointerException("position == null");
168            }
169
170            this.address = address;
171            this.position = position;
172        }
173
174        /**
175         * Gets the address.
176         *
177         * @return {@code >= 0;} the address
178         */
179        public int getAddress() {
180            return address;
181        }
182
183        /**
184         * Gets the source position information.
185         *
186         * @return {@code non-null;} the position information
187         */
188        public SourcePosition getPosition() {
189            return position;
190        }
191    }
192}
193