183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek/* 2eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * Copyright (C) 2007 The Android Open Source Project 3eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * 4eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * Licensed under the Apache License, Version 2.0 (the "License"); 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner * you may not use this file except in compliance with the License. 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner * You may obtain a copy of the License at 7eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * 8eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * http://www.apache.org/licenses/LICENSE-2.0 9eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * 1083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek * Unless required by applicable law or agreed to in writing, software 1183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek * distributed under the License is distributed on an "AS IS" BASIS, 12eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * See the License for the specific language governing permissions and 14eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * limitations under the License. 1583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek */ 1683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 17eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpackage com.android.dx.rop.cst; 18e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek 19eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekimport com.android.dx.util.ExceptionWithContext; 204c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenekimport com.android.dx.util.Hex; 215226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenekimport com.android.dx.util.MutabilityControl; 226bad354120ce0d35901e86ca63e5534b7b9ed092Ted Kremenek 234c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek/** 2459753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek * Standard implementation of {@link ConstantPool}, which directly stores 25eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * an array of {@link Constant} objects and can be made immutable. 26eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek */ 2705e14cd46ef44c07385aae96ec2fdcb9bf7e9467Ted Kremenekpublic final class StdConstantPool 2883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek extends MutabilityControl implements ConstantPool { 29eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek /** {@code non-null;} array of entries */ 30cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek private final Constant[] entries; 31cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek 32cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek /** 33cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek * Constructs an instance. All indices initially contain {@code null}. 34cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek * 35cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek * @param size the size of the pool; this corresponds to the 36cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek * class file field {@code constant_pool_count}, and is in fact 37cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek * always at least one more than the actual size of the constant pool, 38cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek * as element {@code 0} is always invalid. 39cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek */ 40cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek public StdConstantPool(int size) { 41cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek super(size > 1); 42cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek 43cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek if (size < 1) { 44cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek throw new IllegalArgumentException("size < 1"); 45f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek } 467090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek 474c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek entries = new Constant[size]; 48d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } 49d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek 50d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek /** {@inheritDoc} */ 51e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek public int size() { 52d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek return entries.length; 53d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } 54e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek 55d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek /** {@inheritDoc} */ 56d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek public Constant getOrNull(int n) { 57d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek try { 58d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek return entries[n]; 59f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek } catch (IndexOutOfBoundsException ex) { 60d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek // Translate the exception. 61d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek return throwInvalid(n); 62d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek } 63e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek } 64f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek 6583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek /** {@inheritDoc} */ 66d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek public Constant get0Ok(int n) { 67d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek if (n == 0) { 68e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek return null; 69d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } 70e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek 71d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek return get(n); 72e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek } 73d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 74eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek /** {@inheritDoc} */ 7583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek public Constant get(int n) { 76d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek try { 77d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek Constant result = entries[n]; 78d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek 79d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek if (result == null) { 80d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek throwInvalid(n); 81d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } 82d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek 83d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek return result; 84d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } catch (IndexOutOfBoundsException ex) { 855226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek // Translate the exception. 86d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek return throwInvalid(n); 87d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek } 88d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek } 89e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek 902680b5f926fad29c1a2b2723a70d189f4b637979Ted Kremenek /** 91eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * Sets the entry at the given index. 9283c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek * 9383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek * @param n {@code >= 1, < size();} which entry 94eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * @param cst {@code null-ok;} the constant to store 95ab422d17dce198f2af9851340ea7384771a2a8c5Ted Kremenek */ 96ab422d17dce198f2af9851340ea7384771a2a8c5Ted Kremenek public void set(int n, Constant cst) { 9783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek throwIfImmutable(); 9883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 99d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek boolean cat2 = (cst != null) && cst.isCategory2(); 100bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek 101eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek if (n < 1) { 10283c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek throw new IllegalArgumentException("n < 1"); 103d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek } 10483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 10583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek if (cat2) { 106eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek // Storing a category-2 entry nulls out the next index. 10783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek if (n == (entries.length - 1)) { 10883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek throw new IllegalArgumentException("(n == size - 1) && " + 109bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek "cst.isCategory2()"); 110eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek } 11183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek entries[n + 1] = null; 11283c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek } 113eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek 11483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek if ((cst != null) && (entries[n] == null)) { 115bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek /* 11683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek * Overwriting the second half of a category-2 entry nulls out 117d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek * the first half. 118bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek */ 11983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek Constant prev = entries[n - 1]; 12083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek if ((prev != null) && prev.isCategory2()) { 121d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek entries[n - 1] = null; 12283c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek } 123bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek } 124bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek 12583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek entries[n] = cst; 12683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek } 127bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek 12883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek /** 12983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek * Throws the right exception for an invalid cpi. 13083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek * 131bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek * @param idx the bad cpi 132bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek * @return never 133eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek * @throws ExceptionWithContext always thrown 134cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek */ 135cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek private static Constant throwInvalid(int idx) { 136cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek throw new ExceptionWithContext("invalid constant pool index " + 137cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek Hex.u2(idx)); 138cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek } 139cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek} 140cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek