001/* 002 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.compiler.common.util; 024 025/** 026 * The {@code ArrayMap} class implements an efficient one-level map which is implemented as an 027 * array. Note that because of the one-level array inside, this data structure performs best when 028 * the range of integer keys is small and densely used. Note that the implementation can handle 029 * arbitrary intervals, including negative numbers, up to intervals of size 2^31 - 1. 030 */ 031public class ArrayMap<T> { 032 033 private static final int INITIAL_SIZE = 5; // how big the initial array should be 034 private static final int EXTRA = 2; // how far on the left or right of a new element to grow 035 036 Object[] map; 037 int low; 038 039 /** 040 * Constructs a new {@code ArrayMap} with no initial assumptions. 041 */ 042 public ArrayMap() { 043 } 044 045 /** 046 * Constructs a new {@code ArrayMap} that initially covers the specified interval. Note that 047 * this map will automatically expand if necessary later. 048 * 049 * @param low the low index, inclusive 050 * @param high the high index, exclusive 051 */ 052 public ArrayMap(int low, int high) { 053 this.low = low; 054 this.map = new Object[high - low + 1]; 055 } 056 057 /** 058 * Puts a new value in the map at the specified index. 059 * 060 * @param i the index at which to store the value 061 * @param value the value to store at the specified index 062 */ 063 public void put(int i, T value) { 064 int index = i - low; 065 if (map == null) { 066 // no map yet 067 map = new Object[INITIAL_SIZE]; 068 low = index - 2; 069 map[INITIAL_SIZE / 2] = value; 070 } else if (index < 0) { 071 // grow backwards 072 growBackward(i, value); 073 } else if (index >= map.length) { 074 // grow forwards 075 growForward(i, value); 076 } else { 077 // no growth necessary 078 map[index] = value; 079 } 080 } 081 082 /** 083 * Gets the value at the specified index in the map. 084 * 085 * @param i the index 086 * @return the value at the specified index; {@code null} if there is no value at the specified 087 * index, or if the index is out of the currently stored range 088 */ 089 public T get(int i) { 090 int index = i - low; 091 if (map == null || index < 0 || index >= map.length) { 092 return null; 093 } 094 Class<T> type = null; 095 return Util.uncheckedCast(type, map[index]); 096 } 097 098 public int length() { 099 return map.length; 100 } 101 102 private void growBackward(int i, T value) { 103 int nlow = i - EXTRA; 104 Object[] nmap = new Object[low - nlow + map.length]; 105 System.arraycopy(map, 0, nmap, low - nlow, map.length); 106 map = nmap; 107 low = nlow; 108 map[i - low] = value; 109 } 110 111 private void growForward(int i, T value) { 112 int nlen = i - low + 1 + EXTRA; 113 Object[] nmap = new Object[nlen]; 114 System.arraycopy(map, 0, nmap, 0, map.length); 115 map = nmap; 116 map[i - low] = value; 117 } 118}