/* * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.vm.object; import static com.sun.max.vm.MaxineVM.*; import java.lang.reflect.*; import com.oracle.max.cri.intrinsics.*; import com.sun.max.annotate.*; import com.sun.max.unsafe.*; import com.sun.max.vm.actor.holder.*; import com.sun.max.vm.layout.*; import com.sun.max.vm.reference.*; import com.sun.max.vm.runtime.*; /** * This class implements a facade for the {@link Layout Layout} class. The * Layout class requires the use of {@link Reference Reference} objects, as opposed * to regular Java objects, and this class implements a layer around the Layout * API. */ public final class ArrayAccess { private ArrayAccess() { } /** * Reads the length of the specified array. * * @param array the array object * @return the length of the array */ @INLINE public static int readArrayLength(Object array) { if (isHosted()) { if (array.getClass().isArray()) { return Array.getLength(array); } if (array instanceof Hybrid) { final Hybrid hybrid = (Hybrid) array; return hybrid.length(); } throw FatalError.unexpected("Cannot get array length of " + array.getClass().getName() + " instance"); } return Layout.readArrayLength(Reference.fromJava(array)); } /** * An inlined method to check an array index against the bounds of the array. * * @param array the array object * @param index the index into the array */ @INLINE public static void checkIndex(Object array, int index) { // note that we must read the array length first (implicit null check has precedence over bounds check) if (UnsignedMath.aboveOrEqual(index, readArrayLength(array))) { throw Throw.arrayIndexOutOfBoundsException(array, index); } } /** * Checks that the specified object reference can be assigned to the given object array. * This implements the same check as the {@code aastore} JVM bytecode. * * @param array the array object * @param value the object reference to write into the specified array */ @INLINE public static void checkSetObject(Object array, Object value) { if (isHosted()) { final Class arrayClass = array.getClass(); final Class componentType = arrayClass.getComponentType(); if (value != null) { if (!componentType.isInstance(value)) { throw Throw.arrayStoreException(array, value); } } else { if (Word.class.isAssignableFrom(componentType)) { throw Throw.arrayStoreException(array, value); } } } else { if (value != null) { final ClassActor arrayClassActor = ObjectAccess.readClassActor(array); if (!arrayClassActor.componentClassActor().isNonNullInstance(value)) { throw Throw.arrayStoreException(array, value); } } } } public static Pointer elementPointer(byte[] array, int index) { return Reference.fromJava(array).toOrigin().plus(Layout.byteArrayLayout().getElementOffsetFromOrigin(index)); } @INLINE public static Pointer elementPointer(int[] array, int index) { return Reference.fromJava(array).toOrigin().plus(Layout.byteArrayLayout().getElementOffsetFromOrigin(index)); } /** * Gets a byte from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static byte getByte(Object array, int index) { if (isHosted()) { if (array instanceof boolean[]) { final boolean[] booleanArray = (boolean[]) array; return booleanArray[index] ? (byte) 1 : (byte) 0; } assert array instanceof byte[]; final byte[] byteArray = (byte[]) array; return byteArray[index]; } return Layout.getByte(Reference.fromJava(array), index); } /** * Sets a byte in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setByte(Object array, int index, byte value) { if (isHosted()) { if (array instanceof boolean[]) { final boolean[] booleanArray = (boolean[]) array; booleanArray[index] = value != 0; } else { final byte[] byteArray = (byte[]) array; byteArray[index] = value; } } else { Layout.setByte(Reference.fromJava(array), index, value); } } /** * Gets a boolean from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static boolean getBoolean(Object array, int index) { if (isHosted()) { final boolean[] booleanArray = (boolean[]) array; return booleanArray[index]; } return Layout.getBoolean(Reference.fromJava(array), index); } /** * Sets a boolean in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setBoolean(Object array, int index, boolean value) { if (isHosted()) { final boolean[] booleanArray = (boolean[]) array; booleanArray[index] = value; return; } Layout.setBoolean(Reference.fromJava(array), index, value); } /** * Gets a short from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static short getShort(Object array, int index) { if (isHosted()) { final short[] shortArray = (short[]) array; return shortArray[index]; } return Layout.getShort(Reference.fromJava(array), index); } /** * Sets a short in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setShort(Object array, int index, short value) { if (isHosted()) { final short[] shortArray = (short[]) array; shortArray[index] = value; return; } Layout.setShort(Reference.fromJava(array), index, value); } /** * Gets a char from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static char getChar(Object array, int index) { if (isHosted()) { final char[] charArray = (char[]) array; return charArray[index]; } return Layout.getChar(Reference.fromJava(array), index); } /** * Sets a char in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setChar(Object array, int index, char value) { if (isHosted()) { final char[] charArray = (char[]) array; charArray[index] = value; return; } Layout.setChar(Reference.fromJava(array), index, value); } /** * Gets an int from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static int getInt(Object array, int index) { if (isHosted()) { final int[] intArray = (int[]) array; return intArray[index]; } return Layout.getInt(Reference.fromJava(array), index); } /** * Sets an int in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setInt(Object array, int index, int value) { if (isHosted()) { final int[] intArray = (int[]) array; intArray[index] = value; return; } Layout.setInt(Reference.fromJava(array), index, value); } /** * Gets a float from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static float getFloat(Object array, int index) { if (isHosted()) { final float[] floatArray = (float[]) array; return floatArray[index]; } return Layout.getFloat(Reference.fromJava(array), index); } /** * Sets a float in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setFloat(Object array, int index, float value) { if (isHosted()) { final float[] floatArray = (float[]) array; floatArray[index] = value; return; } Layout.setFloat(Reference.fromJava(array), index, value); } /** * Gets a long from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static long getLong(Object array, int index) { if (isHosted()) { final long[] longArray = (long[]) array; return longArray[index]; } return Layout.getLong(Reference.fromJava(array), index); } /** * Sets a long in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setLong(Object array, int index, long value) { if (isHosted()) { final long[] longArray = (long[]) array; longArray[index] = value; return; } Layout.setLong(Reference.fromJava(array), index, value); } /** * Gets a double from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static double getDouble(Object array, int index) { if (isHosted()) { final double[] doubleArray = (double[]) array; return doubleArray[index]; } return Layout.getDouble(Reference.fromJava(array), index); } /** * Sets a double in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setDouble(Object array, int index, double value) { if (isHosted()) { final double[] doubleArray = (double[]) array; doubleArray[index] = value; return; } Layout.setDouble(Reference.fromJava(array), index, value); } /** * Gets a word from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static Word getWord(Object array, int index) { if (isHosted()) { final Word[] wordArray = (Word[]) array; return WordArray.get(wordArray, index); } return Layout.getWord(Reference.fromJava(array), index); } /** * Sets a word in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setWord(Object array, int index, Word value) { if (isHosted()) { final Word[] wordArray = (Word[]) array; WordArray.set(wordArray, index, value); return; } Layout.setWord(Reference.fromJava(array), index, value); } /** * Gets a reference from the specified array at the specified index. * * @param array the array object * @param index the index into the array * @return the value at the specified index in the specified array */ @INLINE public static Object getObject(Object array, int index) { if (isHosted()) { final Object[] objectArray = (Object[]) array; return objectArray[index]; } return Layout.getReference(Reference.fromJava(array), index).toJava(); } /** * Sets a reference in the specified array at the specified index. * * @param array the array object * @param index the index into the array * @param value the value to write into the array at the specified index */ @INLINE public static void setObject(Object array, int index, Object value) { if (isHosted()) { final Object[] objectArray = (Object[]) array; objectArray[index] = value; return; } Layout.setReference(Reference.fromJava(array), index, Reference.fromJava(value)); } }