1 5 package com.tc.object.bytecode.hook.impl; 6 7 import com.tc.object.TCObject; 8 import com.tc.object.util.IdentityWeakHashMap; 9 import com.tc.util.Assert; 10 11 import java.util.HashMap ; 12 import java.util.Map ; 13 14 18 public class ArrayManager { 19 20 private final static int CACHE_DEPTH = 2; 22 private final static int NUM_MAPS = 32; 23 private final static int INITIAL_CAPACITY = 25000; 24 private final static float LOAD_FACTOR = 0.75F; 25 26 private static final Map[] maps = new Map[NUM_MAPS]; 27 private static final Map primClasses = new HashMap(); 28 private static final Object [] keys = new Object [NUM_MAPS * CACHE_DEPTH]; 29 private static final TCObject[] values = new TCObject[NUM_MAPS * CACHE_DEPTH]; 30 31 static { 32 for (int i = 0; i < maps.length; i++) { 33 maps[i] = new IdentityWeakHashMap(INITIAL_CAPACITY, LOAD_FACTOR); 34 } 35 } 36 37 private ArrayManager() { 38 } 40 41 public static void register(Object array, TCObject tco) { 42 if ((array == null) || (tco == null)) { throw new NullPointerException (); } 43 44 final int index = array.hashCode() % NUM_MAPS; 45 final Map map = maps[index]; 46 final int start = index * CACHE_DEPTH; 47 final int end = start + CACHE_DEPTH; 48 final Object prev; 49 50 synchronized (map) { 51 for (int i = start; i < end; i++) { 52 if (keys[i] == array) { 53 values[i] = tco; 54 break; 55 } 56 } 57 58 prev = map.put(array, tco); 59 } 60 if (prev != null) { throw new AssertionError ("replaced mapping for " + array); } 61 } 62 63 public static TCObject getObject(Object array) { 64 final int hash = array.hashCode(); 65 final int index = hash % NUM_MAPS; 66 final Map map = maps[index]; 67 final int start = index * CACHE_DEPTH; 68 final int end = start + CACHE_DEPTH; 69 70 synchronized (map) { 71 for (int i = start; i < end; i++) { 72 if (keys[i] == array) { return values[i]; } 73 } 74 75 int evict = start + (hash % CACHE_DEPTH); 76 TCObject rv = (TCObject) map.get(array); 77 keys[evict] = array; 78 values[evict] = rv; 79 return rv; 80 } 81 } 82 83 public static TCObject getCloneObject(Object array) { 84 return getObject(array); 85 } 86 87 public static Object get(Object array, int index) { 89 if (array == null) throw new NullPointerException (); 90 91 if (array instanceof boolean[]) return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE; 92 if (array instanceof byte[]) return new Byte (((byte[]) array)[index]); 93 if (array instanceof char[]) return new Character (((char[]) array)[index]); 94 if (array instanceof short[]) return new Short (((short[]) array)[index]); 95 if (array instanceof int[]) return new Integer (((int[]) array)[index]); 96 if (array instanceof long[]) return new Long (((long[]) array)[index]); 97 if (array instanceof float[]) return new Float (((float[]) array)[index]); 98 if (array instanceof double[]) return new Double (((double[]) array)[index]); 99 100 if (array instanceof Object []) { 101 TCObject tco = getObject(array); 102 if (tco != null) { 103 synchronized (tco.getResolveLock()) { 104 tco.resolveArrayReference(index); 105 return ((Object []) array)[index]; 106 } 107 } else { 108 return ((Object []) array)[index]; 109 } 110 } 111 112 throw new IllegalArgumentException ("Not an array type: " + array.getClass().getName()); 113 114 } 115 116 public static void objectArrayChanged(Object [] array, int index, Object value) { 117 Object existingObj = array[index]; if (false && existingObj != existingObj) Assert.fail(); 120 TCObject tco = getObject(array); 121 if (tco != null) { 122 tco.objectFieldChanged(array.getClass().getName(), null, value, index); 123 } 124 array[index] = value; 125 } 126 127 public static void shortArrayChanged(short[] array, int index, short value) { 128 short existingVal = array[index]; if (false && existingVal != existingVal) Assert.fail(); 131 TCObject tco = getObject(array); 132 if (tco != null) { 133 tco.shortFieldChanged(null, null, value, index); 134 } 135 array[index] = value; 136 } 137 138 public static void longArrayChanged(long[] array, int index, long value) { 139 long existingVal = array[index]; if (false && existingVal != existingVal) Assert.fail(); 142 TCObject tco = getObject(array); 143 if (tco != null) { 144 tco.longFieldChanged(null, null, value, index); 145 } 146 array[index] = value; 147 } 148 149 public static void intArrayChanged(int[] array, int index, int value) { 150 int existingVal = array[index]; if (false && existingVal != existingVal) Assert.fail(); 153 TCObject tco = getObject(array); 154 if (tco != null) { 155 tco.intFieldChanged(null, null, value, index); 156 } 157 array[index] = value; 158 } 159 160 public static void floatArrayChanged(float[] array, int index, float value) { 161 float existingVal = array[index]; if (false && existingVal != existingVal) Assert.fail(); 164 TCObject tco = getObject(array); 165 if (tco != null) { 166 tco.floatFieldChanged(null, null, value, index); 167 } 168 array[index] = value; 169 } 170 171 public static void doubleArrayChanged(double[] array, int index, double value) { 172 double existingVal = array[index]; if (false && existingVal != existingVal) Assert.fail(); 175 TCObject tco = getObject(array); 176 if (tco != null) { 177 tco.doubleFieldChanged(null, null, value, index); 178 } 179 array[index] = value; 180 } 181 182 public static void charArrayChanged(char[] array, int index, char value) { 183 char existingVal = array[index]; if (false && existingVal != existingVal) Assert.fail(); 186 TCObject tco = getObject(array); 187 if (tco != null) { 188 tco.charFieldChanged(null, null, value, index); 189 } 190 array[index] = value; 191 } 192 193 public static void byteOrBooleanArrayChanged(Object array, int index, byte value) { 194 if (array == null) { throw new NullPointerException (); } 195 196 if (array.getClass().getComponentType().equals(Boolean.TYPE)) { 198 boolean[] booleanArray = (boolean[]) array; 199 boolean existingBooleanVal = booleanArray[index]; if (false && existingBooleanVal != existingBooleanVal) Assert.fail(); boolean booleanValue = value == 1; 203 204 TCObject tco = getObject(array); 205 if (tco != null) { 206 tco.booleanFieldChanged(null, null, booleanValue, index); 207 } 208 booleanArray[index] = booleanValue; 209 } else { 210 byte[] byteArray = (byte[]) array; 211 byte existingByteVal = byteArray[index]; if (false && existingByteVal != existingByteVal) Assert.fail(); 215 TCObject tco = getObject(array); 216 if (tco != null) { 217 tco.byteFieldChanged(null, null, value, index); 218 } 219 byteArray[index] = value; 220 } 221 } 222 223 public static void arraycopy(final Object src, final int srcPos, final Object dest, final int destPos, 224 final int length) { 225 if ((src == null) || (dest == null)) { throw new NullPointerException (); } 227 228 TCObject tcDest = getObject(dest); 229 Class destType = dest.getClass().getComponentType(); 230 if (destType == null) { throw new ArrayStoreException (); } 231 232 boolean isDestPrimitive = destType.isPrimitive(); 233 234 if (isDestPrimitive && tcDest == null) { 237 System.arraycopy(src, srcPos, dest, destPos, length); 238 return; 239 } 240 241 TCObject tcSrc = getObject(src); 243 244 if ((tcDest != null) || (tcSrc != null)) { 245 246 Class srcType = src.getClass().getComponentType(); 247 if (srcType == null) { throw new ArrayStoreException (); } 248 boolean isSrcPrimitive = srcType.isPrimitive(); 249 250 if (isDestPrimitive) { 251 int destCode = getCodeForType(destType); 252 253 if (isSrcPrimitive) { 255 int srcCode = getCodeForType(srcType); 256 if (srcCode != destCode) { throw new ArrayStoreException (); } 257 } else { 258 throw new ArrayStoreException (); 259 } 260 261 switch (destCode) { 262 case BOOLEAN: 263 booleanArrayCopy((boolean[]) src, srcPos, (boolean[]) dest, destPos, length, tcDest); 264 break; 265 case BYTE: 266 byteArrayCopy((byte[]) src, srcPos, (byte[]) dest, destPos, length, tcDest); 267 break; 268 case CHAR: 269 charArrayCopy((char[]) src, srcPos, (char[]) dest, destPos, length, tcDest); 270 break; 271 case DOUBLE: 272 doubleArrayCopy((double[]) src, srcPos, (double[]) dest, destPos, length, tcDest); 273 break; 274 case FLOAT: 275 floatArrayCopy((float[]) src, srcPos, (float[]) dest, destPos, length, tcDest); 276 break; 277 case INT: 278 intArrayCopy((int[]) src, srcPos, (int[]) dest, destPos, length, tcDest); 279 break; 280 case LONG: 281 longArrayCopy((long[]) src, srcPos, (long[]) dest, destPos, length, tcDest); 282 break; 283 case SHORT: 284 shortArrayCopy((short[]) src, srcPos, (short[]) dest, destPos, length, tcDest); 285 break; 286 default: 287 throw Assert.failure("unexpected type code: " + destCode); 288 } 289 } else { 290 if (isSrcPrimitive) { throw new ArrayStoreException (); } 291 292 Object [] destArray = (Object []) dest; 293 Object [] srcArray = (Object []) src; 294 295 if ((srcPos < 0) || (destPos < 0) || (length < 0) || (srcPos + length > srcArray.length) 296 || (destPos + length > destArray.length)) throw new ArrayIndexOutOfBoundsException (); 297 298 Object [] l2subset = new Object [length]; 299 300 if (tcSrc != null) { 301 synchronized (tcSrc.getResolveLock()) { 302 for (int i = 0; i < length; i++) { 303 tcSrc.resolveArrayReference(srcPos + i); 304 l2subset[i] = srcArray[srcPos + i]; 306 } 307 } 308 } else { 309 System.arraycopy(src, srcPos, l2subset, 0, length); 310 } 311 312 int actualLength = length; 313 if (!destType.isAssignableFrom(srcType)) { 315 for (int i = 0, n = l2subset.length; i < n; i++) { 316 Object srcVal = l2subset[i]; 317 if (srcVal != null) { 318 if (!destType.isAssignableFrom(srcVal.getClass())) { 319 actualLength = i; 320 break; 321 } 322 } 323 } 324 } 325 326 Object [] localSubset = new Object [actualLength]; 328 System.arraycopy(l2subset, 0, localSubset, 0, actualLength); 329 330 if (tcDest != null && actualLength > 0) { 331 tcDest.objectArrayChanged(destPos, l2subset, actualLength); 332 } 333 334 System.arraycopy(localSubset, 0, dest, destPos, actualLength); 336 337 if (actualLength != length) { throw new ArrayStoreException (); } 338 339 } 340 } else { 341 System.arraycopy(src, srcPos, dest, destPos, length); 343 } 344 } 345 346 private static int getCodeForType(Class type) { 347 Integer code = (Integer ) primClasses.get(type); 348 if (code == null) { throw new RuntimeException ("No code for type " + type); } 349 return code.intValue(); 350 } 351 352 private static void booleanArrayCopy(boolean[] src, int srcPos, boolean[] dest, int destPos, int length, 353 TCObject tcDest) { 354 if ((srcPos < 0) || (destPos < 0) || (length < 0) || (srcPos + length > src.length) 355 || (destPos + length > dest.length)) throw new ArrayIndexOutOfBoundsException (); 356 357 boolean[] l2subset = new boolean[length]; 358 System.arraycopy(src, srcPos, l2subset, 0, length); 359 tcDest.primitiveArrayChanged(destPos, l2subset, length); 360 361 System.arraycopy(l2subset, 0, dest, destPos, length); 363 } 364 365 private static void byteArrayCopy(byte[] src, int srcPos, byte[] dest, int destPos, int length, TCObject tcDest) { 366 if ((srcPos < 0) || (destPos < 0) || (length < 0) || (srcPos + length > src.length) 367 || (destPos + length > dest.length)) throw new ArrayIndexOutOfBoundsException (); 368 369 byte[] l2subset = new byte[length]; 370 System.arraycopy(src, srcPos, l2subset, 0, length); 371 tcDest.primitiveArrayChanged(destPos, l2subset, length); 372 373 System.arraycopy(l2subset, 0, dest, destPos, length); 375 } 376 377 public static void charArrayCopy(char[] src, int srcPos, char[] dest, int destPos, int length, TCObject tcDest) { 378 if ((srcPos < 0) || (destPos < 0) || (length < 0) || (srcPos + length > src.length) 379 || (destPos + length > dest.length)) throw new ArrayIndexOutOfBoundsException (); 380 381 char[] l2subset = new char[length]; 382 System.arraycopy(src, srcPos, l2subset, 0, length); 383 tcDest.primitiveArrayChanged(destPos, l2subset, length); 384 385 System.arraycopy(l2subset, 0, dest, destPos, length); 387 } 388 389 private static void doubleArrayCopy(double[] src, int srcPos, double[] dest, int destPos, int length, TCObject tcDest) { 390 if ((srcPos < 0) || (destPos < 0) || (length < 0) || (srcPos + length > src.length) 391 || (destPos + length > dest.length)) throw new ArrayIndexOutOfBoundsException (); 392 393 double[] l2subset = new double[length]; 394 System.arraycopy(src, srcPos, l2subset, 0, length); 395 tcDest.primitiveArrayChanged(destPos, l2subset, length); 396 397 System.arraycopy(l2subset, 0, dest, destPos, length); 399 } 400 401 private static void floatArrayCopy(float[] src, int srcPos, float[] dest, int destPos, int length, TCObject tcDest) { 402 if ((srcPos < 0) || (destPos < 0) || (length < 0) || (srcPos + length > src.length) 403 || (destPos + length > dest.length)) throw new ArrayIndexOutOfBoundsException (); 404 405 float[] l2subset = new float[length]; 406 System.arraycopy(src, srcPos, l2subset, 0, length); 407 tcDest.primitiveArrayChanged(destPos, l2subset, length); 408 409 System.arraycopy(l2subset, 0, dest, destPos, length); 411 } 412 413 private static void intArrayCopy(int[] src, int srcPos, int[] dest, int destPos, int length, TCObject tcDest) { 414 if ((srcPos < 0) || (destPos < 0) || (length < 0) || (srcPos + length > src.length) 415 || (destPos + length > dest.length)) throw new ArrayIndexOutOfBoundsException (); 416 417 int[] l2subset = new int[length]; 418 System.arraycopy(src, srcPos, l2subset, 0, length); 419 tcDest.primitiveArrayChanged(destPos, l2subset, length); 420 421 System.arraycopy(l2subset, 0, dest, destPos, length); 423 } 424 425 private static void longArrayCopy(long[] src, int srcPos, long[] dest, int destPos, int length, TCObject tcDest) { 426 if ((srcPos < 0) || (destPos < 0) || (length < 0) || (srcPos + length > src.length) 427 || (destPos + length > dest.length)) throw new ArrayIndexOutOfBoundsException (); 428 429 long[] l2subset = new long[length]; 430 System.arraycopy(src, srcPos, l2subset, 0, length); 431 tcDest.primitiveArrayChanged(destPos, l2subset, length); 432 433 System.arraycopy(l2subset, 0, dest, destPos, length); 435 } 436 437 private static void shortArrayCopy(short[] src, int srcPos, short[] dest, int destPos, int length, TCObject tcDest) { 438 if ((srcPos < 0) || (destPos < 0) || (length < 0) || (srcPos + length > src.length) 439 || (destPos + length > dest.length)) throw new ArrayIndexOutOfBoundsException (); 440 441 short[] l2subset = new short[length]; 442 System.arraycopy(src, srcPos, l2subset, 0, length); 443 tcDest.primitiveArrayChanged(destPos, l2subset, length); 444 445 System.arraycopy(l2subset, 0, dest, destPos, length); 447 } 448 449 private static final int BOOLEAN = 1; 450 private static final int BYTE = 2; 451 private static final int CHAR = 3; 452 private static final int DOUBLE = 4; 453 private static final int FLOAT = 5; 454 private static final int INT = 6; 455 private static final int LONG = 7; 456 private static final int SHORT = 8; 457 458 static { 459 primClasses.put(Boolean.TYPE, new Integer (BOOLEAN)); 460 primClasses.put(Byte.TYPE, new Integer (BYTE)); 461 primClasses.put(Character.TYPE, new Integer (CHAR)); 462 primClasses.put(Double.TYPE, new Integer (DOUBLE)); 463 primClasses.put(Float.TYPE, new Integer (FLOAT)); 464 primClasses.put(Integer.TYPE, new Integer (INT)); 465 primClasses.put(Long.TYPE, new Integer (LONG)); 466 primClasses.put(Short.TYPE, new Integer (SHORT)); 467 } 468 469 } 470 | Popular Tags |