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.rop;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstType;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.StdTypeList;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.TypeList;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.FixedSizeList;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.IntList;
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * List of catch entries, that is, the elements of an "exception table,"
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * which is part of a standard {@code Code} attribute.
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class ByteCatchList extends FixedSizeList {
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} convenient zero-entry instance */
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static final ByteCatchList EMPTY = new ByteCatchList(0);
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance.
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param count the number of elements to be in the table
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public ByteCatchList(int count) {
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        super(count);
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the total length of this structure in bytes, when included in
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * a {@code Code} attribute. The returned value includes the
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * two bytes for {@code exception_table_length}.
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 2;} the total length, in bytes
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int byteLength() {
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return 2 + size() * 8;
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the indicated item.
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param n {@code >= 0;} which item
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} the indicated item
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Item get(int n) {
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (Item) get0(n);
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Sets the item at the given index.
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param n {@code >= 0, < size();} which entry to set
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param item {@code non-null;} the item
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void set(int n, Item item) {
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (item == null) {
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("item == null");
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        set0(n, item);
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Sets the item at the given index.
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param n {@code >= 0, < size();} which entry to set
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param startPc {@code >= 0;} the start pc (inclusive) of the handler's range
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param endPc {@code >= startPc;} the end pc (exclusive) of the
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * handler's range
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param handlerPc {@code >= 0;} the pc of the exception handler
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param exceptionClass {@code null-ok;} the exception class or
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code null} to catch all exceptions with this handler
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void set(int n, int startPc, int endPc, int handlerPc,
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            CstType exceptionClass) {
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        set0(n, new Item(startPc, endPc, handlerPc, exceptionClass));
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the list of items active at the given address. The result is
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * automatically made immutable.
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param pc which address
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} list of exception handlers active at
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code pc}
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public ByteCatchList listFor(int pc) {
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int sz = size();
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        Item[] resultArr = new Item[sz];
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int resultSz = 0;
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < sz; i++) {
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Item one = get(i);
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (one.covers(pc) && typeNotFound(one, resultArr, resultSz)) {
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                resultArr[resultSz] = one;
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                resultSz++;
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (resultSz == 0) {
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return EMPTY;
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        ByteCatchList result = new ByteCatchList(resultSz);
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < resultSz; i++) {
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result.set(i, resultArr[i]);
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        result.setImmutable();
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return result;
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper method for {@link #listFor}, which tells whether a match
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is <i>not</i> found for the exception type of the given item in
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * the given array. A match is considered to be either an exact type
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * match or the class {@code Object} which represents a catch-all.
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param item {@code non-null;} item with the exception type to look for
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param arr {@code non-null;} array to search in
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param count {@code non-null;} maximum number of elements in the array to check
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code true} iff the exception type is <i>not</i> found
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static boolean typeNotFound(Item item, Item[] arr, int count) {
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        CstType type = item.getExceptionClass();
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < count; i++) {
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            CstType one = arr[i].getExceptionClass();
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if ((one == type) || (one == CstType.OBJECT)) {
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return false;
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return true;
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns a target list corresponding to this instance. The result
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is a list of all the exception handler addresses, with the given
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code noException} address appended if appropriate. The
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * result is automatically made immutable.
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param noException {@code >= -1;} the no-exception address to append, or
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code -1} not to append anything
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} list of exception targets, with
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code noException} appended if necessary
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public IntList toTargetList(int noException) {
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (noException < -1) {
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("noException < -1");
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean hasDefault = (noException >= 0);
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int sz = size();
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (sz == 0) {
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (hasDefault) {
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                /*
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                 * The list is empty, but there is a no-exception
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                 * address; so, the result is just that address.
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                 */
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return IntList.makeImmutable(noException);
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            /*
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul             * The list is empty and there isn't even a no-exception
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul             * address.
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul             */
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return IntList.EMPTY;
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        IntList result = new IntList(sz + (hasDefault ? 1 : 0));
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < sz; i++) {
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result.add(get(i).getHandlerPc());
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (hasDefault) {
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result.add(noException);
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        result.setImmutable();
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return result;
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns a rop-style catches list equivalent to this one.
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the converted instance
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public TypeList toRopCatchList() {
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int sz = size();
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (sz == 0) {
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return StdTypeList.EMPTY;
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StdTypeList result = new StdTypeList(sz);
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < sz; i++) {
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result.set(i, get(i).getExceptionClass().getClassType());
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        result.setImmutable();
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return result;
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Item in an exception handler list.
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static class Item {
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} the start pc (inclusive) of the handler's range */
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private final int startPc;
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= startPc;} the end pc (exclusive) of the handler's range */
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private final int endPc;
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} the pc of the exception handler */
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private final int handlerPc;
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code null-ok;} the exception class or {@code null} to catch all
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * exceptions with this handler */
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private final CstType exceptionClass;
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Constructs an instance.
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param startPc {@code >= 0;} the start pc (inclusive) of the
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * handler's range
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param endPc {@code >= startPc;} the end pc (exclusive) of the
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * handler's range
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param handlerPc {@code >= 0;} the pc of the exception handler
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param exceptionClass {@code null-ok;} the exception class or
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * {@code null} to catch all exceptions with this handler
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public Item(int startPc, int endPc, int handlerPc,
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                CstType exceptionClass) {
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (startPc < 0) {
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                throw new IllegalArgumentException("startPc < 0");
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (endPc < startPc) {
255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                throw new IllegalArgumentException("endPc < startPc");
256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (handlerPc < 0) {
259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                throw new IllegalArgumentException("handlerPc < 0");
260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.startPc = startPc;
263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.endPc = endPc;
264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.handlerPc = handlerPc;
265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.exceptionClass = exceptionClass;
266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Gets the start pc (inclusive) of the handler's range.
270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return {@code >= 0;} the start pc (inclusive) of the handler's range.
272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public int getStartPc() {
274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return startPc;
275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Gets the end pc (exclusive) of the handler's range.
279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return {@code >= startPc;} the end pc (exclusive) of the
281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * handler's range.
282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public int getEndPc() {
284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return endPc;
285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Gets the pc of the exception handler.
289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return {@code >= 0;} the pc of the exception handler
291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public int getHandlerPc() {
293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return handlerPc;
294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Gets the class of exception handled.
298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return {@code non-null;} the exception class; {@link CstType#OBJECT}
300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * if this entry handles all possible exceptions
301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public CstType getExceptionClass() {
303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return (exceptionClass != null) ?
304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                exceptionClass : CstType.OBJECT;
305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Returns whether the given address is in the range of this item.
309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param pc the address
311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return {@code true} iff this item covers {@code pc}
312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public boolean covers(int pc) {
314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return (pc >= startPc) && (pc < endPc);
315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
318