Permalink
Browse files

preliminary support for using OpenJDK's class library

Whereas the GNU Classpath port used the strategy of patching Classpath
with core classes from Avian so as to minimize changes to the VM, this
port uses the opposite strategy: abstract and isolate
classpath-specific features in the VM similar to how we abstract away
platform-specific features in system.h.  This allows us to use an
unmodified copy of OpenJDK's class library, including its core classes
and augmented by a few VM-specific classes in the "avian" package.
  • Loading branch information...
1 parent 17c1a55 commit cddea7187d1886a521abbec719691d4fda8135d8 @dicej dicej committed Sep 10, 2010
@@ -12,5 +12,5 @@
public class Addendum {
public Object pool;
- public Object annotationTable;
+ public Object annotationTable;
}
@@ -0,0 +1,268 @@
+/* Copyright (c) 2010, Avian Contributors
+
+ Permission to use, copy, modify, and/or distribute this software
+ for any purpose with or without fee is hereby granted, provided
+ that the above copyright notice and this permission notice appear
+ in all copies.
+
+ There is NO WARRANTY for this software. See license.txt for
+ details. */
+
+package avian;
+
+import static avian.Stream.read1;
+import static avian.Stream.read2;
+
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+public class Classes {
+ private static final int LinkFlag = 1 << 8;
+
+ public static native VMClass defineVMClass
+ (ClassLoader loader, byte[] b, int offset, int length);
+
+ public static native VMClass vmClass(Object o);
+
+ public static native VMClass primitiveClass(char name);
+
+ public static native void initialize(VMClass vmClass);
+
+ public static native boolean isAssignableFrom(VMClass a, VMClass b);
+
+ public static native VMClass getVMClass(Object o);
+
+ private static native VMClass resolveVMClass(ClassLoader loader, byte[] spec)
+ throws ClassNotFoundException;
+
+ private static VMClass loadVMClass(ClassLoader loader,
+ byte[] nameBytes, int offset, int length)
+ {
+ byte[] spec = new byte[length + 1];
+ System.arraycopy(nameBytes, offset, spec, 0, length);
+
+ try {
+ VMClass c = resolveVMClass(loader, spec);
+ if (c == null) {
+ throw new NoClassDefFoundError();
+ }
+ return c;
+ } catch (ClassNotFoundException e) {
+ NoClassDefFoundError error = new NoClassDefFoundError
+ (new String(nameBytes, offset, length, false));
+ error.initCause(e);
+ throw error;
+ }
+ }
+
+ private static Object parseAnnotationValue(ClassLoader loader,
+ Object pool,
+ InputStream in)
+ throws IOException
+ {
+ switch (read1(in)) {
+ case 'Z':
+ return Boolean.valueOf(Singleton.getInt(pool, read2(in) - 1) != 0);
+
+ case 'B':
+ return Byte.valueOf((byte) Singleton.getInt(pool, read2(in) - 1));
+
+ case 'C':
+ return Character.valueOf((char) Singleton.getInt(pool, read2(in) - 1));
+
+ case 'S':
+ return Short.valueOf((short) Singleton.getInt(pool, read2(in) - 1));
+
+ case 'I':
+ return Integer.valueOf(Singleton.getInt(pool, read2(in) - 1));
+
+ case 'F':
+ return Float.valueOf
+ (Float.intBitsToFloat(Singleton.getInt(pool, read2(in) - 1)));
+
+ case 'J': {
+ return Long.valueOf(Singleton.getLong(pool, read2(in) - 1));
+ }
+
+ case 'D': {
+ return Double.valueOf
+ (Double.longBitsToDouble(Singleton.getLong(pool, read2(in) - 1)));
+ }
+
+ case 's': {
+ byte[] data = (byte[]) Singleton.getObject(pool, read2(in) - 1);
+
+ return new String(data, 0, data.length - 1, false);
+ }
+
+ case 'e': {
+ byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
+ byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
+
+ return Enum.valueOf
+ (getClass(loadVMClass(loader, typeName, 1, typeName.length - 3)),
+ new String(name, 0, name.length - 1, false));
+ }
+
+ case 'c':{
+ byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
+
+ return getClass(loadVMClass(loader, name, 1, name.length - 3));
+ }
+
+ case '@':
+ return parseAnnotation(loader, pool, in);
+
+ case '[': {
+ Object[] array = new Object[read2(in)];
+ for (int i = 0; i < array.length; ++i) {
+ array[i] = parseAnnotationValue(loader, pool, in);
+ }
+ return array;
+ }
+
+ default: throw new AssertionError();
+ }
+ }
+
+ private static Object[] parseAnnotation(ClassLoader loader,
+ Object pool,
+ InputStream in)
+ throws IOException
+ {
+ byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
+ Object[] annotation = new Object[(read2(in) + 1) * 2];
+ annotation[1] = getClass
+ (loadVMClass(loader, typeName, 1, typeName.length - 3));
+
+ for (int i = 2; i < annotation.length; i += 2) {
+ byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
+ annotation[i] = new String(name, 0, name.length - 1, false);
+ annotation[i + 1] = parseAnnotationValue(loader, pool, in);
+ }
+
+ return annotation;
+ }
+
+ private static Object[] parseAnnotationTable(ClassLoader loader,
+ Object pool,
+ InputStream in)
+ throws IOException
+ {
+ Object[] table = new Object[read2(in)];
+ for (int i = 0; i < table.length; ++i) {
+ table[i] = parseAnnotation(loader, pool, in);
+ }
+ return table;
+ }
+
+ private static void parseAnnotationTable(ClassLoader loader,
+ Addendum addendum)
+ {
+ if (addendum != null && addendum.annotationTable instanceof byte[]) {
+ try {
+ addendum.annotationTable = parseAnnotationTable
+ (loader, addendum.pool, new ByteArrayInputStream
+ ((byte[]) addendum.annotationTable));
+ } catch (IOException e) {
+ AssertionError error = new AssertionError();
+ error.initCause(e);
+ throw error;
+ }
+ }
+ }
+
+ private static int resolveSpec(ClassLoader loader, byte[] spec, int start) {
+ int result;
+ int end;
+ switch (spec[start]) {
+ case 'L':
+ ++ start;
+ end = start;
+ while (spec[end] != ';') ++ end;
+ result = end + 1;
+ break;
+
+ case '[':
+ end = start + 1;
+ while (spec[end] == '[') ++ end;
+ switch (spec[end]) {
+ case 'L':
+ ++ end;
+ while (spec[end] != ';') ++ end;
+ ++ end;
+ break;
+
+ default:
+ ++ end;
+ }
+ result = end;
+ break;
+
+ default:
+ return start + 1;
+ }
+
+ loadVMClass(loader, spec, start, end - start);
+
+ return result;
+ }
+
+ public static void link(VMClass c, ClassLoader loader) {
+ acquireClassLock();
+ try {
+ if ((c.vmFlags & LinkFlag) == 0) {
+ if (c.super_ != null) {
+ link(c.super_, loader);
+ }
+
+ parseAnnotationTable(loader, c.addendum);
+
+ if (c.interfaceTable != null) {
+ int stride = ((c.flags & Modifier.INTERFACE) != 0 ? 1 : 2);
+ for (int i = 0; i < c.interfaceTable.length; i += stride) {
+ link((VMClass) c.interfaceTable[i], loader);
+ }
+ }
+
+ if (c.methodTable != null) {
+ for (int i = 0; i < c.methodTable.length; ++i) {
+ VMMethod m = c.methodTable[i];
+
+ for (int j = 1; j < m.spec.length;) {
+ j = resolveSpec(loader, m.spec, j);
+ }
+
+ parseAnnotationTable(loader, m.addendum);
+ }
+ }
+
+ if (c.fieldTable != null) {
+ for (int i = 0; i < c.fieldTable.length; ++i) {
+ VMField f = c.fieldTable[i];
+
+ resolveSpec(loader, f.spec, 0);
+
+ parseAnnotationTable(loader, f.addendum);
+ }
+ }
+
+ c.vmFlags |= LinkFlag;
+ }
+ } finally {
+ releaseClassLock();
+ }
+ }
+
+ public static void link(VMClass c) {
+ link(c, c.loader);
+ }
+
+ private static native void acquireClassLock();
+
+ private static native void releaseClassLock();
+}
@@ -0,0 +1,13 @@
+/* Copyright (c) 2010, Avian Contributors
+
+ Permission to use, copy, modify, and/or distribute this software
+ for any purpose with or without fee is hereby granted, provided
+ that the above copyright notice and this permission notice appear
+ in all copies.
+
+ There is NO WARRANTY for this software. See license.txt for
+ details. */
+
+package avian;
+
+public class FieldAddendum extends Addendum { }
@@ -0,0 +1,15 @@
+/* Copyright (c) 2009-2010, Avian Contributors
+
+ Permission to use, copy, modify, and/or distribute this software
+ for any purpose with or without fee is hereby granted, provided
+ that the above copyright notice and this permission notice appear
+ in all copies.
+
+ There is NO WARRANTY for this software. See license.txt for
+ details. */
+
+package avian;
+
+public class MethodAddendum extends Addendum {
+ public Object exceptionTable;
+}
Oops, something went wrong.

0 comments on commit cddea71

Please sign in to comment.