diff --git a/JavaInJava/src/com/sun/max/annotate/FOLD.java b/JavaInJava/src/com/sun/max/annotate/FOLD.java new file mode 100644 index 0000000..820dab8 --- /dev/null +++ b/JavaInJava/src/com/sun/max/annotate/FOLD.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.annotate; +import java.lang.annotation.*; + +/** + * Every thus annotated method must must have no arguments (apart from a receiver for a non-static method). + * It must also be purely functional (without side-effects) + * and idempotent (not influenced by any changing state). + * + * If the method is static, it is to be meta-evaluated unconditionally by the CPS compiler. + * If the method is non-static, it will be meta-evaluated whenever its receiver is known at compile time. + * + * @author Bernd Mathiske + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface FOLD { +} diff --git a/JavaInJava/src/com/sun/max/annotate/UNSAFE.java b/JavaInJava/src/com/sun/max/annotate/UNSAFE.java new file mode 100644 index 0000000..239a322 --- /dev/null +++ b/JavaInJava/src/com/sun/max/annotate/UNSAFE.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.annotate; + +import java.lang.annotation.*; + +/** + * Methods with this annotation must be compiled with the bootstrap compiler, not the JIT. + * Neither can they be interpreted. + *

+ * This is the case when a method uses values of type {@link Word} or + * any constant folding or dead code elimination must take place + * before the code makes sense in the target VM. + *

+ * Most of these methods are recognized automatically. + * Only those not captured during {@linkplain Intrinsics#run() intrinsification} + * need to be annotated. + *

+ * Some other annotations imply UNSAFE: + *

+ *

+ * However, some must be pointed out manually with this annotation. + * + * @see ClassfileReader + * + * @author Bernd Mathiske + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +public @interface UNSAFE { +} diff --git a/JavaInJava/src/com/sun/max/lang/DataModel.java b/JavaInJava/src/com/sun/max/lang/DataModel.java new file mode 100644 index 0000000..cdc0052 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/DataModel.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import java.io.*; + +import com.sun.max.program.*; +import com.sun.max.unsafe.*; +import com.sun.max.vm.compiler.builtin.*; +import com.sun.max.vm.value.*; + +public class DataModel { + + public final WordWidth wordWidth; + public final Endianness endianness; + public final int cacheAlignment; + + public DataModel(WordWidth wordWidth, Endianness endianness, int cacheAlignment) { + this.wordWidth = wordWidth; + this.endianness = endianness; + this.cacheAlignment = cacheAlignment; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof DataModel)) { + return false; + } + final DataModel dataModel = (DataModel) other; + return wordWidth.equals(dataModel.wordWidth) && endianness.equals(dataModel.endianness) && cacheAlignment == dataModel.cacheAlignment; + } + + public byte[] toBytes(byte value) { + return endianness.toBytes(value); + } + + public byte[] toBytes(boolean value) { + final byte[] result = new byte[1]; + result[0] = value ? (byte) 1 : (byte) 0; + return result; + } + + public byte[] toBytes(short value) { + return endianness.toBytes(value); + } + + public byte[] toBytes(char value) { + final short shortValue = UnsafeCast.asShort(value); + return endianness.toBytes(shortValue); + } + + public byte[] toBytes(int value) { + return endianness.toBytes(value); + } + + public byte[] toBytes(float value) { + final int intValue = SpecialBuiltin.floatToInt(value); + return endianness.toBytes(intValue); + } + + public byte[] toBytes(long value) { + return endianness.toBytes(value); + } + + public byte[] toBytes(double value) { + final long longValue = SpecialBuiltin.doubleToLong(value); + return endianness.toBytes(longValue); + } + + public byte[] toBytes(Word value) { + switch (wordWidth) { + case BITS_64: + return toBytes(value.asOffset().toLong()); + case BITS_32: + return toBytes((int) value.asOffset().toLong()); + case BITS_16: + return toBytes((short) value.asOffset().toLong()); + case BITS_8: + return toBytes((byte) value.asOffset().toLong()); + } + ProgramError.unknownCase(); + return null; + } + + public void write(OutputStream stream, Value value) throws IOException { + stream.write(value.toBytes(this)); + } + + @Override + public String toString() { + return wordWidth + "-bit, " + endianness + " endian, " + cacheAlignment + "-byte aligned cache"; + } +} diff --git a/JavaInJava/src/com/sun/max/lang/Objects.java b/JavaInJava/src/com/sun/max/lang/Objects.java new file mode 100644 index 0000000..3337422 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Objects.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import static com.sun.max.unsafe.WithoutAccessCheck.*; + +import java.lang.reflect.*; + +import com.sun.max.*; +import com.sun.max.program.*; + +/** + * Basic generic utilities for objects. + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public final class Objects { + + private Objects() { + } + + /** + * Compares two given objects for equality using {@link Object#equals(Object)}. + * + * @return true if both {@code o1} and {@code o2} are {@code null} || {@code o1.equals(o2)} + */ + public static boolean equal(Object o1, Object o2) { + return o1 == null ? o2 == null : o1.equals(o2); + } + + /** + * Copies the values of the instance fields in one object to another object. + * + * @param fromObject the object from which the field values are to be copied + * @param toObject the object to which the field values are to be copied + */ + public static void copy(Object fromObject, Object toObject) { + assert fromObject.getClass() == toObject.getClass(); + Class c = fromObject.getClass(); + while (c != null) { + for (Field field : c.getDeclaredFields()) { + if ((field.getModifiers() & Modifier.STATIC) == 0) { + field.setAccessible(true); + try { + final Object value = field.get(fromObject); + field.set(toObject, value); + } catch (IllegalArgumentException illegalArgumentException) { + // This should never occur + throw ProgramError.unexpected(illegalArgumentException); + } catch (IllegalAccessException illegalAccessException) { + // This should never occur + throw ProgramError.unexpected(illegalAccessException); + } + } + } + c = c.getSuperclass(); + } + } + + /** + * Creates a new instance of a given class without calling any constructors. This call also ensures that {@code javaClass} + * has been initialized. + * + * @param javaClass the class to construct an instance of + * @return an uninitialized of {@code javaClass} + * @throws InstantiationException if the instantiation fails for any of the reasons described + * {@linkplain InstantiationException here} + */ + public static Object allocateInstance(Class javaClass) throws InstantiationException { + unsafe.ensureClassInitialized(javaClass); + return unsafe.allocateInstance(javaClass); + } + + public static T allocateObject(Class javaClass) throws InstantiationException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { + final Constructor constructor = javaClass.getDeclaredConstructor(); + constructor.setAccessible(true); + final Object object = constructor.newInstance(); + return Utils.cast(javaClass, object); + } +} diff --git a/JavaInJava/src/com/sun/max/lang/Unsigned.java b/JavaInJava/src/com/sun/max/lang/Unsigned.java new file mode 100644 index 0000000..3fa0bec --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Unsigned.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import com.sun.max.annotate.*; +import com.sun.max.unsafe.*; + +/** + * A collection of static methods for doing unsigned arithmetic on Java primitive types + * where the semantics of the arithmetics operations differ from the signed version. + * In addition to providing unsigned arithmetic semantics for the programmer, + * these methods also expose different optimization possibilities to the compiler as + * well as allowing for them to be implemented as compiler builtins. + * + * @author Doug Simon + */ +public class Unsigned { + + /** + * Performs unsigned integer division. + */ + @INLINE + @UNSAFE + public static int idiv(int dividend, int divisor) { + return Address.fromUnsignedInt(dividend).dividedBy(divisor).toInt(); + } + + /** + * Performs unsigned long division. + */ + @INLINE + @UNSAFE + public static long ldiv(long dividend, long divisor) { + return Address.fromLong(dividend).dividedBy(Address.fromLong(divisor)).toLong(); + } + + /** + * Performs unsigned integer modulus. + */ + @INLINE + @UNSAFE + public static int irem(int dividend, int divisor) { + return Address.fromUnsignedInt(dividend).remainder(divisor); + } + + /** + * Performs unsigned long modulus. + */ + @INLINE + @UNSAFE + public static long lrem(long dividend, long divisor) { + return Address.fromLong(dividend).remainder(Address.fromLong(divisor)).toLong(); + } + +} diff --git a/JavaInJava/src/com/sun/max/unsafe/Accessor.java b/JavaInJava/src/com/sun/max/unsafe/Accessor.java new file mode 100644 index 0000000..a0e21d9 --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/Accessor.java @@ -0,0 +1,534 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import com.sun.max.vm.reference.*; + +/** + * ATTENTION: DO NOT USE THIS INTERFACE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING!!! + * + * Common interface for pointers and for object references. + * + * The object layout implementation is written ONCE against this type + * (instead of twice, once against Pointer and once against Reference). + * + * @author Bernd Mathiske + * @author Paul Caprioli + */ +public interface Accessor { + + /** + * Tests whether this is zero. + * @return true if all bits are zero. + */ + boolean isZero(); + + /** + * Reads a byte at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the byte value + */ + byte readByte(Offset offset); + + /** + * Reads a byte at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the byte value + */ + byte readByte(int offset); + + /** + * Gets a byte at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in bytes + * @return the byte value + */ + byte getByte(int displacement, int index); + + /** + * Writes a byte at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeByte(Offset offset, byte value); + + /** + * Writes a byte at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeByte(int offset, byte value); + + /** + * Writes a byte at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in bytes + * @param value the data to be written + */ + void setByte(int displacement, int index, byte value); + + /** + * Reads a boolean at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the boolean value + */ + boolean readBoolean(Offset offset); + + /** + * Reads a boolean at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the boolean value + */ + boolean readBoolean(int offset); + + /** + * Gets a boolean at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in bytes + * @return the boolean value + */ + boolean getBoolean(int displacement, int index); + + /** + * Writes a boolean at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeBoolean(Offset offset, boolean value); + + /** + * Writes a boolean at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeBoolean(int offset, boolean value); + + /** + * Writes a boolean at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in bytes + * @param value the data to be written + */ + void setBoolean(int displacement, int index, boolean value); + + /** + * Reads a short at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the short value + */ + short readShort(Offset offset); + + /** + * Reads a short at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the short value + */ + short readShort(int offset); + + /** + * Gets a short at the scaled index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in shorts + * @return the short value + */ + short getShort(int displacement, int index); + + /** + * Writes a short at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeShort(Offset offset, short value); + + /** + * Writes a short at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeShort(int offset, short value); + + /** + * Writes a short at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in shorts + * @param value the data to be written + */ + void setShort(int displacement, int index, short value); + + /** + * Reads a character at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the character value + */ + char readChar(Offset offset); + + /** + * Reads a character at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the character value + */ + char readChar(int offset); + + /** + * Gets a character at the scaled index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in chars + * @return the character value + */ + char getChar(int displacement, int index); + + /** + * Writes a character at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeChar(Offset offset, char value); + + /** + * Writes a character at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeChar(int offset, char value); + + /** + * Writes a character at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in characters + * @param value the data to be written + */ + void setChar(int displacement, int index, char value); + + /** + * Reads an integer at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the integer value + */ + int readInt(Offset offset); + + /** + * Reads an integer at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the integer value + */ + int readInt(int offset); + + /** + * Gets an integer at the scaled index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in ints + * @return the integer value + */ + int getInt(int displacement, int index); + + /** + * Writes an integer at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeInt(Offset offset, int value); + /** + * Writes an integer at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeInt(int offset, int value); + + /** + * Writes an integer at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in ints + * @param value the data to be written + */ + void setInt(int displacement, int index, int value); + + /** + * Reads a float at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the float value + */ + float readFloat(Offset offset); + + /** + * Reads a float at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the float value + */ + float readFloat(int offset); + + /** + * Gets a float at the scaled index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in floats + * @return the float value + */ + float getFloat(int displacement, int index); + + /** + * Writes a float at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeFloat(Offset offset, float value); + + /** + * Writes a float at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeFloat(int offset, float value); + + /** + * Writes a float at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in floats + * @param value the data to be written + */ + void setFloat(int displacement, int index, float value); + + /** + * Reads a long at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the long value + */ + long readLong(Offset offset); + + /** + * Reads a long at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the long value + */ + long readLong(int offset); + + /** + * Gets a long at the scaled index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in longs + * @return the long value + */ + long getLong(int displacement, int index); + + /** + * Writes a long at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeLong(Offset offset, long value); + + /** + * Writes a long at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeLong(int offset, long value); + + /** + * Writes a long at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in longs + * @param value the data to be written + */ + void setLong(int displacement, int index, long value); + + /** + * Reads a double at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the double value + */ + double readDouble(Offset offset); + + /** + * Reads a double at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the double value + */ + double readDouble(int offset); + + /** + * Gets a double at the scaled index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in doubles + * @return the double value + */ + double getDouble(int displacement, int index); + + /** + * Writes a double at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeDouble(Offset offset, double value); + + /** + * Writes a double at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeDouble(int offset, double value); + + /** + * Writes a double at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in doubles + * @param value the data to be written + */ + void setDouble(int displacement, int index, double value); + + /** + * Reads a Word at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the Word value + */ + Word readWord(Offset offset); + + /** + * Reads a Word at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the Word value + */ + Word readWord(int offset); + + /** + * Gets a Word at the scaled index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in Words + * @return the Word value + */ + Word getWord(int displacement, int index); + + /** + * Writes a Word at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeWord(Offset offset, Word value); + + /** + * Writes a Word at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeWord(int offset, Word value); + + /** + * Writes a Word at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in Words + * @param value the data to be written + */ + void setWord(int displacement, int index, Word value); + + /** + * Reads a Reference at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the Reference value + */ + Reference readReference(Offset offset); + + /** + * Reads a Reference at an offset from this location. + * @param offset the signed offset in bytes from this + * @return the Reference value + */ + Reference readReference(int offset); + + /** + * Gets a Reference at the scaled index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in References + * @return the Reference value + */ + Reference getReference(int displacement, int index); + + /** + * Writes a Reference at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeReference(Offset offset, Reference value); + + /** + * Writes a Reference at an offset from this location. + * @param offset the signed offset in bytes from this + * @param value the data to be written + */ + void writeReference(int offset, Reference value); + + /** + * Writes a Reference at index plus displacement from this location. + * @param displacement signed displacement in bytes + * @param index signed index measured in References + * @param value the data to be written + */ + void setReference(int displacement, int index, Reference value); + + /** + * Atomic compare and swap. + * + * Compares an expected value with the actual value in a location denoted by this accessor and a given offset. + * Iff they are same, {@code newValue} is placed into the location and the {@code expectedValue} is returned. + * Otherwise, the actual value is returned. + * All of the above is performed in one atomic hardware transaction. + * + * @param offset offset from accessor origin + * @param expectedValue if this value is currently in the accessor location, perform the swap + * @param newValue the new value to put into the accessor location + * @return either {@code expectedValue} or the actual value + */ + int compareAndSwapInt(Offset offset, int expectedValue, int newValue); + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + int compareAndSwapInt(int offset, int expectedValue, int newValue); + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + Word compareAndSwapWord(Offset offset, Word expectedValue, Word newValue); + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + Word compareAndSwapWord(int offset, Word expectedValue, Word newValue); + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + Reference compareAndSwapReference(Offset offset, Reference expectedValue, Reference newValue); + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + Reference compareAndSwapReference(int offset, Reference expectedValue, Reference newValue); + + /** + * Copies elements from this array into a given array. + * + * @param displacement signed displacement in bytes + * @param srcIndex the index in this array from which to copy + * @param dst the array into which the elements will be read + * @param dstIndex the index in {@code dst} to which to copy + * @param length the number of elements to copy + */ + void copyElements(int displacement, int srcIndex, Object dst, int dstIndex, int length); +} + diff --git a/JavaInJava/src/com/sun/max/unsafe/Address.java b/JavaInJava/src/com/sun/max/unsafe/Address.java new file mode 100644 index 0000000..5be276f --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/Address.java @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import java.math.*; + +import com.sun.max.annotate.*; +import com.sun.max.lang.*; +import com.sun.max.program.*; + +/** + * A machine word interpreted as a linear address. + * An Address is unsigned and arithmetic is supported. + * + * @author Bernd Mathiske + * @author Paul Caprioli + */ +public abstract class Address extends Word { + + protected Address() { + } + + @INLINE + public static Address zero() { + return fromInt(0); + } + + @INLINE + public static Address max() { + return fromLong(-1L); + } + + /** + * Creates an Address value from a given int value. Note that unlike {@link #fromInt(int)}, + * the given int value is not sign extended. Also note that on 32-bit platforms, this operation + * is effectively a no-op. + * + * @param value the value to be converted to an Address + */ + @INLINE + public static Address fromUnsignedInt(int value) { + if (Word.width() == 64) { + final long longValue = value; + final long n = longValue & 0xffffffffL; + return UnsafeCast.asAddress(n); + } + return UnsafeCast.asAddress(value); + } + + /** + * Creates an Address value from a given int value. Note that unlike {@link #fromUnsignedInt(int)}, + * the given int value is sign extended first. Also note that on 32-bit platforms, this operation + * is effectively a no-op. + * + * @param value the value to be converted to an Address + */ + @INLINE + public static Address fromInt(int value) { + if (Word.width() == 64) { + final long n = value; + return UnsafeCast.asAddress(n); + } + return UnsafeCast.asAddress(value); + } + + @INLINE + public static Address fromLong(long value) { + if (Word.width() == 64) { + return UnsafeCast.asAddress(value); + } + final int n = (int) value; + return UnsafeCast.asAddress(n); + } + + @Override + public String toString() { + return "@" + toHexString(); + } + + public String toUnsignedString(int radix) { + if (radix == 16) { + if (Word.width() == 64) { + return Long.toHexString(toLong()); + } + assert Word.width() == 32; + return Integer.toHexString(toInt()); + } + if (radix == 8) { + if (Word.width() == 64) { + return Long.toOctalString(toLong()); + } + assert Word.width() == 32; + return Integer.toOctalString(toInt()); + } + if (radix == 2) { + if (Word.width() == 64) { + return Long.toBinaryString(toLong()); + } + assert Word.width() == 32; + return Integer.toBinaryString(toInt()); + } + assert radix == 10; + + final long n = toLong(); + if (Word.width() == 32) { + if (n <= Integer.MAX_VALUE && n >= 0) { + return Integer.toString(toInt()); + } + return Long.toString(n & 0xffffffffL); + } + + final long low = n & 0xffffffffL; + final long high = n >>> 32; + return BigInteger.valueOf(high).shiftLeft(32).or(BigInteger.valueOf(low)).toString(); + } + + public static Address parse(String s, int radix) { + Address result = Address.zero(); + for (int i = 0; i < s.length(); i++) { + result = result.times(radix); + result = result.plus(Integer.parseInt(String.valueOf(s.charAt(i)), radix)); + } + return result; + } + + @INLINE + public final int toInt() { + if (Word.width() == 64) { + final long n = UnsafeCast.asLong(this); + return (int) n; + } + return UnsafeCast.asInt(this); + } + + @INLINE + public final long toLong() { + if (Word.width() == 64) { + return UnsafeCast.asLong(this); + } + return 0xffffffffL & UnsafeCast.asInt(this); + } + + @INLINE + public final boolean equals(int other) { + return fromInt(other) == this; + } + + @INLINE(override = true) + public Address plus(Address addend) { + return asOffset().plus(addend.asOffset()).asAddress(); + } + + @INLINE(override = true) + public Address plus(Offset offset) { + return asOffset().plus(offset).asAddress(); + } + + @INLINE(override = true) + public Address plus(int addend) { + return asOffset().plus(addend).asAddress(); + } + + @INLINE(override = true) + public Address plus(long addend) { + return asOffset().plus(addend).asAddress(); + } + + @INLINE(override = true) + public Address minus(Address subtrahend) { + return asOffset().minus(subtrahend.asOffset()).asAddress(); + } + + @INLINE(override = true) + public Address minus(Offset offset) { + return asOffset().minus(offset).asAddress(); + } + + @INLINE(override = true) + public Address minus(int subtrahend) { + return asOffset().minus(subtrahend).asAddress(); + } + + @INLINE(override = true) + public Address minus(long subtrahend) { + return asOffset().minus(subtrahend).asAddress(); + } + + @INLINE(override = true) + public Address times(Address factor) { + return asOffset().times(factor.asOffset()).asAddress(); + } + + @INLINE(override = true) + public Address times(int factor) { + return asOffset().times(factor).asAddress(); + } + + protected abstract Address dividedByAddress(Address divisor); + + @INLINE(override = true) + public Address dividedBy(Address divisor) { + return dividedByAddress(divisor); + } + + protected abstract Address dividedByInt(int divisor); + + @INLINE(override = true) + public Address dividedBy(int divisor) { + return dividedByInt(divisor); + } + + protected abstract Address remainderByAddress(Address divisor); + + @INLINE(override = true) + public Address remainder(Address divisor) { + return remainderByAddress(divisor); + } + + protected abstract int remainderByInt(int divisor); + + @INLINE(override = true) + public final int remainder(int divisor) { + return remainderByInt(divisor); + } + + @INLINE(override = true) + public final boolean isRoundedBy(Address nBytes) { + return remainder(nBytes).isZero(); + } + + @INLINE(override = true) + public final boolean isRoundedBy(int nBytes) { + return remainder(nBytes) == 0; + } + + @INLINE(override = true) + public Address roundedUpBy(Address nBytes) { + if (isRoundedBy(nBytes)) { + return this; + } + return plus(nBytes.minus(remainder(nBytes))); + } + + @INLINE(override = true) + public Address roundedUpBy(int nBytes) { + if (isRoundedBy(nBytes)) { + return this; + } + return plus(nBytes - remainder(nBytes)); + } + + @INLINE(override = true) + public Address roundedDownBy(int nBytes) { + return minus(remainder(nBytes)); + } + + @INLINE(override = true) + public Address wordAligned() { + final int n = Word.size(); + return plus(n - 1).and(Address.fromInt(n - 1).not()); + } + + @INLINE(override = true) + public Address aligned(int alignment) { + return plus(alignment - 1).and(Address.fromInt(alignment - 1).not()); + } + + @INLINE(override = true) + public boolean isWordAligned() { + final int n = Word.size(); + return and(n - 1).equals(Address.zero()); + } + + @INLINE(override = true) + public boolean isAligned(int alignment) { + return and(alignment - 1).equals(Address.zero()); + } + + @INLINE(override = true) + public final boolean isBitSet(int index) { + return (toLong() & (1L << index)) != 0; + } + + @INLINE(override = true) + public Address bitSet(int index) { + return fromLong(toLong() | (1L << index)); + } + + @INLINE(override = true) + public Address bitClear(int index) { + return fromLong(toLong() & ~(1L << index)); + } + + @INLINE(override = true) + public Address and(Address operand) { + if (Word.width() == 64) { + return fromLong(toLong() & operand.toLong()); + } + return fromInt(toInt() & operand.toInt()); + } + + @INLINE(override = true) + public Address and(int operand) { + return and(fromInt(operand)); + } + + @INLINE(override = true) + public Address and(long operand) { + return and(fromLong(operand)); + } + + @INLINE(override = true) + public Address or(Address operand) { + if (Word.width() == 64) { + return fromLong(toLong() | operand.toLong()); + } + return fromInt(toInt() | operand.toInt()); + } + + @INLINE(override = true) + public Address or(int operand) { + return or(fromInt(operand)); + } + + @INLINE(override = true) + public Address or(long operand) { + return or(fromLong(operand)); + } + + @INLINE(override = true) + public Address not() { + if (Word.width() == 64) { + return fromLong(~toLong()); + } + return fromInt(~toInt()); + } + + @INLINE(override = true) + public Address shiftedLeft(int nBits) { + if (Word.width() == 64) { + return fromLong(toLong() << nBits); + } + return fromInt(toInt() << nBits); + } + + @INLINE(override = true) + public Address unsignedShiftedRight(int nBits) { + if (Word.width() == 64) { + return fromLong(toLong() >>> nBits); + } + return fromInt(toInt() >>> nBits); + } + + @INLINE(override = true) + public final int numberOfEffectiveBits() { + if (Word.width() == 64) { + return 64 - Long.numberOfLeadingZeros(toLong()); + } + return 32 - Integer.numberOfLeadingZeros(toInt()); + } + + public final WordWidth effectiveWidth() { + final int bit = numberOfEffectiveBits(); + for (WordWidth width : WordWidth.VALUES) { + if (bit < width.numberOfBits) { + return width; + } + } + throw ProgramError.unexpected(); + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/DataAccess.java b/JavaInJava/src/com/sun/max/unsafe/DataAccess.java new file mode 100644 index 0000000..b95a19d --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/DataAccess.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import java.nio.*; + +/** + * Reading/writing bytes and other primitive data kinds from/to a source/destination that can be identified by an {@link Address}. + * For each kind, methods support direct addressing, offset addressing, and indexed addressing for arrays. + * + * @author Bernd Mathiske + * @author Michael Van De Vanter + */ +public interface DataAccess extends DataIO { + + void readFully(Address address, ByteBuffer buffer); + void readFully(Address address, byte[] bytes); + byte[] readFully(Address address, int length); + + byte readByte(Address address); + byte readByte(Address address, Offset offset); + byte readByte(Address address, int offset); + byte getByte(Address address, int displacement, int index); + + boolean readBoolean(Address address); + boolean readBoolean(Address address, Offset offset); + boolean readBoolean(Address address, int offset); + boolean getBoolean(Address address, int displacement, int index); + + short readShort(Address address); + short readShort(Address address, Offset offset); + short readShort(Address address, int offset); + short getShort(Address address, int displacement, int index); + + char readChar(Address address); + char readChar(Address address, Offset offset); + char readChar(Address address, int offset); + char getChar(Address address, int displacement, int index); + + int readInt(Address address); + int readInt(Address address, Offset offset); + int readInt(Address address, int offset); + int getInt(Address address, int displacement, int index); + + float readFloat(Address address); + float readFloat(Address address, Offset offset); + float readFloat(Address address, int offset); + float getFloat(Address address, int displacement, int index); + + long readLong(Address address); + long readLong(Address address, Offset offset); + long readLong(Address address, int offset); + long getLong(Address address, int displacement, int index); + + double readDouble(Address address); + double readDouble(Address address, Offset offset); + double readDouble(Address address, int offset); + double getDouble(Address address, int displacement, int index); + + Word readWord(Address address); + Word readWord(Address address, Offset offset); + Word readWord(Address address, int offset); + Word getWord(Address address, int displacement, int index); + + void writeBytes(Address address, byte[] bytes); + void writeBuffer(Address address, ByteBuffer buffer); + + void writeByte(Address address, byte value); + void writeByte(Address address, Offset offset, byte value); + void writeByte(Address address, int offset, byte value); + void setByte(Address address, int displacement, int index, byte value); + + void writeBoolean(Address address, boolean value); + void writeBoolean(Address address, Offset offset, boolean value); + void writeBoolean(Address address, int offset, boolean value); + void setBoolean(Address address, int displacement, int index, boolean value); + + void writeShort(Address address, short value); + void writeShort(Address address, Offset offset, short value); + void writeShort(Address address, int offset, short value); + void setShort(Address address, int displacement, int index, short value); + + void writeChar(Address address, char value); + void writeChar(Address address, Offset offset, char value); + void writeChar(Address address, int offset, char value); + void setChar(Address address, int displacement, int index, char value); + + void writeInt(Address address, int value); + void writeInt(Address address, Offset offset, int value); + void writeInt(Address address, int offset, int value); + void setInt(Address address, int displacement, int index, int value); + + void writeFloat(Address address, float value); + void writeFloat(Address address, Offset offset, float value); + void writeFloat(Address address, int offset, float value); + void setFloat(Address address, int displacement, int index, float value); + + void writeLong(Address address, long value); + void writeLong(Address address, Offset offset, long value); + void writeLong(Address address, int offset, long value); + void setLong(Address address, int displacement, int index, long value); + + void writeDouble(Address address, double value); + void writeDouble(Address address, Offset offset, double value); + void writeDouble(Address address, int offset, double value); + void setDouble(Address address, int displacement, int index, double value); + + void writeWord(Address address, Word value); + void writeWord(Address address, Offset offset, Word value); + void writeWord(Address address, int offset, Word value); + void setWord(Address address, int displacement, int index, Word value); + + void copyElements(Address address, int displacement, int srcIndex, Object dst, int dstIndex, int length); +} diff --git a/JavaInJava/src/com/sun/max/unsafe/DataIO.java b/JavaInJava/src/com/sun/max/unsafe/DataIO.java new file mode 100644 index 0000000..9ed813d --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/DataIO.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import java.nio.*; + +/** + * Buffered reading/writing of bytes from/to a source/destination that can be identified by an {@link Address}. + * + * @author Bernd Mathiske + * @author Michael Van De Vanter + */ +public interface DataIO { + + /** + * Reads bytes from an address into a given byte buffer. + * + * Precondition: + * {@code buffer != null && offset >= 0 && offset < buffer.capacity() && length >= 0 && offset + length <= buffer.capacity()} + * + * @param src the address from which reading should start + * @param dst the buffer into which the bytes are read + * @param dstOffset the offset in {@code dst} at which the bytes are read + * @param length the maximum number of bytes to be read + * @return the number of bytes read into {@code dst} + * + * @throws DataIOError if some IO error occurs + * @throws IndexOutOfBoundsException if {@code offset} is negative, {@code length} is negative, or + * {@code length > buffer.limit() - offset} + */ + int read(Address src, ByteBuffer dst, int dstOffset, int length) throws DataIOError, IndexOutOfBoundsException; + + /** + * Writes bytes from a given byte buffer to a given address. + * + * Precondition: + * {@code buffer != null && offset >= 0 && offset < buffer.capacity() && length >= 0 && offset + length <= buffer.capacity()} + * + * @param src the buffer from which the bytes are written + * @param srcOffset the offset in {@code src} from which the bytes are written + * @param length the maximum number of bytes to be written + * @param dst the address at which writing should start + * @return the number of bytes written to {@code dst} + * + * @throws DataIOError if some IO error occurs + * @throws IndexOutOfBoundsException if {@code srcOffset} is negative, {@code length} is negative, or + * {@code length > src.limit() - srcOffset} + */ + int write(ByteBuffer src, int srcOffset, int length, Address dst) throws DataIOError, IndexOutOfBoundsException; + + public static class Static { + + /** + * Fills a buffer by reading bytes from a source. + * + * @param dataIO the source of data to be read + * @param src the location in the source where reading should start + * @param dst the buffer to be filled with the data + */ + public static void readFully(DataIO dataIO, Address src, ByteBuffer dst) { + final int length = dst.limit(); + int n = 0; + assert dst.position() == 0; + while (n < length) { + final int count = dataIO.read(src.plus(n), dst, n, length - n); + if (count <= 0) { + throw new DataIOError(src, (length - n) + " of " + length + " bytes unread"); + } + n += count; + dst.position(0); + } + } + + /** + * Reads bytes from a source. + * + * @param dataIO the source of data to be read + * @param src the location in the source where reading should start + * @param length the total number of bytes to be read + * @return the bytes read from the source. + */ + public static byte[] readFully(DataIO dataIO, Address src, int length) { + final ByteBuffer buffer = ByteBuffer.wrap(new byte[length]); + readFully(dataIO, src, buffer); + return buffer.array(); + } + + /** + * Checks the preconditions related to the destination buffer for {@link DataIO#read(Address, ByteBuffer, int, int)}. + */ + public static void checkRead(ByteBuffer dst, int dstOffset, int length) { + if (dst == null) { + throw new NullPointerException(); + } else if (dstOffset < 0 || length < 0 || length > dst.limit() - dstOffset) { + throw new IndexOutOfBoundsException(); + } + } + + /** + * Checks the preconditions related to the source buffer for {@link DataIO#write(ByteBuffer, int, int, Address)}. + */ + public static void checkWrite(ByteBuffer src, int srcOffset, int length) { + if ((srcOffset < 0) || (srcOffset > src.limit()) || (length < 0) || + ((srcOffset + length) > src.limit()) || ((srcOffset + length) < 0)) { + throw new IndexOutOfBoundsException(); + } + } + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/DataIOError.java b/JavaInJava/src/com/sun/max/unsafe/DataIOError.java new file mode 100644 index 0000000..f5fd3d6 --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/DataIOError.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +/** + * Thrown when an error occurs accessing memory through a {@link DataIO} or {@link DataAccess}. + * + * @author Aritra Bandyopadhyay + */ +public class DataIOError extends Error { + private final Address faultAddress; + + public DataIOError(Address address, String message) { + super("data access error at ^" + address.toPaddedHexString('0') + " (" + message + " )"); + faultAddress = address; + } + + public DataIOError(Address address) { + super("data access error at ^" + address.toPaddedHexString('0')); + faultAddress = address; + } + + public Address getFaultAddress() { + return faultAddress; + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/Offset.java b/JavaInJava/src/com/sun/max/unsafe/Offset.java new file mode 100644 index 0000000..4ed7556 --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/Offset.java @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import com.sun.max.annotate.*; +import com.sun.max.lang.*; +import com.sun.max.program.*; + +/** + * Offsets from addresses or pointers. Unlike an 'Address', an 'Offset' can be negative. Both types have the identical + * number of bits used for representation. However, 'Offset' uses twos complement, whereas 'Address' is simply unsigned. + * + * @author Bernd Mathiske + */ +public abstract class Offset extends Word { + + protected Offset() { + } + + @INLINE + public static Offset zero() { + return fromInt(0); + } + + @INLINE + public static Offset fromUnsignedInt(int value) { + return Address.fromUnsignedInt(value).asOffset(); + } + + @INLINE + public static Offset fromInt(int value) { + if (Word.width() == 64) { + final long n = value; + return UnsafeCast.asOffset(n); + } + return UnsafeCast.asOffset(value); + } + + @INLINE + public static Offset fromLong(long value) { + if (Word.width() == 64) { + return UnsafeCast.asOffset(value); + } + final int n = (int) value; + return UnsafeCast.asOffset(n); + } + + @Override + public String toString() { + return "&" + toHexString(); + } + + @INLINE + public final int toInt() { + if (Word.width() == 64) { + final long n = UnsafeCast.asLong(this); + return (int) n; + } + return UnsafeCast.asInt(this); + } + + @INLINE + public final long toLong() { + if (Word.width() == 64) { + return UnsafeCast.asLong(this); + } + return UnsafeCast.asInt(this); + } + + public final int compareTo(Offset other) { + if (greaterThan(other)) { + return 1; + } + if (lessThan(other)) { + return -1; + } + return 0; + } + + @INLINE + public final boolean equals(int other) { + return fromInt(other) == this; + } + + @INLINE + public final boolean lessEqual(Offset other) { + if (Word.width() == 64) { + return toLong() <= other.toLong(); + } + return toInt() <= other.toInt(); + } + + @INLINE + public final boolean lessEqual(int other) { + return lessEqual(fromInt(other)); + } + + @INLINE + public final boolean lessThan(Offset other) { + if (Word.width() == 64) { + return toLong() < other.toLong(); + } + return toInt() < other.toInt(); + } + + @INLINE + public final boolean lessThan(int other) { + return lessThan(fromInt(other)); + } + + @INLINE + public final boolean greaterEqual(Offset other) { + if (Word.width() == 64) { + return toLong() >= other.toLong(); + } + return toInt() >= other.toInt(); + } + + @INLINE + public final boolean greaterEqual(int other) { + return greaterEqual(fromInt(other)); + } + + @INLINE + public final boolean greaterThan(Offset other) { + if (Word.width() == 64) { + return toLong() > other.toLong(); + } + return toInt() > other.toInt(); + } + + @INLINE + public final boolean greaterThan(int other) { + return greaterThan(fromInt(other)); + } + + @INLINE + public final Offset negate() { + if (Word.width() == 64) { + return fromLong(-toLong()); + } + return fromInt(-toInt()); + } + + @INLINE + public final boolean isNegative() { + if (Word.width() == 64) { + return toLong() < 0L; + } + return toInt() < 0; + } + + @INLINE + public final Offset plus(Offset addend) { + if (Word.width() == 64) { + return fromLong(toLong() + addend.toLong()); + } + return fromInt(toInt() + addend.toInt()); + } + + @INLINE + public final Offset plus(Size addend) { + return plus(addend.asOffset()); + } + + @INLINE + public final Offset plus(int addend) { + return plus(fromInt(addend)); + } + + @INLINE + public final Offset plus(long addend) { + return plus(fromLong(addend)); + } + + @INLINE + public final Offset minus(Offset subtrahend) { + if (Word.width() == 64) { + return fromLong(toLong() - subtrahend.toLong()); + } + return fromInt(toInt() - subtrahend.toInt()); + } + + @INLINE + public final Offset minus(Size subtrahend) { + return minus(subtrahend.asOffset()); + } + + @INLINE + public final Offset minus(int subtrahend) { + return minus(fromInt(subtrahend)); + } + + @INLINE + public final Offset minus(long subtrahend) { + return minus(fromLong(subtrahend)); + } + + @INLINE + public final Offset times(Offset factor) { + if (Word.width() == 64) { + return fromLong(toLong() * factor.toLong()); + } + return fromInt(toInt() * factor.toInt()); + } + + @INLINE + public final Offset times(Address factor) { + return times(factor.asOffset()); + } + + @INLINE + public final Offset times(int factor) { + return times(fromInt(factor)); + } + + @INLINE + public final Offset dividedBy(Offset divisor) throws ArithmeticException { + if (Word.width() == 64) { + return fromLong(toLong() / divisor.toLong()); + } + return fromInt(toInt() / divisor.toInt()); + } + + @INLINE + public final Offset dividedBy(int divisor) throws ArithmeticException { + return dividedBy(fromInt(divisor)); + } + + @INLINE + public final Offset remainder(Offset divisor) throws ArithmeticException { + if (Word.width() == 64) { + return fromLong(toLong() % divisor.toLong()); + } + return fromInt(toInt() % divisor.toInt()); + } + + @INLINE + public final int remainder(int divisor) throws ArithmeticException { + return remainder(fromInt(divisor)).toInt(); + } + + @INLINE + public final boolean isRoundedBy(int numberOfBytes) { + return remainder(numberOfBytes) == 0; + } + + public final Offset roundedUpBy(int numberOfBytes) { + if (isRoundedBy(numberOfBytes)) { + return this; + } + return plus(numberOfBytes - remainder(numberOfBytes)); + } + + @INLINE(override = true) + public Offset and(Offset operand) { + if (Word.width() == 64) { + return fromLong(toLong() & operand.toLong()); + } + return fromInt(toInt() & operand.toInt()); + } + + @INLINE(override = true) + public Offset and(int operand) { + return and(fromInt(operand)); + } + + @INLINE(override = true) + public Offset and(long operand) { + return and(fromLong(operand)); + } + + @INLINE(override = true) + public Offset or(Offset operand) { + if (Word.width() == 64) { + return fromLong(toLong() | operand.toLong()); + } + return fromInt(toInt() | operand.toInt()); + } + + @INLINE(override = true) + public Offset or(int operand) { + return or(fromInt(operand)); + } + + @INLINE(override = true) + public Offset or(long operand) { + return or(fromLong(operand)); + } + + @INLINE(override = true) + public Offset not() { + if (Word.width() == 64) { + return fromLong(~toLong()); + } + return fromInt(~toInt()); + } + + @INLINE + public final Offset roundedDownBy(int numberOfBytes) { + return minus(remainder(numberOfBytes)); + } + + @INLINE(override = true) + public final Offset aligned() { + final int n = Word.size(); + return plus(n - 1).and(Offset.fromInt(n - 1).not()); + } + + @INLINE(override = true) + public final boolean isAligned() { + final int n = Word.size(); + return and(n - 1).equals(Offset.zero()); + } + + public final int numberOfEffectiveBits() { + if (Word.width() == 64) { + final long n = toLong(); + if (n >= 0) { + return 64 - Long.numberOfLeadingZeros(n); + } + return 65 - Long.numberOfLeadingZeros(~n); + } + final int n = toInt(); + if (n >= 0) { + return 32 - Integer.numberOfLeadingZeros(n); + } + return 33 - Integer.numberOfLeadingZeros(~n); + } + + public final WordWidth effectiveWidth() { + final int bit = numberOfEffectiveBits(); + for (WordWidth width : WordWidth.values()) { + if (bit < width.numberOfBits) { + return width; + } + } + throw ProgramError.unexpected(); + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/Package.java b/JavaInJava/src/com/sun/max/unsafe/Package.java new file mode 100644 index 0000000..7f156ca --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/Package.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import com.sun.max.*; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class Package extends BasePackage { + public Package() { + super(); + } + + @Override + public Class[] wordSubclasses() { + return new Class[] { + Address.class, + Offset.class, + Pointer.class, + Size.class, + Word.class + }; + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/Pointer.java b/JavaInJava/src/com/sun/max/unsafe/Pointer.java new file mode 100644 index 0000000..ad085bd --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/Pointer.java @@ -0,0 +1,949 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import static com.sun.cri.bytecode.Bytecodes.*; + +import com.sun.cri.bytecode.*; +import com.sun.max.annotate.*; +import com.sun.max.asm.*; +import com.sun.max.lang.*; +import com.sun.max.lang.Bytes; +import com.sun.max.platform.*; +import com.sun.max.vm.reference.*; +import com.sun.max.vm.runtime.*; +import com.sun.max.vm.type.*; + +/** + * Pointers are addresses with extra methods to access memory. + * + * @author Bernd Mathiske + */ +public abstract class Pointer extends Address implements Accessor { + + private static final int FLOAT_SIZE = 4; + private static final int DOUBLE_SIZE = 8; + + protected Pointer() { + } + + public interface Procedure { + void run(Pointer pointer); + } + + public interface Predicate { + boolean evaluate(Pointer pointer); + } + + @INLINE + public static Pointer zero() { + return fromInt(0); + } + + @INLINE + public static Pointer fromUnsignedInt(int value) { + return Address.fromUnsignedInt(value).asPointer(); + } + + @INLINE + public static Pointer fromInt(int value) { + return Address.fromInt(value).asPointer(); + } + + @INLINE + public static Pointer fromLong(long value) { + return Address.fromLong(value).asPointer(); + } + + @Override + public final String toString() { + return "^" + toHexString(); + } + + @Override + @INLINE + public final Pointer plus(int addend) { + return asAddress().plus(addend).asPointer(); + } + + @Override + @INLINE + public final Pointer plus(long addend) { + return asAddress().plus(addend).asPointer(); + } + + @Override + @INLINE + public final Pointer plus(Address addend) { + return asAddress().plus(addend).asPointer(); + } + + @Override + @INLINE + public final Pointer plus(Offset addend) { + return asAddress().plus(addend).asPointer(); + } + + @INLINE + public final Pointer plusWords(int nWords) { + return plus(nWords * Word.size()); + } + + @Override + @INLINE + public final Pointer minus(Address subtrahend) { + return asAddress().minus(subtrahend).asPointer(); + } + + @Override + @INLINE + public final Pointer minus(int subtrahend) { + return asAddress().minus(subtrahend).asPointer(); + } + + @Override + @INLINE + public final Pointer minus(long subtrahend) { + return asAddress().minus(subtrahend).asPointer(); + } + + @INLINE + public final Pointer minusWords(int nWords) { + return minus(nWords * Word.size()); + } + + @Override + @INLINE + public final Pointer minus(Offset subtrahend) { + return asAddress().minus(subtrahend).asPointer(); + } + + @Override + @INLINE + public final Pointer times(Address factor) { + return asAddress().times(factor).asPointer(); + } + + @Override + @INLINE + public final Pointer times(int factor) { + return asAddress().times(factor).asPointer(); + } + + @Override + @INLINE + public final Pointer dividedBy(Address divisor) { + return asAddress().dividedBy(divisor).asPointer(); + } + + @Override + @INLINE + public final Pointer dividedBy(int divisor) { + return asAddress().dividedBy(divisor).asPointer(); + } + + @Override + @INLINE + public final Pointer remainder(Address divisor) { + return asAddress().remainder(divisor).asPointer(); + } + + @Override + @INLINE + public final Pointer roundedUpBy(Address nBytes) { + return asAddress().roundedUpBy(nBytes).asPointer(); + } + + @Override + @INLINE + public final Pointer roundedUpBy(int nBytes) { + return asAddress().roundedUpBy(nBytes).asPointer(); + } + + @Override + @INLINE + public final Pointer roundedDownBy(int nBytes) { + return asAddress().roundedDownBy(nBytes).asPointer(); + } + + @Override + @INLINE + public final Pointer wordAligned() { + return asAddress().wordAligned().asPointer(); + } + + @Override + @INLINE(override = true) + public final boolean isWordAligned() { + return asAddress().isWordAligned(); + } + + @Override + @INLINE + public final Pointer bitSet(int index) { + return asAddress().bitSet(index).asPointer(); + } + + @Override + @INLINE + public final Pointer bitClear(int index) { + return asAddress().bitClear(index).asPointer(); + } + + @Override + @INLINE + public final Pointer and(Address operand) { + return asAddress().and(operand).asPointer(); + } + + @Override + @INLINE + public final Pointer and(int operand) { + return asAddress().and(operand).asPointer(); + } + + @Override + @INLINE + public final Pointer and(long operand) { + return asAddress().and(operand).asPointer(); + } + + @Override + @INLINE + public final Pointer or(Address operand) { + return asAddress().or(operand).asPointer(); + } + + @Override + @INLINE + public final Pointer or(int operand) { + return asAddress().or(operand).asPointer(); + } + + @Override + @INLINE + public final Pointer or(long operand) { + return asAddress().or(operand).asPointer(); + } + + @Override + @INLINE + public final Pointer not() { + return asAddress().not().asPointer(); + } + + @Override + @INLINE + public final Pointer shiftedLeft(int nBits) { + return asAddress().shiftedLeft(nBits).asPointer(); + } + + @Override + @INLINE + public final Pointer unsignedShiftedRight(int nBits) { + return asAddress().unsignedShiftedRight(nBits).asPointer(); + } + + @UNSAFE + @FOLD + private static boolean risc() { + return Platform.platform().isa.category == ISA.Category.RISC; + } + + public byte readByte(int offset) { + return readByte(Offset.fromInt(offset)); + } + + public abstract byte readByte(Offset offset); + + private native byte builtinGetByte(int displacement, int index); + + @INLINE + public final byte getByte(int displacement, int index) { + if (risc()) { + return readByte(Offset.fromInt(index).plus(displacement)); + } + return builtinGetByte(displacement, index); + } + + @INLINE + public final byte getByte(int index) { + return getByte(0, index); + } + + @INLINE + public final byte getByte() { + return getByte(0); + } + + @INLINE + public final boolean readBoolean(Offset offset) { + return UnsafeCast.asBoolean(readByte(offset)); + } + + @INLINE + public final boolean readBoolean(int offset) { + return UnsafeCast.asBoolean(readByte(offset)); + } + + @INLINE + public final boolean getBoolean(int displacement, int index) { + return UnsafeCast.asBoolean(getByte(displacement, index)); + } + + @INLINE + public final boolean getBoolean(int index) { + return getBoolean(0, index); + } + + @INLINE + public final boolean getBoolean() { + return getBoolean(0); + } + + public final short readShort(int offset) { + return readShort(Offset.fromInt(offset)); + } + + public abstract short readShort(Offset offset); + + private native short builtinGetShort(int displacement, int index); + + @INLINE + public final short getShort(int displacement, int index) { + if (risc()) { + return readShort(Offset.fromInt(index).times(Shorts.SIZE).plus(displacement)); + } + return builtinGetShort(displacement, index); + } + + @INLINE + public final short getShort(int index) { + return getShort(0, index); + } + + @INLINE + public final short getShort() { + return getShort(0); + } + + public final char readChar(int offset) { + return readChar(Offset.fromInt(offset)); + } + + public abstract char readChar(Offset offset); + + private native char builtinGetChar(int displacement, int index); + + @INLINE + public final char getChar(int displacement, int index) { + if (risc()) { + return readChar(Offset.fromInt(index).times(Chars.SIZE).plus(displacement)); + } + return builtinGetChar(displacement, index); + } + + @INLINE + public final char getChar(int index) { + return getChar(0, index); + } + + @INLINE + public final char getChar() { + return getChar(0); + } + + public final int readInt(int offset) { + return readInt(Offset.fromInt(offset)); + } + + public abstract int readInt(Offset offset); + + private native int builtinGetInt(int displacement, int index); + + @INLINE + public final int getInt(int displacement, int index) { + if (risc()) { + return readInt(Offset.fromInt(index).times(Ints.SIZE).plus(displacement)); + } + return builtinGetInt(displacement, index); + } + + @INLINE + public final int getInt(int index) { + return getInt(0, index); + } + + @INLINE + public final int getInt() { + return getInt(0); + } + + public final float readFloat(int offset) { + return readFloat(Offset.fromInt(offset)); + } + + public abstract float readFloat(Offset offset); + + private native float builtinGetFloat(int displacement, int index); + + @INLINE + public final float getFloat(int displacement, int index) { + if (risc()) { + return readFloat(Offset.fromInt(index).times(FLOAT_SIZE).plus(displacement)); + } + return builtinGetFloat(displacement, index); + } + + @INLINE + public final float getFloat(int index) { + return getFloat(0, index); + } + + @INLINE + public final float getFloat() { + return getFloat(0); + } + + public final long readLong(int offset) { + return readLong(Offset.fromInt(offset)); + } + + public abstract long readLong(Offset offset); + + private native long builtinGetLong(int displacement, int index); + + @INLINE + public final long getLong(int displacement, int index) { + if (risc()) { + return readLong(Offset.fromInt(index).times(Longs.SIZE).plus(displacement)); + } + return builtinGetLong(displacement, index); + } + + @INLINE + public final long getLong(int index) { + return getLong(0, index); + } + + @INLINE + public final long getLong() { + return getLong(0); + } + + public final double readDouble(int offset) { + return readDouble(Offset.fromInt(offset)); + } + + public abstract double readDouble(Offset offset); + + private native double builtinGetDouble(int displacement, int index); + + @INLINE + public final double getDouble(int displacement, int index) { + if (risc()) { + return readDouble(Offset.fromInt(index).times(DOUBLE_SIZE).plus(displacement)); + } + return builtinGetDouble(displacement, index); + } + + @INLINE + public final double getDouble(int index) { + return getDouble(0, index); + } + + @INLINE + public final double getDouble() { + return getDouble(0); + } + + public final Word readWord(int offset) { + return readWord(Offset.fromInt(offset)); + } + + public abstract Word readWord(Offset offset); + + private native Word builtinGetWord(int displacement, int index); + + @INLINE + public final Word getWord(int displacement, int index) { + if (risc()) { + return readWord(Offset.fromInt(index).times(Word.size()).plus(displacement)); + } + return builtinGetWord(displacement, index); + } + + @INLINE + public final Word getWord(int index) { + return getWord(0, index); + } + + @INLINE + public final Word getWord() { + return getWord(0); + } + + public final Reference readReference(int offset) { + return readReference(Offset.fromInt(offset)); + } + + public abstract Reference readReference(Offset offset); + + private native Reference builtinGetReference(int displacement, int index); + + @INLINE + public final Reference getReference(int displacement, int index) { + if (risc()) { + return readReference(Offset.fromInt(index).times(Word.size()).plus(displacement)); + } + return builtinGetReference(displacement, index); + } + + @INLINE + public final Reference getReference(int index) { + return getReference(0, index); + } + + @INLINE + public final Reference getReference() { + return getReference(0); + } + + public final void writeByte(int offset, byte value) { + writeByte(Offset.fromInt(offset), value); + } + + public abstract void writeByte(Offset offset, byte value); + + private native void builtinSetByte(int displacement, int index, byte value); + + @INLINE + public final void setByte(int displacement, int index, byte value) { + if (risc()) { + writeByte(Offset.fromInt(index).plus(displacement), value); + } else { + builtinSetByte(displacement, index, value); + } + } + + @INLINE + public final void setByte(int index, byte value) { + setByte(0, index, value); + } + + @INLINE + public final void setByte(byte value) { + setByte(0, value); + } + + @INLINE + public final void writeBoolean(Offset offset, boolean value) { + writeByte(offset, UnsafeCast.asByte(value)); + } + + @INLINE + public final void writeBoolean(int offset, boolean value) { + writeByte(offset, UnsafeCast.asByte(value)); + } + + @INLINE + public final void setBoolean(int displacement, int index, boolean value) { + setByte(displacement, index, UnsafeCast.asByte(value)); + } + + @INLINE + public final void setBoolean(int index, boolean value) { + setBoolean(0, index, value); + } + + @INLINE + public final void setBoolean(boolean value) { + setBoolean(0, value); + } + + public final void writeShort(int offset, short value) { + writeShort(Offset.fromInt(offset), value); + } + + public abstract void writeShort(Offset offset, short value); + + private native void builtinSetShort(int displacement, int index, short value); + + @INLINE + public final void setShort(int displacement, int index, short value) { + if (risc()) { + writeShort(Offset.fromInt(index).times(Shorts.SIZE).plus(displacement), value); + } else { + builtinSetShort(displacement, index, value); + } + } + + @INLINE + public final void setShort(int index, short value) { + setShort(0, index, value); + } + + @INLINE + public final void setShort(short value) { + setShort(0, value); + } + + @INLINE + public final void writeChar(Offset offset, char value) { + writeShort(offset, UnsafeCast.asShort(value)); + } + + @INLINE + public final void writeChar(int offset, char value) { + writeShort(offset, UnsafeCast.asShort(value)); + } + + @INLINE + public final void setChar(int displacement, int index, char value) { + setShort(displacement, index, UnsafeCast.asShort(value)); + } + + @INLINE + public final void setChar(int index, char value) { + setChar(0, index, value); + } + + @INLINE + public final void setChar(char value) { + setChar(0, value); + } + + public final void writeInt(int offset, int value) { + writeInt(Offset.fromInt(offset), value); + } + + public abstract void writeInt(Offset offset, int value); + + private native void builtinSetInt(int displacement, int index, int value); + + @INLINE + public final void setInt(int displacement, int index, int value) { + if (risc()) { + writeInt(Offset.fromInt(index).times(Ints.SIZE).plus(displacement), value); + } else { + builtinSetInt(displacement, index, value); + } + } + + @INLINE + public final void setInt(int index, int value) { + setInt(0, index, value); + } + + @INLINE + public final void setInt(int value) { + setInt(0, value); + } + + public final void writeFloat(int offset, float value) { + writeFloat(Offset.fromInt(offset), value); + } + + public abstract void writeFloat(Offset offset, float value); + + private native void builtinSetFloat(int displacement, int index, float value); + + @INLINE + public final void setFloat(int displacement, int index, float value) { + if (risc()) { + writeFloat(Offset.fromInt(index).times(FLOAT_SIZE).plus(displacement), value); + } else { + builtinSetFloat(displacement, index, value); + } + } + + @INLINE + public final void setFloat(int index, float value) { + setFloat(0, index, value); + } + + @INLINE + public final void setFloat(float value) { + setFloat(0, value); + } + + public final void writeLong(int offset, long value) { + writeLong(Offset.fromInt(offset), value); + } + + public abstract void writeLong(Offset offset, long value); + + private native void builtinSetLong(int displacement, int index, long value); + + @INLINE + public final void setLong(int displacement, int index, long value) { + if (risc()) { + writeLong(Offset.fromInt(index).times(Longs.SIZE).plus(displacement), value); + } else { + builtinSetLong(displacement, index, value); + } + } + + @INLINE + public final void setLong(int index, long value) { + setLong(0, index, value); + } + + @INLINE + public final void setLong(long value) { + setLong(0, value); + } + + public final void writeDouble(int offset, double value) { + writeDouble(Offset.fromInt(offset), value); + } + + public abstract void writeDouble(Offset offset, double value); + + private native void builtinSetDouble(int displacement, int index, double value); + + @INLINE + public final void setDouble(int displacement, int index, double value) { + if (risc()) { + writeDouble(Offset.fromInt(index).times(DOUBLE_SIZE).plus(displacement), value); + } else { + builtinSetDouble(displacement, index, value); + } + } + + @INLINE + public final void setDouble(int index, double value) { + setDouble(0, index, value); + } + + @INLINE + public final void setDouble(double value) { + setDouble(0, value); + } + + public final void writeWord(int offset, Word value) { + writeWord(Offset.fromInt(offset), value); + } + + public abstract void writeWord(Offset offset, Word value); + + private native void builtinSetWord(int displacement, int index, Word value); + + @INLINE + public final void setWord(int displacement, int index, Word value) { + if (risc()) { + writeWord(Offset.fromInt(index).times(Word.size()).plus(displacement), value); + } else { + builtinSetWord(displacement, index, value); + } + } + + @INLINE + public final void setWord(int index, Word value) { + setWord(0, index, value); + } + + @INLINE + public final void setWord(Word value) { + setWord(0, value); + } + + public final void writeReference(int offset, Reference value) { + writeReference(Offset.fromInt(offset), value); + } + + public abstract void writeReference(Offset offset, Reference value); + + private native void builtinSetReference(int displacement, int index, Reference value); + + @INLINE + public final void setReference(int displacement, int index, Reference value) { + if (risc()) { + writeReference(Offset.fromInt(index).times(Word.size()).plus(displacement), value); + } else { + builtinSetReference(displacement, index, value); + } + } + + @INLINE + public final void setReference(int index, Reference value) { + setReference(0, index, value); + } + + @INLINE + public final void setReference(Reference value) { + setReference(0, value); + } + + /** + * @see Accessor#compareAndSwapInt(Offset, int, int) + */ + public native int compareAndSwapInt(int offset, int expectedValue, int newValue); + + /** + * @see Accessor#compareAndSwapInt(Offset, int, int) + */ + public native int compareAndSwapInt(Offset offset, int expectedValue, int newValue); + + /** + * @see Accessor#compareAndSwapInt(Offset, int, int) + */ + public native Word compareAndSwapWord(int offset, Word expectedValue, Word newValue); + + /** + * @see Accessor#compareAndSwapInt(Offset, int, int) + */ + public native Word compareAndSwapWord(Offset offset, Word expectedValue, Word newValue); + + /** + * @see Accessor#compareAndSwapInt(Offset, int, int) + */ + public native Reference compareAndSwapReference(int offset, Reference expectedValue, Reference newValue); + + /** + * @see Accessor#compareAndSwapInt(Offset, int, int) + */ + public native Reference compareAndSwapReference(Offset offset, Reference expectedValue, Reference newValue); + + /** + * Sets a bit in the bit map whose base is denoted by the value of this pointer. + * + * ATTENTION: There is no protection against concurrent access to the affected byte. + * + * This method may read the affected byte first, then set the bit in it and then write the byte back. + * + * @param bitIndex the index of the bit to set + */ + public void setBit(int bitIndex) { + final int byteIndex = Unsigned.idiv(bitIndex, Bytes.WIDTH); + byte byteValue = getByte(byteIndex); + byteValue |= 1 << (bitIndex % Bytes.WIDTH); + setByte(byteIndex, byteValue); + } + + /** + * Modifies up to 8 bits in the bit map whose base is denoted by the value of this pointer + * by OR'ing in a given 8-bit mask. + * + * ATTENTION: There is no protection against concurrent access to affected bytes. + * + * This method may read each affected byte first, then set some bits in it and then write the byte back. + * There are either 1 or 2 affected bytes, depending on alignment of the bit index to bytes in memory. + * + * @param bitIndex the index of the first bit to set + * @param bits a mask of 8 bits OR'ed with the 8 bits in this bit map starting at {@code bitIndex} + */ + public void setBits(int bitIndex, byte bits) { + // If we do not mask off the leading bits after a conversion to int right here, + // then the arithmetic operations below will convert implicitly to int and may insert sign bits. + final int intBits = bits & 0xff; + + int byteIndex = Unsigned.idiv(bitIndex, Bytes.WIDTH); + final int rest = bitIndex % Bytes.WIDTH; + byte byteValue = getByte(byteIndex); + byteValue |= intBits << rest; + setByte(byteIndex, byteValue); + if (rest > 0) { + byteIndex++; + byteValue = getByte(byteIndex); + byteValue |= intBits >>> (Bytes.WIDTH - rest); + setByte(byteIndex, byteValue); + } + } + + public final void copyElements(int displacement, int srcIndex, Object dst, int dstIndex, int length) { + Kind kind = Kind.fromJava(dst.getClass().getComponentType()); + switch (kind.asEnum) { + case BOOLEAN: { + boolean[] arr = (boolean[]) dst; + for (int i = 0; i < length; ++i) { + arr[dstIndex + i] = getBoolean(displacement, srcIndex); + } + break; + } + case BYTE: { + byte[] arr = (byte[]) dst; + for (int i = 0; i < length; ++i) { + arr[dstIndex + i] = getByte(displacement, srcIndex); + } + break; + } + case CHAR: { + char[] arr = (char[]) dst; + for (int i = 0; i < length; ++i) { + arr[dstIndex + i] = getChar(displacement, srcIndex); + } + break; + } + case SHORT: { + short[] arr = (short[]) dst; + for (int i = 0; i < length; ++i) { + arr[dstIndex + i] = getShort(displacement, srcIndex); + } + break; + } + case INT: { + int[] arr = (int[]) dst; + for (int i = 0; i < length; ++i) { + arr[dstIndex + i] = getInt(displacement, srcIndex); + } + break; + } + case FLOAT: { + float[] arr = (float[]) dst; + for (int i = 0; i < length; ++i) { + arr[dstIndex + i] = getFloat(displacement, srcIndex); + } + break; + } + case LONG: { + long[] arr = (long[]) dst; + for (int i = 0; i < length; ++i) { + arr[dstIndex + i] = getLong(displacement, srcIndex); + } + break; + } + case DOUBLE: { + double[] arr = (double[]) dst; + for (int i = 0; i < length; ++i) { + arr[dstIndex + i] = getDouble(displacement, srcIndex); + } + break; + } + case REFERENCE: { + Reference[] arr = (Reference[]) dst; + for (int i = 0; i < length; ++i) { + arr[dstIndex + i] = getReference(displacement, srcIndex); + } + break; + } + case WORD: { + Word[] arr = (Word[]) dst; + for (int i = 0; i < length; ++i) { + WordArray.set(arr, dstIndex + i, getWord(displacement, srcIndex)); + } + break; + } + default: + throw FatalError.unexpected("invalid type"); + } + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/Size.java b/JavaInJava/src/com/sun/max/unsafe/Size.java new file mode 100644 index 0000000..ccc05eb --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/Size.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import com.sun.max.annotate.*; +import com.sun.max.lang.*; + +/** + * Use this type rather than Address to remark that you are referring to the size of something. A "size" is always + * referring to a number of bytes. (In contrast, a "length" is bound to a given snippet unit that may differ from + * bytes.) + * + * We delegate much of the implementation to Address. + * We only need this for running on the host VM, + * because there the actual types are BoxedSize and BoxedAddress. + * + * @author Bernd Mathiske + */ +public abstract class Size extends Address { + + protected Size() { + } + + @INLINE + public static Size zero() { + return fromInt(0); + } + + public static final Size K = Size.fromInt(Ints.K); + public static final Size M = Size.fromInt(Ints.M); + public static final Size G = Size.fromLong(Longs.G); + + @INLINE + public static Size fromUnsignedInt(int value) { + return Address.fromUnsignedInt(value).asSize(); + } + + @INLINE + public static Size fromInt(int value) { + return Address.fromInt(value).asSize(); + } + + @INLINE + public static Size fromLong(long value) { + return Address.fromLong(value).asSize(); + } + + @Override + public String toString() { + return "#" + toUnsignedString(10); + } + + @INLINE + @Override + public final Size plus(int addend) { + return asAddress().plus(addend).asSize(); + } + + @INLINE + @Override + public final Size plus(long addend) { + return asAddress().plus(addend).asSize(); + } + + @INLINE + @Override + public final Size plus(Address addend) { + return asAddress().plus(addend).asSize(); + } + + @INLINE + @Override + public final Size plus(Offset addend) { + return asAddress().plus(addend).asSize(); + } + + @INLINE + @Override + public final Size minus(Address subtrahend) { + return asAddress().minus(subtrahend).asSize(); + } + + @INLINE + @Override + public final Size minus(int subtrahend) { + return asAddress().minus(subtrahend).asSize(); + } + + @INLINE + @Override + public final Size minus(long subtrahend) { + return asAddress().minus(subtrahend).asSize(); + } + + @INLINE + @Override + public final Size minus(Offset subtrahend) { + return asAddress().minus(subtrahend).asSize(); + } + + @INLINE + @Override + public final Size times(Address factor) { + return asAddress().times(factor).asSize(); + } + + @INLINE + @Override + public final Size times(int factor) { + return asAddress().times(factor).asSize(); + } + + @INLINE + @Override + public final Size dividedBy(Address divisor) { + return asAddress().dividedBy(divisor).asSize(); + } + + @INLINE + @Override + public final Size dividedBy(int divisor) { + return asAddress().dividedBy(divisor).asSize(); + } + + @INLINE + @Override + public final Size remainder(Address divisor) { + return asAddress().remainder(divisor).asSize(); + } + + @INLINE + @Override + public final Size roundedUpBy(int nBytes) { + return asAddress().roundedUpBy(nBytes).asSize(); + } + + @INLINE + @Override + public final Size roundedDownBy(int nBytes) { + return asAddress().roundedDownBy(nBytes).asSize(); + } + + @INLINE + @Override + public final Size wordAligned() { + return asAddress().wordAligned().asSize(); + } + + @INLINE(override = true) + @Override + public Size aligned(int alignment) { + return asAddress().aligned(alignment).asSize(); + } + + @INLINE(override = true) + @Override + public final boolean isWordAligned() { + return asAddress().isWordAligned(); + } + + @INLINE + @Override + public final Size bitSet(int index) { + return asAddress().bitSet(index).asSize(); + } + + @INLINE + @Override + public final Size bitClear(int index) { + return asAddress().bitClear(index).asSize(); + } + + @INLINE + @Override + public final Size and(Address operand) { + return asAddress().and(operand).asSize(); + } + + @INLINE + @Override + public final Size and(int operand) { + return asAddress().and(operand).asSize(); + } + + @INLINE + @Override + public final Size and(long operand) { + return asAddress().and(operand).asSize(); + } + + @INLINE + @Override + public final Size or(Address operand) { + return asAddress().or(operand).asSize(); + } + + @INLINE + @Override + public final Size or(int operand) { + return asAddress().or(operand).asSize(); + } + + @INLINE + @Override + public final Size or(long operand) { + return asAddress().or(operand).asSize(); + } + + @INLINE + @Override + public final Size not() { + return asAddress().not().asSize(); + } + + @INLINE + @Override + public final Size shiftedLeft(int nBits) { + return asAddress().shiftedLeft(nBits).asSize(); + } + + @INLINE + @Override + public final Size unsignedShiftedRight(int nBits) { + return asAddress().unsignedShiftedRight(nBits).asSize(); + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/UnsafeCast.java b/JavaInJava/src/com/sun/max/unsafe/UnsafeCast.java new file mode 100644 index 0000000..aa20ff6 --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/UnsafeCast.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import static com.sun.cri.bytecode.Bytecodes.*; + +import java.lang.ref.*; +import java.security.*; + +import com.sun.cri.bytecode.*; +import com.sun.max.annotate.*; +import com.sun.max.vm.actor.holder.*; +import com.sun.max.vm.actor.member.*; +import com.sun.max.vm.object.*; +import com.sun.max.vm.reflection.*; +import com.sun.max.vm.stack.*; +import com.sun.max.vm.thread.*; +import com.sun.max.vm.type.*; + +/** + * Any method annotated with {@link INTRINSIC}(UNSAFE_CAST) exists solely to provide an escape hatch from Java's type checking. All + * such methods are recognized by the compiler to simply be an unsafe coercion from one type to another. + * + * Any method annotated with this annotation must take exactly one parameter (which will be the receiver if the method + * is non-static ), have a non-void, non-generic return type. The type of the parameter is the type being + * converted from and the return type is the type being converted to. + * + * The compiler must translate calls to these methods to simply replace the use of the result with the single parameter. + * + * A method annotated with the {@code INTRINSIC(UNSAFE_CAST)} may have an implementation (i.e. it is not {@code native} and not + * {@code abstract}). This implementation is used to fold (i.e. compile-time evaluate) the method. The implementation + * will simply be an explicit cast statement that results in a runtime type check when the method is + * evaluated. + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public final class UnsafeCast { + @HOSTED_ONLY + private UnsafeCast() { + } + + @INTRINSIC(UNSAFE_CAST) public static VmThread asVmThread(Object object) { return (VmThread) object; } + @INTRINSIC(UNSAFE_CAST) public static Object[] asObjectArray(Object object) { return (Object[]) object; } + @INTRINSIC(UNSAFE_CAST) public static Hybrid asHybrid(Object object) { return (Hybrid) object; } + @INTRINSIC(UNSAFE_CAST) public static StackUnwindingContext asStackUnwindingContext(Object object) { return (StackUnwindingContext) object; } + @INTRINSIC(UNSAFE_CAST) public static Class asClass(Object object) { return (Class) object; } + @INTRINSIC(UNSAFE_CAST) public static ClassRegistry asClassRegistry(Object object) { return (ClassRegistry) object; } + @INTRINSIC(UNSAFE_CAST) public static MethodInvocationStub asMethodInvocationStub(Object object) { return (MethodInvocationStub) object; } + @INTRINSIC(UNSAFE_CAST) public static ConstructorInvocationStub asConstructorInvocationStub(Object object) { return (ConstructorInvocationStub) object; } + @INTRINSIC(UNSAFE_CAST) public static Throwable asThrowable(Object object) { return (Throwable) object; } + @INTRINSIC(UNSAFE_CAST) public static int[] asIntArray(Object object) { return (int[]) object; } + @INTRINSIC(UNSAFE_CAST) public static DynamicHub asDynamicHub(Object object) { return (DynamicHub) object; } + @INTRINSIC(UNSAFE_CAST) public static Hub asHub(Object object) { return (Hub) object; } + @INTRINSIC(UNSAFE_CAST) public static ArrayClassActor asArrayClassActor(Object object) { return (ArrayClassActor) object; } + @INTRINSIC(UNSAFE_CAST) public static ClassActor asClassActor(Object object) { return (ClassActor) object; } + @INTRINSIC(UNSAFE_CAST) public static FieldActor asFieldActor(Object object) { return (FieldActor) object; } + @INTRINSIC(UNSAFE_CAST) public static MethodActor asClassMethodActor(Object object) { return (ClassMethodActor) object; } + @INTRINSIC(UNSAFE_CAST) public static StaticMethodActor asStaticMethodActor(Object object) { return (StaticMethodActor) object; } + @INTRINSIC(UNSAFE_CAST) public static VirtualMethodActor asVirtualMethodActor(Object object) { return (VirtualMethodActor) object; } + @INTRINSIC(UNSAFE_CAST) public static AccessControlContext asAccessControlContext(Object object) { return (AccessControlContext) object; } + @INTRINSIC(UNSAFE_CAST) public static Reference asJDKReference(Object object) { return (Reference) object; } + @INTRINSIC(UNSAFE_CAST) public static InterfaceActor asInterfaceActor(Object object) { return (InterfaceActor) object; } + @INTRINSIC(UNSAFE_CAST) public static InterfaceMethodActor asInterfaceMethodActor(Object object) { return (InterfaceMethodActor) object; } + + @INTRINSIC(UNSAFE_CAST) public static Address asAddress(int value) { return Address.fromUnsignedInt(value); } + @INTRINSIC(UNSAFE_CAST) public static Address asAddress(long value) { return Address.fromLong(value); } + @INTRINSIC(UNSAFE_CAST) public static Offset asOffset(int value) { return Offset.fromUnsignedInt(value); } + @INTRINSIC(UNSAFE_CAST) public static Offset asOffset(long value) { return Offset.fromLong(value); } + + @INTRINSIC(UNSAFE_CAST) public static int asInt(Word word) { return word.asAddress().toInt(); } + @INTRINSIC(UNSAFE_CAST) public static long asLong(Word word) { return word.asAddress().toLong(); } + @INTRINSIC(UNSAFE_CAST) public static boolean asBoolean(byte value) { return value != 0; } + @INTRINSIC(UNSAFE_CAST) public static byte asByte(boolean value) { return value ? 1 : (byte) 0; } + @INTRINSIC(UNSAFE_CAST) public static int asInt(boolean value) { return value ? 1 : 0; } + @INTRINSIC(UNSAFE_CAST) public static char asChar(short value) { return (char) value; } + @INTRINSIC(UNSAFE_CAST) public static short asShort(char value) { return (short) value; } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/WithoutAccessCheck.java b/JavaInJava/src/com/sun/max/unsafe/WithoutAccessCheck.java new file mode 100644 index 0000000..8a98d9e --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/WithoutAccessCheck.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import java.lang.reflect.*; + +import sun.misc.*; + +import com.sun.max.program.*; + +/** + * Bypass access checks for reflective operations. + * + * @author Bernd Mathiske + */ +public final class WithoutAccessCheck { + public static final Unsafe unsafe = (Unsafe) getStaticField(Unsafe.class, "theUnsafe"); + + private WithoutAccessCheck() { + } + + private static Field findField(Class javaClass, String fieldName) { + Class c = javaClass; + while (c != null) { + try { + final Field field = c.getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } catch (NoSuchFieldException noSuchFieldException) { + } + c = c.getSuperclass(); + } + throw ProgramError.unexpected("could not find field " + fieldName); + } + + private static void accessError(Field field) { + throw new IllegalAccessError("could not access field " + field); + } + + public static Object getInstanceField(Object tuple, String fieldName) { + final Field field = findField(tuple.getClass(), fieldName); + try { + return field.get(tuple); + } catch (IllegalAccessException illegalAccessException) { + accessError(field); + return null; + } + } + + public static void setInstanceField(Object tuple, String fieldName, Object value) { + final Field field = findField(tuple.getClass(), fieldName); + try { + field.set(tuple, value); + } catch (IllegalAccessException illegalAccessException) { + accessError(field); + } + } + + public static Object getStaticField(Class javaClass, String fieldName) { + final Field field = findField(javaClass, fieldName); + try { + return field.get(javaClass); + } catch (IllegalAccessException illegalAccessException) { + accessError(field); + return null; + } + } + + public static void setStaticField(Class javaClass, String fieldName, Object value) { + final Field field = findField(javaClass, fieldName); + try { + field.set(javaClass, value); + } catch (IllegalAccessException illegalAccessException) { + accessError(field); + } + } + + public static Object newInstance(Class javaClass) { + try { + final Constructor constructor = javaClass.getDeclaredConstructor(); + constructor.setAccessible(true); + return constructor.newInstance(); + } catch (Exception e) { + throw ProgramError.unexpected(e); + } + } + + /** + * Return the named method with a method signature matching parameter classes from the given class. + */ + private static Method getMethod(Class instanceClass, String methodName, Class[] parameterClasses) + throws NoSuchMethodException { + if (instanceClass == null) { + throw new NoSuchMethodException("Invalid method : " + methodName); + } + try { + final Method declaredMethod = instanceClass.getDeclaredMethod(methodName, parameterClasses); + return declaredMethod; + } catch (NoSuchMethodException noSuchMethodException) { + return getMethod(instanceClass.getSuperclass(), methodName, parameterClasses); + } + } + + private static Class getWrapperClass(Class primitiveClass) { + assert primitiveClass.isPrimitive(); + String name = primitiveClass.getName(); + if (name.equals("int")) { + name = "Integer"; + } else if (name.equals("char")) { + name = "Character"; + } else { + name = Character.toUpperCase(name.charAt(0)) + name.substring(1); + } + try { + return Class.forName("java.lang." + name); + } catch (Throwable throwable) { + throw ProgramError.unexpected(); + } + } + + private static boolean compatible(Class parameterClass, Object argument) { + if (parameterClass == null) { + return false; + } + if (parameterClass.isPrimitive()) { + if (argument == null) { + return false; + } + return getWrapperClass(parameterClass).isInstance(argument); + } else if (argument == null) { + return true; + } + return parameterClass.isInstance(argument); + } + + private static boolean compatible(Class[] parameterClasses, Object[] arguments) { + if (arguments == null) { + return parameterClasses == null; + } + if (parameterClasses.length != arguments.length) { + return false; + } + for (int i = 0; i < parameterClasses.length; i++) { + if (!compatible(parameterClasses[i], arguments[i])) { + return false; + } + } + return true; + } + + /** + * Calls a method on the given object instance with the given arguments. + */ + public static Object invokeVirtual(Object instance, String methodName, Class[] parameterClasses, Object[] arguments) + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + assert compatible(parameterClasses, arguments); + final Method method = getMethod(instance.getClass(), methodName, parameterClasses); + method.setAccessible(true); + return method.invoke(instance, arguments); + } + + public static Object invokeStatic(Class instanceClass, String methodName, Class[] parameterClasses, Object[] arguments) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + assert compatible(parameterClasses, arguments); + final Method method = getMethod(instanceClass, methodName, parameterClasses); + method.setAccessible(true); + return method.invoke(null, arguments); + } + + public static Object invokeConstructor(Class instanceClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { + final Constructor constructor = instanceClass.getDeclaredConstructor(new Class[]{}); + constructor.setAccessible(true); + return constructor.newInstance(new Object[]{}); + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/Word.java b/JavaInJava/src/com/sun/max/unsafe/Word.java new file mode 100644 index 0000000..4a35321 --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/Word.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import static com.sun.cri.bytecode.Bytecodes.*; +import static com.sun.max.platform.Platform.*; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +import com.sun.cri.bytecode.*; +import com.sun.max.*; +import com.sun.max.annotate.*; +import com.sun.max.lang.*; +import com.sun.max.program.*; +import com.sun.max.vm.*; +import com.sun.max.vm.compiler.builtin.*; +import com.sun.max.vm.hosted.*; +import com.sun.max.vm.jni.*; +import com.sun.max.vm.value.*; + +/** + * A machine-word sized unboxed type. The {@code Word} type itself is mostly opaque, providing operations + * to determine the {@linkplain #size() size} (in bytes) and {@linkplain #width() width} (in bits) of a word. + * Subclasses define extra operations such as {@linkplain Offset signed} and {@linkplain Address unsigned} + * arithmetic, and {@linkplain Pointer pointer} operations. + * + * In a {@linkplain MaxineVM#isHosted() hosted} runtime, {@code Word} type values are implemented with + * {@linkplain Boxed boxed} values. + * + * The closure of {@code Word} types (i.e. all the classes that subclass {@link Word}) is {@linkplain #getSubclasses() discovered} + * during initialization in a hosted environment. This discovery mechanism relies on the same package based + * facility used to configure the schemes of a VM. Each package that defines one or more {@code Word} subclasses + * must also declare a subclass of {@link MaxPackage} named "Package" that overrides {@link MaxPackage#wordSubclasses()}. + * + * @see WordValue + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public abstract class Word { + + protected Word() { + } + + @INLINE + public static Word zero() { + return Address.zero(); + } + + @INLINE + public static Word allOnes() { + return Address.max(); + } + + @FOLD + public static Endianness endianness() { + return platform().endianness(); + } + + @FOLD + public static WordWidth widthValue() { + return platform().wordWidth(); + } + + @FOLD + public static int width() { + return widthValue().numberOfBits; + } + + @FOLD + public static int size() { + return widthValue().numberOfBytes; + } + + public final Address asAddress() { + throw new UnsupportedOperationException("later"); + } + + public final Offset asOffset() { + throw new UnsupportedOperationException("later"); + } + + public final Size asSize() { + throw new UnsupportedOperationException("later"); + } + + public final Pointer asPointer() { + throw new UnsupportedOperationException("later"); + } + + /** + * @return bit index of the least significant bit set, or -1 if zero. + */ + public final int leastSignificantBitSet() { + return SpecialBuiltin.leastSignificantBit(this); + } + + /** + * @return bit index of the least significant bit set, or -1 if zero. + */ + public final int mostSignificantBitSet() { + return SpecialBuiltin.mostSignificantBit(this); + } + + public final String toHexString() { + String result = Long.toHexString(asAddress().toLong()); + if (width() == 32 && result.length() > 8) { + result = result.substring(result.length() - 8); + } + return result; + } + + public final String toPaddedHexString(char pad) { + if (Word.width() == 64) { + return Longs.toPaddedHexString(asAddress().toLong(), pad); + } + return Ints.toPaddedHexString(asAddress().toInt(), pad); + } + + @Override + public String toString() { + return "$" + toHexString(); + } + + @Override + public final int hashCode() { + return asOffset().toInt(); + } + + @INLINE + public final boolean isZero() { + return equals(Word.zero()); + } + + @INLINE + public final boolean isAllOnes() { + return equals(Word.allOnes()); + } + + @INLINE + public final boolean equals(Word other) { + if (Word.width() == 64) { + return asOffset().toLong() == other.asOffset().toLong(); + } + return asOffset().toInt() == other.asOffset().toInt(); + } + + @Override + public final boolean equals(Object other) { + throw ProgramError.unexpected("must not call equals(Object) with Word argument"); + } + + /** + * Reads an address from a given data input stream. + */ + public static Word read(DataInput stream) throws IOException { + if (width() == 64) { + return Address.fromLong(stream.readLong()); + } + return Address.fromInt(stream.readInt()); + } + + /** + * Writes this address to a given data output stream. + */ + @INLINE + public final void write(DataOutput stream) throws IOException { + if (width() == 64) { + stream.writeLong(asAddress().toLong()); + } else { + stream.writeInt(asAddress().toInt()); + } + } + + /** + * Reads an address from a given input stream using a given endianness. + */ + public static Word read(InputStream inputStream, Endianness endianness) throws IOException { + if (width() == 64) { + return Address.fromLong(endianness.readLong(inputStream)); + } + return Address.fromInt(endianness.readInt(inputStream)); + } + + /** + * Writes this address to a given output stream using a given endianness. + */ + @INLINE + public final void write(OutputStream outputStream, Endianness endianness) throws IOException { + if (width() == 64) { + endianness.writeLong(outputStream, asAddress().toLong()); + } else { + endianness.writeInt(outputStream, asAddress().toInt()); + } + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/WordArray.java b/JavaInJava/src/com/sun/max/unsafe/WordArray.java new file mode 100644 index 0000000..bbf1db3 --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/WordArray.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.unsafe; + +import com.sun.max.annotate.*; +import com.sun.max.vm.object.*; + +/** + * Why we never directly use any arrays of any subtype of 'Word': + * + * The byte codes aaload and aastore have no clue whether the array reference on the stack refers to a Word array or an + * Object array. As long as we are unable to or unsure whether we can discern the difference STATICALLY, we must not + * allow aaload and aastore to deal with either case dynamically. + * + * Compare this to the situation between byte arrays and boolean arrays addressed by baload and bastore! In those cases, + * we CAN differentiate between the respective array types DYNAMICALLY and cause no harm to the GC, because both types + * are primitive types. + * + * In case of Object and Word, one calls for a stack map entry and the other does not. Therefore, a dynamic distinction + * would require support for dynamic stack map changes. So far we are not willing to afford the price for that + * (runtime, implementation effort, complexity). + * + * Instead, always use WordArray.set() and WordArray.get() instead of [] when addressing word array elements. + * + * @author Bernd Mathiske + */ +public final class WordArray { + + private WordArray() { + } + + public static void fill(Word[] array, Word value) { + for (int i = 0; i < array.length; i++) { + uncheckedSet(array, i, value); + } + } + + @INLINE + public static Word uncheckedGet(Word[] array, int index) { + return ArrayAccess.getWord(array, index); + } + + @INLINE + public static Word get(Word[] array, int index) { + ArrayAccess.checkIndex(array, index); + return ArrayAccess.getWord(array, index); + } + + @INLINE + public static void uncheckedSet(Word[] array, int index, Word value) { + ArrayAccess.setWord(array, index, value); + } + + @INLINE + public static void set(Word[] array, int index, Word value) { + ArrayAccess.checkIndex(array, index); + ArrayAccess.setWord(array, index, value); + } + + public static void copyAll(Word[] fromArray, Word[] toArray) { + if (fromArray.length > toArray.length) { + throw new ArrayIndexOutOfBoundsException(); + } + for (int i = 0; i < fromArray.length; i++) { + uncheckedSet(toArray, i, uncheckedGet(fromArray, i)); + } + } +} diff --git a/JavaInJava/src/com/sun/max/unsafe/package-info.java b/JavaInJava/src/com/sun/max/unsafe/package-info.java new file mode 100644 index 0000000..cab09ab --- /dev/null +++ b/JavaInJava/src/com/sun/max/unsafe/package-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * "Unsafe" operations that transgress the safety guarantees of the core Java language specification: + * direct memory access, unchecked type casts, unchecked member access, etc. + * + * @author Bernd Mathiske + */ +package com.sun.max.unsafe; diff --git a/JavaInJava/src/com/sun/max/vm/VMPackage.java b/JavaInJava/src/com/sun/max/vm/VMPackage.java new file mode 100644 index 0000000..333cd2e --- /dev/null +++ b/JavaInJava/src/com/sun/max/vm/VMPackage.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.vm; + +import com.sun.max.*; +import com.sun.max.annotate.*; + +/** + * Denotes a package of classes that are (potentially) in the VM. + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public abstract class VMPackage extends MaxPackage { + public VMPackage() { + } + + public boolean isPartOfMaxineVM(VMConfiguration vmConfiguration) { + return true; + } + + /** + * Determines if this package contains any classes annotated with {@link METHOD_SUBSTITUTIONS}. + * @return + */ + public boolean containsMethodSubstitutions() { + return false; + } +} diff --git a/JavaInJava/src/com/sun/max/vm/VMScheme.java b/JavaInJava/src/com/sun/max/vm/VMScheme.java new file mode 100644 index 0000000..c123bc2 --- /dev/null +++ b/JavaInJava/src/com/sun/max/vm/VMScheme.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.vm; + +import com.sun.max.*; + +/** + * @author Bernd Mathiske + */ +public interface VMScheme extends Scheme { + + /** + * Gets the class embodying the specification of the scheme implemented by this object. + */ + Class specification(); + + /** + * Performs any scheme specific actions when entering a given VM phase. + * + * @param phase the VM phase that has just been entered + */ + void initialize(MaxineVM.Phase phase); + +} diff --git a/JavaInJava/src/com/sun/max/vm/compiler/builtin/SpecialBuiltin.java b/JavaInJava/src/com/sun/max/vm/compiler/builtin/SpecialBuiltin.java new file mode 100644 index 0000000..968f0c7 --- /dev/null +++ b/JavaInJava/src/com/sun/max/vm/compiler/builtin/SpecialBuiltin.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.vm.compiler.builtin; + +import com.sun.max.unsafe.*; + +/** + * @author Bernd Mathiske + */ +public abstract class SpecialBuiltin { + + /** + * Returns the index of the least significant bit set in a given value. + * + * @param value the value to scan for the least significant bit + * @return the index of the least significant bit within {@code value} or {@code -1} if {@code value == 0} + */ + public static int leastSignificantBit(Word value) { + long l = value.asAddress().toLong(); + if (l == 0) { + return -1; + } + return Long.numberOfTrailingZeros(l); + } + + /** + * Returns the index to the most significant bit set in a given value. + * + * @param value the value to scan for the most significant bit + * @return the index to the most significant bit within {@code value} or {@code -1} if {@code value == 0} + */ + public static int mostSignificantBit(Word value) { + long l = value.asAddress().toLong(); + if (l == 0) { + return -1; + } + return Long.numberOfTrailingZeros(l); + } + + public static boolean aboveEqual(int value1, int value2) { + final long unsignedInt1 = value1 & 0xFFFFFFFFL; + final long unsignedInt2 = value2 & 0xFFFFFFFFL; + return unsignedInt1 >= unsignedInt2; + } + + public static boolean aboveThan(int value1, int value2) { + final long unsignedInt1 = value1 & 0xFFFFFFFFL; + final long unsignedInt2 = value2 & 0xFFFFFFFFL; + return unsignedInt1 > unsignedInt2; + } + + public static boolean belowEqual(int value1, int value2) { + final long unsignedInt1 = value1 & 0xFFFFFFFFL; + final long unsignedInt2 = value2 & 0xFFFFFFFFL; + return unsignedInt1 <= unsignedInt2; + } + + public static boolean belowThan(int value1, int value2) { + final long unsignedInt1 = value1 & 0xFFFFFFFFL; + final long unsignedInt2 = value2 & 0xFFFFFFFFL; + return unsignedInt1 < unsignedInt2; + } + + public static float intToFloat(int value) { + return Float.intBitsToFloat(value); + } + + public static int floatToInt(float value) { + return Float.floatToRawIntBits(value); + } + + public static double longToDouble(long value) { + return Double.longBitsToDouble(value); + } + + public static long doubleToLong(double value) { + return Double.doubleToRawLongBits(value); + } +} diff --git a/JavaInJava/src/com/sun/max/vm/reference/Package.java b/JavaInJava/src/com/sun/max/vm/reference/Package.java new file mode 100644 index 0000000..cb666b9 --- /dev/null +++ b/JavaInJava/src/com/sun/max/vm/reference/Package.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.vm.reference; + +import com.sun.max.*; +import com.sun.max.vm.*; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class Package extends VMPackage { + public Package() { + super(); + } +} diff --git a/JavaInJava/src/com/sun/max/vm/reference/Reference.java b/JavaInJava/src/com/sun/max/vm/reference/Reference.java new file mode 100644 index 0000000..3f4c188 --- /dev/null +++ b/JavaInJava/src/com/sun/max/vm/reference/Reference.java @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.vm.reference; + +import static com.sun.max.vm.VMConfiguration.*; + +import com.sun.max.annotate.*; +import com.sun.max.unsafe.*; +import com.sun.max.vm.layout.*; + +/** + * @author Bernd Mathiske + */ +public abstract class Reference implements Accessor { + + protected Reference() { + } + + @UNSAFE + @FOLD + private static ReferenceScheme referenceScheme() { + return vmConfig().referenceScheme(); + } + + @INLINE + public static Reference fromJava(Object object) { + return referenceScheme().fromJava(object); + } + + @INLINE + public final Object toJava() { + return referenceScheme().toJava(this); + } + + @INLINE + public static Reference fromOrigin(Pointer origin) { + return referenceScheme().fromOrigin(origin); + } + + @INLINE + public final Pointer toOrigin() { + return referenceScheme().toOrigin(this); + } + + @INLINE + public final Reference readHubReference() { + return Layout.readHubReference(this); + } + + @INLINE + public final boolean isZero() { + return referenceScheme().isZero(this); + } + + @INLINE + public static Reference zero() { + return referenceScheme().zero(); + } + + @INLINE + public final boolean isAllOnes() { + return referenceScheme().isAllOnes(this); + } + + @INLINE(override = true) + public boolean equals(Reference other) { + return other == this; + } + + @INLINE + public final boolean isMarked() { + return referenceScheme().isMarked(this); + } + + @INLINE + public final Reference marked() { + return referenceScheme().marked(this); + } + + @INLINE + public final Reference unmarked() { + return referenceScheme().unmarked(this); + } + + @INLINE + public final byte readByte(Offset offset) { + return referenceScheme().readByte(this, offset); + } + + @INLINE + public final byte readByte(int offset) { + return referenceScheme().readByte(this, offset); + } + + @INLINE + public final byte getByte(int displacement, int index) { + return referenceScheme().getByte(this, displacement, index); + } + + @INLINE + public final boolean readBoolean(Offset offset) { + return referenceScheme().readBoolean(this, offset); + } + + @INLINE + public final boolean readBoolean(int offset) { + return referenceScheme().readBoolean(this, offset); + } + + @INLINE + public final boolean getBoolean(int displacement, int index) { + return referenceScheme().getBoolean(this, displacement, index); + } + + @INLINE + public final short readShort(Offset offset) { + return referenceScheme().readShort(this, offset); + } + + @INLINE + public final short readShort(int offset) { + return referenceScheme().readShort(this, offset); + } + + @INLINE + public final short getShort(int displacement, int index) { + return referenceScheme().getShort(this, displacement, index); + } + + @INLINE + public final char readChar(Offset offset) { + return referenceScheme().readChar(this, offset); + } + + @INLINE + public final char readChar(int offset) { + return referenceScheme().readChar(this, offset); + } + + @INLINE + public final char getChar(int displacement, int index) { + return referenceScheme().getChar(this, displacement, index); + } + + @INLINE + public final int readInt(Offset offset) { + return referenceScheme().readInt(this, offset); + } + + @INLINE + public final int readInt(int offset) { + return referenceScheme().readInt(this, offset); + } + + @INLINE + public final int getInt(int displacement, int index) { + return referenceScheme().getInt(this, displacement, index); + } + + @INLINE + public final float readFloat(Offset offset) { + return referenceScheme().readFloat(this, offset); + } + + @INLINE + public final float readFloat(int offset) { + return referenceScheme().readFloat(this, offset); + } + + @INLINE + public final float getFloat(int displacement, int index) { + return referenceScheme().getFloat(this, displacement, index); + } + + @INLINE + public final long readLong(Offset offset) { + return referenceScheme().readLong(this, offset); + } + + @INLINE + public final long readLong(int offset) { + return referenceScheme().readLong(this, offset); + } + + @INLINE + public final long getLong(int displacement, int index) { + return referenceScheme().getLong(this, displacement, index); + } + + @INLINE + public final double readDouble(Offset offset) { + return referenceScheme().readDouble(this, offset); + } + + @INLINE + public final double readDouble(int offset) { + return referenceScheme().readDouble(this, offset); + } + + @INLINE + public final double getDouble(int displacement, int index) { + return referenceScheme().getDouble(this, displacement, index); + } + + @INLINE + public final Word readWord(Offset offset) { + return referenceScheme().readWord(this, offset); + } + + @INLINE + public final Word readWord(int offset) { + return referenceScheme().readWord(this, offset); + } + + @INLINE + public final Word getWord(int displacement, int index) { + return referenceScheme().getWord(this, displacement, index); + } + + @INLINE + public final Reference readReference(Offset offset) { + return referenceScheme().readReference(this, offset); + } + + @INLINE + public final Reference readReference(int offset) { + return referenceScheme().readReference(this, offset); + } + + @INLINE + public final Reference getReference(int displacement, int index) { + return referenceScheme().getReference(this, displacement, index); + } + + @INLINE + public final void writeByte(Offset offset, byte value) { + referenceScheme().writeByte(this, offset, value); + } + + @INLINE + public final void writeByte(int offset, byte value) { + referenceScheme().writeByte(this, offset, value); + } + + @INLINE + public final void setByte(int displacement, int index, byte value) { + referenceScheme().setByte(this, displacement, index, value); + } + + @INLINE + public final void writeBoolean(Offset offset, boolean value) { + referenceScheme().writeBoolean(this, offset, value); + } + + @INLINE + public final void writeBoolean(int offset, boolean value) { + referenceScheme().writeBoolean(this, offset, value); + } + + @INLINE + public final void setBoolean(int displacement, int index, boolean value) { + referenceScheme().setBoolean(this, displacement, index, value); + } + + @INLINE + public final void writeShort(Offset offset, short value) { + referenceScheme().writeShort(this, offset, value); + } + + @INLINE + public final void writeShort(int offset, short value) { + referenceScheme().writeShort(this, offset, value); + } + + @INLINE + public final void setShort(int displacement, int index, short value) { + referenceScheme().setShort(this, displacement, index, value); + } + + @INLINE + public final void writeChar(Offset offset, char value) { + referenceScheme().writeChar(this, offset, value); + } + + @INLINE + public final void writeChar(int offset, char value) { + referenceScheme().writeChar(this, offset, value); + } + + @INLINE + public final void setChar(int displacement, int index, char value) { + referenceScheme().setChar(this, displacement, index, value); + } + + @INLINE + public final void writeInt(Offset offset, int value) { + referenceScheme().writeInt(this, offset, value); + } + + @INLINE + public final void writeInt(int offset, int value) { + referenceScheme().writeInt(this, offset, value); + } + + @INLINE + public final void setInt(int displacement, int index, int value) { + referenceScheme().setInt(this, displacement, index, value); + } + + @INLINE + public final void writeFloat(Offset offset, float value) { + referenceScheme().writeFloat(this, offset, value); + } + + @INLINE + public final void writeFloat(int offset, float value) { + referenceScheme().writeFloat(this, offset, value); + } + + @INLINE + public final void setFloat(int displacement, int index, float value) { + referenceScheme().setFloat(this, displacement, index, value); + } + + @INLINE + public final void writeLong(Offset offset, long value) { + referenceScheme().writeLong(this, offset, value); + } + + @INLINE + public final void writeLong(int offset, long value) { + referenceScheme().writeLong(this, offset, value); + } + + @INLINE + public final void setLong(int displacement, int index, long value) { + referenceScheme().setLong(this, displacement, index, value); + } + + @INLINE + public final void writeDouble(Offset offset, double value) { + referenceScheme().writeDouble(this, offset, value); + } + + @INLINE + public final void writeDouble(int offset, double value) { + referenceScheme().writeDouble(this, offset, value); + } + + @INLINE + public final void setDouble(int displacement, int index, double value) { + referenceScheme().setDouble(this, displacement, index, value); + } + + @INLINE + public final void writeWord(Offset offset, Word value) { + referenceScheme().writeWord(this, offset, value); + } + + @INLINE + public final void writeWord(int offset, Word value) { + referenceScheme().writeWord(this, offset, value); + } + + @INLINE + public final void setWord(int displacement, int index, Word value) { + referenceScheme().setWord(this, displacement, index, value); + } + + @INLINE + public final void writeReference(Offset offset, Reference value) { + referenceScheme().writeReference(this, offset, value); + } + + @INLINE + public final void writeReference(int offset, Reference value) { + referenceScheme().writeReference(this, offset, value); + } + + @INLINE + public final void setReference(int displacement, int index, Reference value) { + referenceScheme().setReference(this, displacement, index, value); + } + + /** + * Atomically compares the contents of a memory location to a given value and, if they are the same, modifies the + * contents of that memory location to a given new value. + * + * @param offset the offset from this reference of the memory location to be tested and potentially updated + * @param expectedValue the value that must currently exist in the memory location for the update to occur + * @param newValue the value to which the memory is updated if its current value is {@code expectedValue} + * @return the value of the memory location before this call; if it is equal to {@code expectedValue}, then the + * update occurred, otherwise the update did not occur (assuming {@code expectedValue != newValue}) + */ + @INLINE + public final int compareAndSwapInt(Offset offset, int expectedValue, int newValue) { + return referenceScheme().compareAndSwapInt(this, offset, expectedValue, newValue); + } + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + @INLINE + public final int compareAndSwapInt(int offset, int expectedValue, int newValue) { + return referenceScheme().compareAndSwapInt(this, offset, expectedValue, newValue); + } + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + @INLINE + public final Word compareAndSwapWord(Offset offset, Word expectedValue, Word newValue) { + return referenceScheme().compareAndSwapWord(this, offset, expectedValue, newValue); + } + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + @INLINE + public final Word compareAndSwapWord(int offset, Word expectedValue, Word newValue) { + return referenceScheme().compareAndSwapWord(this, offset, expectedValue, newValue); + } + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + @INLINE + public final Reference compareAndSwapReference(Offset offset, Reference expectedValue, Reference newValue) { + return referenceScheme().compareAndSwapReference(this, offset, expectedValue, newValue); + } + + /** + * @see #compareAndSwapInt(Offset, int, int) + */ + @INLINE + public final Reference compareAndSwapReference(int offset, Reference expectedValue, Reference newValue) { + return referenceScheme().compareAndSwapReference(this, offset, expectedValue, newValue); + } + + @INLINE + public final void copyElements(int displacement, int srcIndex, Object dst, int dstIndex, int length) { + referenceScheme().copyElements(displacement, this, displacement, dst, dstIndex, length); + } +} diff --git a/JavaInJava/src/com/sun/max/vm/reference/ReferenceScheme.java b/JavaInJava/src/com/sun/max/vm/reference/ReferenceScheme.java new file mode 100644 index 0000000..2f9c9d2 --- /dev/null +++ b/JavaInJava/src/com/sun/max/vm/reference/ReferenceScheme.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.vm.reference; + +import com.sun.max.unsafe.*; +import com.sun.max.vm.*; + +/** + * Reference-based object access methods for mutator use. + * + * A "reference" is a runtime value of type 'java.lang.Object'. + * It can be stored in fields and array elements of other objects. + * The mutator refers to objects and parts thereof by using references. + * + * @author Bernd Mathiske + */ +public interface ReferenceScheme extends VMScheme { + + Reference fromOrigin(Pointer origin); + + Reference fromJava(Object object); + + Object toJava(Reference reference); + Pointer toOrigin(Reference reference); + + /** + * @return the "zero" ref that represents 'null'. + */ + Reference zero(); + + boolean isZero(Reference ref); + + boolean isAllOnes(Reference ref); + + boolean isMarked(Reference ref); + + Reference marked(Reference ref); + + Reference unmarked(Reference ref); + + byte readByte(Reference reference, Offset offset); + byte readByte(Reference reference, int offset); + byte getByte(Reference reference, int displacement, int index); + + boolean readBoolean(Reference reference, Offset offset); + boolean readBoolean(Reference reference, int offset); + boolean getBoolean(Reference reference, int displacement, int index); + + short readShort(Reference reference, Offset offset); + short readShort(Reference reference, int offset); + short getShort(Reference reference, int displacement, int index); + + char readChar(Reference reference, Offset offset); + char readChar(Reference reference, int offset); + char getChar(Reference reference, int displacement, int index); + + int readInt(Reference reference, Offset offset); + int readInt(Reference reference, int offset); + int getInt(Reference reference, int displacement, int index); + + float readFloat(Reference reference, Offset offset); + float readFloat(Reference reference, int offset); + float getFloat(Reference reference, int displacement, int index); + + long readLong(Reference reference, Offset offset); + long readLong(Reference reference, int offset); + long getLong(Reference reference, int displacement, int index); + + double readDouble(Reference reference, Offset offset); + double readDouble(Reference reference, int offset); + double getDouble(Reference reference, int displacement, int index); + + Word readWord(Reference reference, Offset offset); + Word readWord(Reference reference, int offset); + Word getWord(Reference reference, int displacement, int index); + + Reference readReference(Reference reference, Offset offset); + Reference readReference(Reference reference, int offset); + Reference getReference(Reference reference, int displacement, int index); + + void writeByte(Reference reference, Offset offset, byte value); + void writeByte(Reference reference, int offset, byte value); + void setByte(Reference reference, int displacement, int index, byte value); + + void writeBoolean(Reference reference, Offset offset, boolean value); + void writeBoolean(Reference reference, int offset, boolean value); + void setBoolean(Reference reference, int displacement, int index, boolean value); + + void writeShort(Reference reference, Offset offset, short value); + void writeShort(Reference reference, int offset, short value); + void setShort(Reference reference, int displacement, int index, short value); + + void writeChar(Reference reference, Offset offset, char value); + void writeChar(Reference reference, int offset, char value); + void setChar(Reference reference, int displacement, int index, char value); + + void writeInt(Reference reference, Offset offset, int value); + void writeInt(Reference reference, int offset, int value); + void setInt(Reference reference, int displacement, int index, int value); + + void writeFloat(Reference reference, Offset offset, float value); + void writeFloat(Reference reference, int offset, float value); + void setFloat(Reference reference, int displacement, int index, float value); + + void writeLong(Reference reference, Offset offset, long value); + void writeLong(Reference reference, int offset, long value); + void setLong(Reference reference, int displacement, int index, long value); + + void writeDouble(Reference reference, Offset offset, double value); + void writeDouble(Reference reference, int offset, double value); + void setDouble(Reference reference, int displacement, int index, double value); + + void writeWord(Reference reference, Offset offset, Word value); + void writeWord(Reference reference, int offset, Word value); + void setWord(Reference reference, int displacement, int index, Word value); + + void writeReference(Reference reference, Offset offset, Reference value); + void writeReference(Reference reference, int offset, Reference value); + void setReference(Reference reference, int displacement, int index, Reference value); + + /** + * Atomically compares the contents of the memory location addressed by adding {@code offset} to {@code reference} + * to a given value and, if they are the same, modifies the contents of that memory location to a given new value. + * + * @param reference the base of the memory location + * @param offset the offset of the memory location + * @param expectedValue the value that must currently exist in the memory location for the update to occur + * @param newValue the value to which the memory is updated if its current value is {@code expectedValue} + * @return the value of the memory location before this call; if it is equal to {@code expectedValue}, then the + * update occurred, otherwise the update did not occur (assuming {@code expectedValue != newValue}) + */ + int compareAndSwapInt(Reference reference, Offset offset, int expectedValue, int newValue); + + /** + * @see #compareAndSwapInt(Reference, Offset, int, int) + */ + int compareAndSwapInt(Reference reference, int offset, int expectedValue, int newValue); + + /** + * @see #compareAndSwapInt(Reference, Offset, int, int) + */ + Word compareAndSwapWord(Reference reference, Offset offset, Word expectedValue, Word newValue); + + /** + * @see #compareAndSwapInt(Reference, Offset, int, int) + */ + Word compareAndSwapWord(Reference reference, int offset, Word expectedValue, Word newValue); + + Reference compareAndSwapReference(Reference reference, Offset offset, Reference expectedValue, Reference newValue); + Reference compareAndSwapReference(Reference reference, int offset, Reference expectedValue, Reference newValue); + + void copyElements(int displacement, Reference src, int srcIndex, Object dst, int dstIndex, int length); +} diff --git a/JavaInJava/src/com/sun/max/vm/reference/package-info.java b/JavaInJava/src/com/sun/max/vm/reference/package-info.java new file mode 100644 index 0000000..950319d --- /dev/null +++ b/JavaInJava/src/com/sun/max/vm/reference/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * Object reference specifications and operations. + * + * @author Bernd Mathiske + */ +package com.sun.max.vm.reference;