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.rop.cst;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dex.util.ExceptionWithContext;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.MutabilityControl;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Standard implementation of {@link ConstantPool}, which directly stores
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an array of {@link Constant} objects and can be made immutable.
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class StdConstantPool
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        extends MutabilityControl implements ConstantPool {
2999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} array of entries */
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final Constant[] entries;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
3399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Constructs an instance. All indices initially contain {@code null}.
34de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param size the size of the pool; this corresponds to the
3699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * class file field {@code constant_pool_count}, and is in fact
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * always at least one more than the actual size of the constant pool,
3899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * as element {@code 0} is always invalid.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public StdConstantPool(int size) {
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(size > 1);
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (size < 1) {
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("size < 1");
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        entries = new Constant[size];
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int size() {
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return entries.length;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Constant getOrNull(int n) {
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return entries[n];
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IndexOutOfBoundsException ex) {
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Translate the exception.
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return throwInvalid(n);
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Constant get0Ok(int n) {
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (n == 0) {
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return get(n);
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Constant get(int n) {
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Constant result = entries[n];
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (result == null) {
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throwInvalid(n);
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return result;
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IndexOutOfBoundsException ex) {
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Translate the exception.
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return throwInvalid(n);
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets the entry at the given index.
92de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
9399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 1, < size();} which entry
9499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param cst {@code null-ok;} the constant to store
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void set(int n, Constant cst) {
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwIfImmutable();
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean cat2 = (cst != null) && cst.isCategory2();
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (n < 1) {
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n < 1");
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cat2) {
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Storing a category-2 entry nulls out the next index.
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (n == (entries.length - 1)) {
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalArgumentException("(n == size - 1) && " +
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                                   "cst.isCategory2()");
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            entries[n + 1] = null;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((cst != null) && (entries[n] == null)) {
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Overwriting the second half of a category-2 entry nulls out
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the first half.
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Constant prev = entries[n - 1];
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((prev != null) && prev.isCategory2()) {
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                entries[n - 1] = null;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        entries[n] = cst;
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Throws the right exception for an invalid cpi.
130de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param idx the bad cpi
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return never
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws ExceptionWithContext always thrown
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static Constant throwInvalid(int idx) {
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new ExceptionWithContext("invalid constant pool index " +
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                       Hex.u2(idx));
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
140