break each Class, Field, and Method into separate classes

In order to facilitate making the VM compatible with multiple class
libraries, it's useful to separate the VM-specific representation of
these classes from the library implementations.  This commit
introduces VMClass, VMField, and VMMethod for that purpose.
This commit is contained in:
Joel Dice 2010-09-01 10:13:52 -06:00
parent 4273ff834c
commit 17c1a552d5
21 changed files with 547 additions and 348 deletions

View File

@ -11,5 +11,6 @@
package avian;
public class ClassAddendum extends Addendum {
public volatile Class class_;
public Object[] signers;
}

View File

@ -13,6 +13,7 @@ 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.net.URL;
@ -24,16 +25,26 @@ import java.io.IOException;
public class SystemClassLoader extends ClassLoader {
private static final int LinkFlag = 1 << 8;
public static native Class defineClass
public static native VMClass defineVMClass
(ClassLoader loader, byte[] b, int offset, int length);
protected native Class findClass(String name) throws ClassNotFoundException;
private static native VMClass findVMClass(String name)
throws ClassNotFoundException;
protected native Class reallyFindLoadedClass(String name);
protected Class findClass(String name) throws ClassNotFoundException {
return getClass(findVMClass(name));
}
private native boolean resourceExists(String name);
private static native VMClass findLoadedVMClass(String name);
private static native Class resolveClass(ClassLoader loader, byte[] spec)
protected Class reallyFindLoadedClass(String name){
VMClass c = findLoadedVMClass(name);
return c == null ? null : getClass(c);
}
private static native boolean resourceExists(String name);
private static native VMClass resolveVMClass(ClassLoader loader, byte[] spec)
throws ClassNotFoundException;
protected URL findResource(String name) {
@ -45,14 +56,14 @@ public class SystemClassLoader extends ClassLoader {
return null;
}
private static Class loadClass(ClassLoader loader,
byte[] nameBytes, int offset, int length)
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 {
Class c = resolveClass(loader, spec);
VMClass c = resolveVMClass(loader, spec);
if (c == null) {
throw new NoClassDefFoundError();
}
@ -110,14 +121,14 @@ public class SystemClassLoader extends ClassLoader {
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
return Enum.valueOf
(loadClass(loader, typeName, 1, typeName.length - 3),
(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 loadClass(loader, name, 1, name.length - 3);
return getClass(loadVMClass(loader, name, 1, name.length - 3));
}
case '@':
@ -142,7 +153,8 @@ public class SystemClassLoader extends ClassLoader {
{
byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
Object[] annotation = new Object[(read2(in) + 1) * 2];
annotation[1] = loadClass(loader, typeName, 1, typeName.length - 3);
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);
@ -214,7 +226,7 @@ public class SystemClassLoader extends ClassLoader {
return start + 1;
}
loadClass(loader, spec, start, end - start);
loadVMClass(loader, spec, start, end - start);
return result;
}
@ -223,7 +235,35 @@ public class SystemClassLoader extends ClassLoader {
private static native void releaseClassLock();
public static void link(Class c, ClassLoader loader) {
public static Class getClass(VMClass vmClass) {
if (vmClass.addendum == null) {
SystemClassLoader.acquireClassLock();
try {
if (vmClass.addendum == null) {
vmClass.addendum = new ClassAddendum();
}
} finally {
SystemClassLoader.releaseClassLock();
}
}
if (vmClass.addendum.class_ == null) {
SystemClassLoader.acquireClassLock();
try {
if (vmClass.addendum.class_ == null) {
vmClass.addendum.class_ = new Class(vmClass);
}
} finally {
SystemClassLoader.releaseClassLock();
}
}
return vmClass.addendum.class_;
}
public static native VMClass getVMClass(Object o);
public static void link(VMClass c, ClassLoader loader) {
acquireClassLock();
try {
if ((c.vmFlags & LinkFlag) == 0) {
@ -234,15 +274,15 @@ public class SystemClassLoader extends ClassLoader {
parseAnnotationTable(loader, c.addendum);
if (c.interfaceTable != null) {
int stride = (c.isInterface() ? 1 : 2);
int stride = ((c.flags & Modifier.INTERFACE) != 0 ? 1 : 2);
for (int i = 0; i < c.interfaceTable.length; i += stride) {
link((Class) c.interfaceTable[i], loader);
link((VMClass) c.interfaceTable[i], loader);
}
}
if (c.methodTable != null) {
for (int i = 0; i < c.methodTable.length; ++i) {
Method m = c.methodTable[i];
VMMethod m = c.methodTable[i];
for (int j = 1; j < m.spec.length;) {
j = resolveSpec(loader, m.spec, j);
@ -254,7 +294,7 @@ public class SystemClassLoader extends ClassLoader {
if (c.fieldTable != null) {
for (int i = 0; i < c.fieldTable.length; ++i) {
Field f = c.fieldTable[i];
VMField f = c.fieldTable[i];
resolveSpec(loader, f.spec, 0);
@ -269,7 +309,7 @@ public class SystemClassLoader extends ClassLoader {
}
}
public static void link(Class c) {
link(c, c.getClassLoader());
public static void link(VMClass c) {
link(c, c.loader);
}
}

View File

@ -0,0 +1,30 @@
/* Copyright (c) 2008-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 VMClass {
public short flags;
public short vmFlags;
public short fixedSize;
public byte arrayElementSize;
public byte arrayDimensions;
public int[] objectMask;
public byte[] name;
public byte[] sourceFile;
public VMClass super_;
public Object[] interfaceTable;
public VMMethod[] virtualTable;
public VMField[] fieldTable;
public VMMethod[] methodTable;
public volatile avian.ClassAddendum addendum;
public Object staticTable;
public ClassLoader loader;
}

View File

@ -0,0 +1,22 @@
/* Copyright (c) 2008-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 VMField {
public byte vmFlags;
public byte code;
public short flags;
public short offset;
public byte[] name;
public byte[] spec;
public avian.Addendum addendum;
public VMClass class_;
}

View File

@ -0,0 +1,26 @@
/* Copyright (c) 2008-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 VMMethod {
public byte vmFlags;
public byte returnCode;
public byte parameterCount;
public byte parameterFootprint;
public short flags;
public short offset;
public int nativeID;
public byte[] name;
public byte[] spec;
public avian.Addendum addendum;
public VMClass class_;
public Object code;
}

View File

@ -10,7 +10,10 @@
package java.lang;
import avian.VMClass;
import avian.ClassAddendum;
import avian.AnnotationInvocationHandler;
import avian.SystemClassLoader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@ -38,24 +41,13 @@ public final class Class <T>
{
private static final int PrimitiveFlag = 1 << 5;
private short flags;
public short vmFlags;
private short fixedSize;
private byte arrayElementSize;
private byte arrayDimensions;
private int[] objectMask;
private byte[] name;
private byte[] sourceFile;
public Class super_;
public Object[] interfaceTable;
public Method[] virtualTable;
public Field[] fieldTable;
public Method[] methodTable;
public avian.ClassAddendum addendum;
private Object staticTable;
private ClassLoader loader;
public final VMClass vmClass;
private Class() { }
public Class(VMClass vmClass) {
this.vmClass = vmClass;
}
public static native VMClass vmClass(Object o);
public String toString() {
return getName();
@ -73,26 +65,30 @@ public final class Class <T>
}
public String getName() {
if (name == null) {
if ((vmFlags & PrimitiveFlag) != 0) {
if (this == primitiveClass('V')) {
name = "void\0".getBytes();
} else if (this == primitiveClass('Z')) {
name = "boolean\0".getBytes();
} else if (this == primitiveClass('B')) {
name = "byte\0".getBytes();
} else if (this == primitiveClass('C')) {
name = "char\0".getBytes();
} else if (this == primitiveClass('S')) {
name = "short\0".getBytes();
} else if (this == primitiveClass('I')) {
name = "int\0".getBytes();
} else if (this == primitiveClass('F')) {
name = "float\0".getBytes();
} else if (this == primitiveClass('J')) {
name = "long\0".getBytes();
} else if (this == primitiveClass('D')) {
name = "double\0".getBytes();
return getName(vmClass);
}
public static String getName(VMClass c) {
if (c.name == null) {
if ((c.vmFlags & PrimitiveFlag) != 0) {
if (c == primitiveClass('V')) {
c.name = "void\0".getBytes();
} else if (c == primitiveClass('Z')) {
c.name = "boolean\0".getBytes();
} else if (c == primitiveClass('B')) {
c.name = "byte\0".getBytes();
} else if (c == primitiveClass('C')) {
c.name = "char\0".getBytes();
} else if (c == primitiveClass('S')) {
c.name = "short\0".getBytes();
} else if (c == primitiveClass('I')) {
c.name = "int\0".getBytes();
} else if (c == primitiveClass('F')) {
c.name = "float\0".getBytes();
} else if (c == primitiveClass('J')) {
c.name = "long\0".getBytes();
} else if (c == primitiveClass('D')) {
c.name = "double\0".getBytes();
} else {
throw new AssertionError();
}
@ -102,11 +98,12 @@ public final class Class <T>
}
return new String
(replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false);
(replace('/', '.', c.name, 0, c.name.length - 1), 0, c.name.length - 1,
false);
}
public String getCanonicalName() {
if ((vmFlags & PrimitiveFlag) != 0) {
if ((vmClass.vmFlags & PrimitiveFlag) != 0) {
return getName();
} else if (isArray()) {
return getComponentType().getCanonicalName() + "[]";
@ -116,7 +113,7 @@ public final class Class <T>
}
public String getSimpleName() {
if ((vmFlags & PrimitiveFlag) != 0) {
if ((vmClass.vmFlags & PrimitiveFlag) != 0) {
return getName();
} else if (isArray()) {
return getComponentType().getSimpleName() + "[]";
@ -131,10 +128,6 @@ public final class Class <T>
}
}
public Object staticTable() {
return staticTable;
}
public T newInstance()
throws IllegalAccessException, InstantiationException
{
@ -148,8 +141,7 @@ public final class Class <T>
}
public static Class forName(String name) throws ClassNotFoundException {
return forName
(name, true, Method.getCaller().getDeclaringClass().getClassLoader());
return forName(name, true, Method.getCaller().class_.loader);
}
public static Class forName(String name, boolean initialize,
@ -157,19 +149,19 @@ public final class Class <T>
throws ClassNotFoundException
{
if (loader == null) {
loader = Class.class.loader;
loader = Class.class.vmClass.loader;
}
Class c = loader.loadClass(name);
avian.SystemClassLoader.link(c, loader);
SystemClassLoader.link(c.vmClass, loader);
if (initialize) {
c.initialize();
initialize(c.vmClass);
}
return c;
}
private static native Class primitiveClass(char name);
private static native VMClass primitiveClass(char name);
private native void initialize();
private static native void initialize(VMClass vmClass);
public static Class forCanonicalName(String name) {
return forCanonicalName(null, name);
@ -183,7 +175,7 @@ public final class Class <T>
return forName(name.substring(1, name.length() - 1), true, loader);
} else {
if (name.length() == 1) {
return primitiveClass(name.charAt(0));
return SystemClassLoader.getClass(primitiveClass(name.charAt(0)));
} else {
throw new ClassNotFoundException(name);
}
@ -197,39 +189,43 @@ public final class Class <T>
if (isArray()) {
String n = getName();
if ("[Z".equals(n)) {
return primitiveClass('Z');
return SystemClassLoader.getClass(primitiveClass('Z'));
} else if ("[B".equals(n)) {
return primitiveClass('B');
return SystemClassLoader.getClass(primitiveClass('B'));
} else if ("[S".equals(n)) {
return primitiveClass('S');
return SystemClassLoader.getClass(primitiveClass('S'));
} else if ("[C".equals(n)) {
return primitiveClass('C');
return SystemClassLoader.getClass(primitiveClass('C'));
} else if ("[I".equals(n)) {
return primitiveClass('I');
return SystemClassLoader.getClass(primitiveClass('I'));
} else if ("[F".equals(n)) {
return primitiveClass('F');
return SystemClassLoader.getClass(primitiveClass('F'));
} else if ("[J".equals(n)) {
return primitiveClass('J');
return SystemClassLoader.getClass(primitiveClass('J'));
} else if ("[D".equals(n)) {
return primitiveClass('D');
return SystemClassLoader.getClass(primitiveClass('D'));
}
if (staticTable == null) throw new AssertionError(name);
return (Class) staticTable;
if (vmClass.staticTable == null) throw new AssertionError();
return SystemClassLoader.getClass((VMClass) vmClass.staticTable);
} else {
return null;
}
}
public native boolean isAssignableFrom(Class c);
public static native boolean isAssignableFrom(VMClass a, VMClass b);
private Field findField(String name) {
if (fieldTable != null) {
avian.SystemClassLoader.link(this);
public boolean isAssignableFrom(Class c) {
return isAssignableFrom(vmClass, c.vmClass);
}
for (int i = 0; i < fieldTable.length; ++i) {
if (fieldTable[i].getName().equals(name)) {
return fieldTable[i];
private static Field findField(VMClass vmClass, String name) {
if (vmClass.fieldTable != null) {
SystemClassLoader.link(vmClass);
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
if (Field.getName(vmClass.fieldTable[i]).equals(name)) {
return new Field(vmClass.fieldTable[i]);
}
}
}
@ -237,7 +233,7 @@ public final class Class <T>
}
public Field getDeclaredField(String name) throws NoSuchFieldException {
Field f = findField(name);
Field f = findField(vmClass, name);
if (f == null) {
throw new NoSuchFieldException(name);
} else {
@ -246,8 +242,8 @@ public final class Class <T>
}
public Field getField(String name) throws NoSuchFieldException {
for (Class c = this; c != null; c = c.super_) {
Field f = c.findField(name);
for (VMClass c = vmClass; c != null; c = c.super_) {
Field f = findField(c, name);
if (f != null) {
return f;
}
@ -268,19 +264,22 @@ public final class Class <T>
}
}
private Method findMethod(String name, Class[] parameterTypes) {
if (methodTable != null) {
avian.SystemClassLoader.link(this);
private static Method findMethod(VMClass vmClass, String name,
Class[] parameterTypes)
{
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
if (parameterTypes == null) {
parameterTypes = new Class[0];
}
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals(name)
&& match(parameterTypes, methodTable[i].getParameterTypes()))
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (Method.getName(vmClass.methodTable[i]).equals(name)
&& match(parameterTypes,
Method.getParameterTypes(vmClass.methodTable[i])))
{
return methodTable[i];
return new Method(vmClass.methodTable[i]);
}
}
}
@ -293,7 +292,7 @@ public final class Class <T>
if (name.startsWith("<")) {
throw new NoSuchMethodException(name);
}
Method m = findMethod(name, parameterTypes);
Method m = findMethod(vmClass, name, parameterTypes);
if (m == null) {
throw new NoSuchMethodException(name);
} else {
@ -307,8 +306,8 @@ public final class Class <T>
if (name.startsWith("<")) {
throw new NoSuchMethodException(name);
}
for (Class c = this; c != null; c = c.super_) {
Method m = c.findMethod(name, parameterTypes);
for (VMClass c = vmClass; c != null; c = c.super_) {
Method m = findMethod(c, name, parameterTypes);
if (m != null) {
return m;
}
@ -319,7 +318,7 @@ public final class Class <T>
public Constructor getConstructor(Class ... parameterTypes)
throws NoSuchMethodException
{
Method m = findMethod("<init>", parameterTypes);
Method m = findMethod(vmClass, "<init>", parameterTypes);
if (m == null) {
throw new NoSuchMethodException();
} else {
@ -348,11 +347,12 @@ public final class Class <T>
private int countConstructors(boolean publicOnly) {
int count = 0;
if (methodTable != null) {
for (int i = 0; i < methodTable.length; ++i) {
if (vmClass.methodTable != null) {
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (((! publicOnly)
|| ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0)
&& methodTable[i].getName().equals("<init>"))
|| ((vmClass.methodTable[i].flags & Modifier.PUBLIC))
!= 0)
&& Method.getName(vmClass.methodTable[i]).equals("<init>"))
{
++ count;
}
@ -363,13 +363,13 @@ public final class Class <T>
public Constructor[] getDeclaredConstructors() {
Constructor[] array = new Constructor[countConstructors(false)];
if (methodTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals("<init>")) {
array[index++] = new Constructor(methodTable[i]);
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (Method.getName(vmClass.methodTable[i]).equals("<init>")) {
array[index++] = new Constructor(new Method(vmClass.methodTable[i]));
}
}
}
@ -379,15 +379,15 @@ public final class Class <T>
public Constructor[] getConstructors() {
Constructor[] array = new Constructor[countConstructors(true)];
if (methodTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
&& methodTable[i].getName().equals("<init>"))
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (((vmClass.methodTable[i].flags & Modifier.PUBLIC) != 0)
&& Method.getName(vmClass.methodTable[i]).equals("<init>"))
{
array[index++] = new Constructor(methodTable[i]);
array[index++] = new Constructor(new Method(vmClass.methodTable[i]));
}
}
}
@ -396,9 +396,11 @@ public final class Class <T>
}
public Field[] getDeclaredFields() {
if (fieldTable != null) {
Field[] array = new Field[fieldTable.length];
System.arraycopy(fieldTable, 0, array, 0, fieldTable.length);
if (vmClass.fieldTable != null) {
Field[] array = new Field[vmClass.fieldTable.length];
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
array[i] = new Field(vmClass.fieldTable[i]);
}
return array;
} else {
return new Field[0];
@ -407,9 +409,9 @@ public final class Class <T>
private int countPublicFields() {
int count = 0;
if (fieldTable != null) {
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
if (vmClass.fieldTable != null) {
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC)) != 0) {
++ count;
}
}
@ -419,13 +421,13 @@ public final class Class <T>
public Field[] getFields() {
Field[] array = new Field[countPublicFields()];
if (fieldTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.fieldTable != null) {
SystemClassLoader.link(vmClass);
int ai = 0;
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
array[ai++] = fieldTable[i];
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC)) != 0) {
array[ai++] = new Field(vmClass.fieldTable[i]);
}
}
}
@ -434,11 +436,12 @@ public final class Class <T>
private int countMethods(boolean publicOnly) {
int count = 0;
if (methodTable != null) {
for (int i = 0; i < methodTable.length; ++i) {
if (vmClass.methodTable != null) {
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (((! publicOnly)
|| ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0)
&& (! methodTable[i].getName().startsWith("<")))
|| ((vmClass.methodTable[i].flags & Modifier.PUBLIC))
!= 0)
&& (! Method.getName(vmClass.methodTable[i]).startsWith("<")))
{
++ count;
}
@ -449,13 +452,13 @@ public final class Class <T>
public Method[] getDeclaredMethods() {
Method[] array = new Method[countMethods(false)];
if (methodTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
int ai = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (! methodTable[i].getName().startsWith("<")) {
array[ai++] = methodTable[i];
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (! Method.getName(vmClass.methodTable[i]).startsWith("<")) {
array[ai++] = new Method(vmClass.methodTable[i]);
}
}
}
@ -465,15 +468,15 @@ public final class Class <T>
public Method[] getMethods() {
Method[] array = new Method[countMethods(true)];
if (methodTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
&& (! methodTable[i].getName().startsWith("<")))
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (((vmClass.methodTable[i].flags & Modifier.PUBLIC) != 0)
&& (! Method.getName(vmClass.methodTable[i]).startsWith("<")))
{
array[index++] = methodTable[i];
array[index++] = new Method(vmClass.methodTable[i]);
}
}
}
@ -482,13 +485,14 @@ public final class Class <T>
}
public Class[] getInterfaces() {
if (interfaceTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.interfaceTable != null) {
SystemClassLoader.link(vmClass);
int stride = (isInterface() ? 1 : 2);
Class[] array = new Class[interfaceTable.length / stride];
Class[] array = new Class[vmClass.interfaceTable.length / stride];
for (int i = 0; i < array.length; ++i) {
array[i] = (Class) interfaceTable[i * stride];
array[i] = SystemClassLoader.getClass
((VMClass) vmClass.interfaceTable[i * stride]);
}
return array;
} else {
@ -509,36 +513,41 @@ public final class Class <T>
}
public ClassLoader getClassLoader() {
return loader;
return vmClass.loader;
}
public int getModifiers() {
return flags;
return vmClass.flags;
}
public boolean isInterface() {
return (flags & Modifier.INTERFACE) != 0;
return (vmClass.flags & Modifier.INTERFACE) != 0;
}
public Class getSuperclass() {
return super_;
return SystemClassLoader.getClass(vmClass.super_);
}
public boolean isArray() {
return arrayDimensions != 0;
return vmClass.arrayDimensions != 0;
}
public static boolean isInstance(VMClass c, Object o) {
return o != null && isAssignableFrom(c, SystemClassLoader.getVMClass(o));
}
public boolean isInstance(Object o) {
return o != null && isAssignableFrom(o.getClass());
return isInstance(vmClass, o);
}
public boolean isPrimitive() {
return (vmFlags & PrimitiveFlag) != 0;
return (vmClass.vmFlags & PrimitiveFlag) != 0;
}
public URL getResource(String path) {
if (! path.startsWith("/")) {
String name = new String(this.name, 0, this.name.length - 1, false);
String name = new String
(vmClass.name, 0, vmClass.name.length - 1, false);
int index = name.lastIndexOf('/');
if (index >= 0) {
path = name.substring(0, index) + "/" + path;
@ -573,11 +582,11 @@ public final class Class <T>
}
public Object[] getSigners() {
return addendum == null ? null : addendum.signers;
return vmClass.addendum.signers;
}
public Package getPackage() {
if ((vmFlags & PrimitiveFlag) != 0 || isArray()) {
if ((vmClass.vmFlags & PrimitiveFlag) != 0 || isArray()) {
return null;
} else {
String name = getCanonicalName();
@ -597,25 +606,25 @@ public final class Class <T>
return getAnnotation(class_) != null;
}
private Annotation getAnnotation(Object[] a) {
private static Annotation getAnnotation(VMClass c, Object[] a) {
if (a[0] == null) {
a[0] = Proxy.newProxyInstance
(loader, new Class[] { (Class) a[1] },
(c.loader, new Class[] { (Class) a[1] },
new AnnotationInvocationHandler(a));
}
return (Annotation) a[0];
}
public <T extends Annotation> T getAnnotation(Class<T> class_) {
for (Class c = this; c != null; c = c.super_) {
for (VMClass c = vmClass; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
avian.SystemClassLoader.link(c, c.loader);
SystemClassLoader.link(c, c.loader);
Object[] table = (Object[]) c.addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
Object[] a = (Object[]) table[i];
if (a[1] == class_) {
return (T) c.getAnnotation(a);
return (T) getAnnotation(c, a);
}
}
}
@ -624,13 +633,13 @@ public final class Class <T>
}
public Annotation[] getDeclaredAnnotations() {
if (addendum != null && addendum.annotationTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.addendum.annotationTable != null) {
SystemClassLoader.link(vmClass);
Object[] table = (Object[]) addendum.annotationTable;
Object[] table = (Object[]) vmClass.addendum.annotationTable;
Annotation[] array = new Annotation[table.length];
for (int i = 0; i < table.length; ++i) {
array[i] = getAnnotation((Object[]) table[i]);
array[i] = getAnnotation(vmClass, (Object[]) table[i]);
}
return array;
} else {
@ -640,7 +649,7 @@ public final class Class <T>
private int countAnnotations() {
int count = 0;
for (Class c = this; c != null; c = c.super_) {
for (VMClass c = vmClass; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
count += ((Object[]) c.addendum.annotationTable).length;
}
@ -651,11 +660,11 @@ public final class Class <T>
public Annotation[] getAnnotations() {
Annotation[] array = new Annotation[countMethods(true)];
int i = 0;
for (Class c = this; c != null; c = c.super_) {
for (VMClass c = vmClass; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
Object[] table = (Object[]) c.addendum.annotationTable;
for (int j = 0; j < table.length; ++j) {
array[i++] = getAnnotation((Object[]) table[j]);
array[i++] = getAnnotation(vmClass, (Object[]) table[j]);
}
}
}
@ -692,14 +701,4 @@ public final class Class <T>
p.add(new AllPermission());
return new ProtectionDomain(null, p);
}
// for GNU Classpath compatibility:
void setSigners(Object[] signers) {
if (signers != null && signers.length > 0) {
if (addendum == null) {
addendum = new avian.ClassAddendum();
}
addendum.signers = signers;
}
}
}

View File

@ -46,7 +46,8 @@ public abstract class ClassLoader {
throw new IndexOutOfBoundsException();
}
return avian.SystemClassLoader.defineClass(this, b, offset, length);
return avian.SystemClassLoader.getClass
(avian.SystemClassLoader.defineVMClass(this, b, offset, length));
}
protected Class findClass(String name) throws ClassNotFoundException {
@ -87,7 +88,7 @@ public abstract class ClassLoader {
}
protected void resolveClass(Class c) {
avian.SystemClassLoader.link(c, this);
avian.SystemClassLoader.link(c.vmClass, this);
}
private ClassLoader getParent() {

View File

@ -27,7 +27,11 @@ public class Object {
protected void finalize() throws Throwable { }
public native final Class<? extends Object> getClass();
public final Class<? extends Object> getClass() {
return avian.SystemClassLoader.getClass(getVMClass(this));
}
private static native avian.VMClass getVMClass(Object o);
public native int hashCode();

View File

@ -78,13 +78,13 @@ public class Constructor<T> extends AccessibleObject
return method.getGenericParameterTypes();
}
private static native <T> T make(Class<T> c);
private static native Object make(avian.VMClass c);
public T newInstance(Object ... arguments)
throws InvocationTargetException, InstantiationException,
IllegalAccessException
{
T v = make(method.getDeclaringClass());
T v = (T) make(method.getDeclaringClass().vmClass);
method.invoke(v, arguments);
return v;
}

View File

@ -10,7 +10,9 @@
package java.lang.reflect;
import avian.VMField;
import avian.AnnotationInvocationHandler;
import avian.SystemClassLoader;
import java.lang.annotation.Annotation;
@ -26,81 +28,90 @@ public class Field<T> extends AccessibleObject {
private static final int BooleanField = 8;
private static final int ObjectField = 9;
private byte vmFlags;
private byte code;
private short flags;
private short offset;
private byte[] name;
public byte[] spec;
public avian.Addendum addendum;
private Class<T> class_;
private final VMField vmField;
private boolean accessible = true;
private Field() { }
public Field(VMField vmField) {
this.vmField = vmField;
}
public boolean isAccessible() {
return (vmFlags & Accessible) != 0;
return accessible;
}
public void setAccessible(boolean v) {
if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible;
accessible = v;
}
public Class<T> getDeclaringClass() {
return class_;
return SystemClassLoader.getClass(vmField.class_);
}
public int getModifiers() {
return flags;
return vmField.flags;
}
public String getName() {
return new String(name, 0, name.length - 1, false);
return getName(vmField);
}
public static String getName(VMField vmField) {
return new String(vmField.name, 0, vmField.name.length - 1, false);
}
public Class getType() {
return Class.forCanonicalName(class_.getClassLoader(),
new String(spec, 0, spec.length - 1, false));
return Class.forCanonicalName
(vmField.class_.loader,
new String(vmField.spec, 0, vmField.spec.length - 1, false));
}
public Object get(Object instance) throws IllegalAccessException {
Object target;
if ((flags & Modifier.STATIC) != 0) {
target = class_.staticTable();
} else if (class_.isInstance(instance)) {
if ((vmField.flags & Modifier.STATIC) != 0) {
target = vmField.class_.staticTable;
} else if (Class.isInstance(vmField.class_, instance)) {
target = instance;
} else {
throw new IllegalArgumentException();
}
switch (code) {
switch (vmField.code) {
case ByteField:
return Byte.valueOf((byte) getPrimitive(target, code, offset));
return Byte.valueOf
((byte) getPrimitive(target, vmField.code, vmField.offset));
case BooleanField:
return Boolean.valueOf(getPrimitive(target, code, offset) != 0);
return Boolean.valueOf
(getPrimitive(target, vmField.code, vmField.offset) != 0);
case CharField:
return Character.valueOf((char) getPrimitive(target, code, offset));
return Character.valueOf
((char) getPrimitive(target, vmField.code, vmField.offset));
case ShortField:
return Short.valueOf((short) getPrimitive(target, code, offset));
return Short.valueOf
((short) getPrimitive(target, vmField.code, vmField.offset));
case IntField:
return Integer.valueOf((int) getPrimitive(target, code, offset));
return Integer.valueOf
((int) getPrimitive(target, vmField.code, vmField.offset));
case LongField:
return Long.valueOf((int) getPrimitive(target, code, offset));
return Long.valueOf
((int) getPrimitive(target, vmField.code, vmField.offset));
case FloatField:
return Float.valueOf
(Float.intBitsToFloat((int) getPrimitive(target, code, offset)));
(Float.intBitsToFloat
((int) getPrimitive(target, vmField.code, vmField.offset)));
case DoubleField:
return Double.valueOf
(Double.longBitsToDouble(getPrimitive(target, code, offset)));
(Double.longBitsToDouble
(getPrimitive(target, vmField.code, vmField.offset)));
case ObjectField:
return getObject(target, offset);
return getObject(target, vmField.offset);
default:
throw new Error();
@ -143,56 +154,58 @@ public class Field<T> extends AccessibleObject {
throws IllegalAccessException
{
Object target;
if ((flags & Modifier.STATIC) != 0) {
target = class_.staticTable();
} else if (class_.isInstance(instance)) {
if ((vmField.flags & Modifier.STATIC) != 0) {
target = vmField.class_.staticTable;
} else if (Class.isInstance(vmField.class_, instance)) {
target = instance;
} else {
throw new IllegalArgumentException();
}
switch (code) {
switch (vmField.code) {
case ByteField:
setPrimitive(target, code, offset, (Byte) value);
setPrimitive(target, vmField.code, vmField.offset, (Byte) value);
break;
case BooleanField:
setPrimitive(target, code, offset, ((Boolean) value) ? 1 : 0);
setPrimitive
(target, vmField.code, vmField.offset, ((Boolean) value) ? 1 : 0);
break;
case CharField:
setPrimitive(target, code, offset, (Character) value);
setPrimitive(target, vmField.code, vmField.offset, (Character) value);
break;
case ShortField:
setPrimitive(target, code, offset, (Short) value);
setPrimitive(target, vmField.code, vmField.offset, (Short) value);
break;
case IntField:
setPrimitive(target, code, offset, (Integer) value);
setPrimitive(target, vmField.code, vmField.offset, (Integer) value);
break;
case LongField:
setPrimitive(target, code, offset, (Long) value);
setPrimitive(target, vmField.code, vmField.offset, (Long) value);
break;
case FloatField:
setPrimitive(target, code, offset,
setPrimitive(target, vmField.code, vmField.offset,
Float.floatToRawIntBits((Float) value));
break;
case DoubleField:
setPrimitive(target, code, offset,
setPrimitive(target, vmField.code, vmField.offset,
Double.doubleToRawLongBits((Double) value));
break;
case ObjectField:
if (value == null || getType().isInstance(value)) {
setObject(target, offset, value);
setObject(target, vmField.offset, value);
} else {
throw new IllegalArgumentException
("needed " + getType() + ", got " + value.getClass().getName() +
" when setting " + class_.getName() + "." + getName());
("needed " + getType() + ", got "
+ Class.getName(Class.vmClass(target)) +
" when setting " + Class.getName(vmField.class_) + "." + getName());
}
break;
@ -204,15 +217,15 @@ public class Field<T> extends AccessibleObject {
private Annotation getAnnotation(Object[] a) {
if (a[0] == null) {
a[0] = Proxy.newProxyInstance
(class_.getClassLoader(), new Class[] { (Class) a[1] },
(vmField.class_.loader, new Class[] { (Class) a[1] },
new AnnotationInvocationHandler(a));
}
return (Annotation) a[0];
}
public <T extends Annotation> T getAnnotation(Class<T> class_) {
if (addendum != null && addendum.annotationTable != null) {
Object[] table = (Object[]) addendum.annotationTable;
if (vmField.addendum.annotationTable != null) {
Object[] table = (Object[]) vmField.addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
Object[] a = (Object[]) table[i];
if (a[1] == class_) {
@ -224,8 +237,8 @@ public class Field<T> extends AccessibleObject {
}
public Annotation[] getAnnotations() {
if (addendum != null && addendum.annotationTable != null) {
Object[] table = (Object[]) addendum.annotationTable;
if (vmField.addendum.annotationTable != null) {
Object[] table = (Object[]) vmField.addendum.annotationTable;
Annotation[] array = new Annotation[table.length];
for (int i = 0; i < table.length; ++i) {
array[i] = getAnnotation((Object[]) table[i]);
@ -255,9 +268,4 @@ public class Field<T> extends AccessibleObject {
private static native void setObject
(Object instance, int offset, Object value);
public static class Addendum {
public Object pool;
public Object annotationTable;
}
}

View File

@ -10,53 +10,54 @@
package java.lang.reflect;
import avian.VMMethod;
import avian.AnnotationInvocationHandler;
import avian.SystemClassLoader;
import java.lang.annotation.Annotation;
public class Method<T> extends AccessibleObject
implements Member, GenericDeclaration
{
private byte vmFlags;
private byte returnCode;
public byte parameterCount;
public byte parameterFootprint;
private short flags;
private short offset;
private int nativeID;
private byte[] name;
public byte[] spec;
public avian.Addendum addendum;
private Class<T> class_;
private Object code;
private long compiled;
private final VMMethod vmMethod;
private boolean accessible;
private Method() { }
public Method(VMMethod vmMethod) {
this.vmMethod = vmMethod;
}
public boolean isAccessible() {
return (vmFlags & Accessible) != 0;
return accessible;
}
public void setAccessible(boolean v) {
if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible;
accessible = v;
}
public static native Method getCaller();
public static native VMMethod getCaller();
public Class<T> getDeclaringClass() {
return class_;
return SystemClassLoader.getClass(vmMethod.class_);
}
public int getModifiers() {
return flags;
return vmMethod.flags;
}
public String getName() {
return new String(name, 0, name.length - 1, false);
return getName(vmMethod);
}
String getSpec() {
return new String(spec, 0, spec.length - 1, false);
public static String getName(VMMethod vmMethod) {
return new String(vmMethod.name, 0, vmMethod.name.length - 1, false);
}
private String getSpec() {
return getSpec(vmMethod);
}
public static String getSpec(VMMethod vmMethod) {
return new String(vmMethod.spec, 0, vmMethod.spec.length - 1, false);
}
private static int next(char c, String s, int start) {
@ -67,12 +68,17 @@ public class Method<T> extends AccessibleObject
}
public Class[] getParameterTypes() {
int count = parameterCount;
return getParameterTypes(vmMethod);
}
public static Class[] getParameterTypes(VMMethod vmMethod) {
int count = vmMethod.parameterCount;
Class[] types = new Class[count];
int index = 0;
String spec = new String(this.spec, 1, this.spec.length - 1, false);
String spec = new String
(vmMethod.spec, 1, vmMethod.spec.length - 1, false);
try {
for (int i = 0; i < spec.length(); ++i) {
@ -83,7 +89,7 @@ public class Method<T> extends AccessibleObject
int start = i + 1;
i = next(';', spec, start);
String name = spec.substring(start, i).replace('/', '.');
types[index++] = Class.forName(name, true, class_.getClassLoader());
types[index++] = Class.forName(name, true, vmMethod.class_.loader);
} else if (c == '[') {
int start = i;
while (spec.charAt(i) == '[') ++i;
@ -92,16 +98,16 @@ public class Method<T> extends AccessibleObject
i = next(';', spec, i + 1);
String name = spec.substring(start, i).replace('/', '.');
types[index++] = Class.forName
(name, true, class_.getClassLoader());
(name, true, vmMethod.class_.loader);
} else {
String name = spec.substring(start, i + 1);
types[index++] = Class.forCanonicalName
(class_.getClassLoader(), name);
(vmMethod.class_.loader, name);
}
} else {
String name = spec.substring(i, i + 1);
types[index++] = Class.forCanonicalName
(class_.getClassLoader(), name);
(vmMethod.class_.loader, name);
}
}
} catch (ClassNotFoundException e) {
@ -114,38 +120,43 @@ public class Method<T> extends AccessibleObject
public Object invoke(Object instance, Object ... arguments)
throws InvocationTargetException, IllegalAccessException
{
if ((flags & Modifier.STATIC) != 0 || class_.isInstance(instance)) {
if ((flags & Modifier.STATIC) != 0) {
if ((vmMethod.flags & Modifier.STATIC) != 0
|| Class.isInstance(vmMethod.class_, instance))
{
if ((vmMethod.flags & Modifier.STATIC) != 0) {
instance = null;
}
if (arguments == null) {
if (parameterCount > 0) {
if (vmMethod.parameterCount > 0) {
throw new NullPointerException();
}
arguments = new Object[0];
}
if (arguments.length == parameterCount) {
return invoke(this, instance, arguments);
if (arguments.length == vmMethod.parameterCount) {
return invoke(vmMethod, instance, arguments);
} else {
throw new ArrayIndexOutOfBoundsException();
}
} else {
// System.out.println
// (getDeclaringClass() + "." + getName() + " flags: " + vmMethod.flags + " vm flags: " + vmMethod.vmFlags + " return code: " + vmMethod.returnCode);
throw new IllegalArgumentException();
}
}
private static native Object invoke(Method method, Object instance,
private static native Object invoke(VMMethod method, Object instance,
Object ... arguments)
throws InvocationTargetException, IllegalAccessException;
public Class getReturnType() {
for (int i = 0; i < spec.length - 1; ++i) {
if (spec[i] == ')') {
for (int i = 0; i < vmMethod.spec.length - 1; ++i) {
if (vmMethod.spec[i] == ')') {
return Class.forCanonicalName
(class_.getClassLoader(),
new String(spec, i + 1, spec.length - i - 2, false));
(vmMethod.class_.loader,
new String
(vmMethod.spec, i + 1, vmMethod.spec.length - i - 2, false));
}
}
throw new RuntimeException();
@ -154,15 +165,15 @@ public class Method<T> extends AccessibleObject
private Annotation getAnnotation(Object[] a) {
if (a[0] == null) {
a[0] = Proxy.newProxyInstance
(class_.getClassLoader(), new Class[] { (Class) a[1] },
(vmMethod.class_.loader, new Class[] { (Class) a[1] },
new AnnotationInvocationHandler(a));
}
return (Annotation) a[0];
}
public <T extends Annotation> T getAnnotation(Class<T> class_) {
if (addendum != null && addendum.annotationTable != null) {
Object[] table = (Object[]) addendum.annotationTable;
if (vmMethod.addendum.annotationTable != null) {
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
Object[] a = (Object[]) table[i];
if (a[1] == class_) {
@ -174,8 +185,8 @@ public class Method<T> extends AccessibleObject
}
public Annotation[] getAnnotations() {
if (addendum != null && addendum.annotationTable != null) {
Object[] table = (Object[]) addendum.annotationTable;
if (vmMethod.addendum.annotationTable != null) {
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
Annotation[] array = new Annotation[table.length];
for (int i = 0; i < table.length; ++i) {
array[i] = getAnnotation((Object[]) table[i]);

View File

@ -45,12 +45,14 @@ public class Proxy {
private static final int getfield = 0xb4;
private static final int iload = 0x15;
private static final int invokeinterface = 0xb9;
private static final int invokespecial = 0xb7;
private static final int invokestatic = 0xb8;
private static final int invokevirtual = 0xb6;
private static final int ireturn = 0xac;
private static final int ldc_w = 0x13;
private static final int lload = 0x16;
private static final int lreturn = 0xad;
private static final int new_ = 0xbb;
private static final int pop = 0x57;
private static final int putfield = 0xb5;
private static final int return_ = 0xb1;
@ -172,15 +174,26 @@ public class Proxy {
write1(out, aload_0);
write1(out, new_);
write2(out, poolAddClass(pool, "java/lang/reflect/Method") + 1);
write1(out, dup);
write1(out, ldc_w);
write2(out, poolAddClass(pool, className) + 1);
write1(out, getfield);
write2(out, poolAddFieldRef
(pool, "java/lang/Class",
"methodTable", "[Ljava/lang/reflect/Method;") + 1);
"vmClass", "Lavian/VMClass;") + 1);
write1(out, getfield);
write2(out, poolAddFieldRef
(pool, "avian/VMClass",
"methodTable", "[Lavian/VMMethod;") + 1);
write1(out, ldc_w);
write2(out, poolAddInteger(pool, index) + 1);
write1(out, aaload);
write1(out, invokespecial);
write2(out, poolAddMethodRef
(pool, "java/lang/reflect/Method",
"<init>", "(Lavian/VMMethod;)V") + 1);
write1(out, ldc_w);
write2(out, poolAddInteger(pool, parameterCount) + 1);
@ -434,22 +447,22 @@ public class Proxy {
interfaceIndexes[i] = poolAddClass(pool, interfaces[i].getName());
}
Map<String,Method> virtualMap = new HashMap();
Map<String,avian.VMMethod> virtualMap = new HashMap();
for (Class c: interfaces) {
Method[] ivtable = c.virtualTable;
avian.VMMethod[] ivtable = c.vmClass.virtualTable;
if (ivtable != null) {
for (Method m: ivtable) {
virtualMap.put(m.getName() + m.getSpec(), m);
for (avian.VMMethod m: ivtable) {
virtualMap.put(Method.getName(m) + Method.getSpec(m), m);
}
}
}
MethodData[] methodTable = new MethodData[virtualMap.size() + 1];
{ int i = 0;
for (Method m: virtualMap.values()) {
for (avian.VMMethod m: virtualMap.values()) {
methodTable[i] = new MethodData
(poolAddUtf8(pool, m.getName()),
poolAddUtf8(pool, m.getSpec()),
(poolAddUtf8(pool, Method.getName(m)),
poolAddUtf8(pool, Method.getSpec(m)),
makeInvokeCode(pool, name, m.spec, m.parameterCount,
m.parameterFootprint, i));
++ i;
@ -501,8 +514,9 @@ public class Proxy {
write2(out, 0); // attribute count
byte[] classData = out.toByteArray();
return avian.SystemClassLoader.defineClass
(loader, classData, 0, classData.length);
return avian.SystemClassLoader.getClass
(avian.SystemClassLoader.defineVMClass
(loader, classData, 0, classData.length));
}
public static Object newProxyInstance(ClassLoader loader,

View File

@ -94,13 +94,12 @@ public abstract class ResourceBundle {
}
public static ResourceBundle getBundle(String name, Locale locale) {
return getBundle(name, locale,
Method.getCaller().getDeclaringClass().getClassLoader());
return getBundle(name, locale, Method.getCaller().class_.loader);
}
public static ResourceBundle getBundle(String name) {
return getBundle(name, Locale.getDefault(),
Method.getCaller().getDeclaringClass().getClassLoader());
return getBundle
(name, Locale.getDefault(), Method.getCaller().class_.loader);
}
public Object getObject(String key) {

View File

@ -107,15 +107,15 @@ public class Logger {
return logger.getLevel();
}
private void log(Level level, Method caller, String message,
private void log(Level level, avian.VMMethod caller, String message,
Throwable exception) {
if (level.intValue() < getEffectiveLevel().intValue()) {
return;
}
LogRecord r = new LogRecord
(name, caller == null ? "<unknown>" : caller.getName(), level, message,
exception);
(name, caller == null ? "<unknown>" : Method.getName(caller), level,
message, exception);
publish(r);
}

View File

@ -97,12 +97,12 @@ Avian_java_lang_Object_toString
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Object_getClass
Avian_java_lang_Object_getVMClass
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
object o = reinterpret_cast<object>(arguments[0]);
return reinterpret_cast<int64_t>(objectClass(t, this_));
return reinterpret_cast<int64_t>(objectClass(t, o));
}
extern "C" JNIEXPORT void JNICALL
@ -183,7 +183,15 @@ Avian_avian_SystemClassLoader_releaseClassLock
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_defineClass
Avian_avian_SystemClassLoader_getVMClass
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(objectClass(t, reinterpret_cast<object>(arguments[0])));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_defineVMClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
@ -214,25 +222,25 @@ Avian_avian_SystemClassLoader_defineClass
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_reallyFindLoadedClass
Avian_avian_SystemClassLoader_findLoadedVMClass
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[1]);
object name = reinterpret_cast<object>(arguments[0]);
return search(t, name, findLoadedSystemClass, true);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findClass
Avian_avian_SystemClassLoader_findVMClass
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[1]);
object name = reinterpret_cast<object>(arguments[0]);
return search(t, name, resolveSystemClass, true);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_resolveClass
Avian_avian_SystemClassLoader_resolveVMClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
@ -245,7 +253,7 @@ extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_resourceExists
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[1]);
object name = reinterpret_cast<object>(arguments[0]);
if (LIKELY(name)) {
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);

View File

@ -4370,7 +4370,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
frame->pushObject(frame->append(class_));
frame->pushObject(frame->append(getJClass(t, class_)));
} else if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ClassType))
{
frame->pushObject(frame->append(getJClass(t, v)));
} else {
frame->pushObject(frame->append(v));
}
@ -6160,9 +6164,6 @@ invokeNativeSlow(MyThread* t, object method)
{
PROTECT(t, method);
object class_ = methodClass(t, method);
PROTECT(t, class_);
unsigned footprint = methodParameterFootprint(t, method) + 1;
if (methodFlags(t, method) & ACC_STATIC) {
++ footprint;
@ -6181,9 +6182,13 @@ invokeNativeSlow(MyThread* t, object method)
+ t->arch->frameFooterSize()
+ t->arch->frameReturnAddressSize();
object jclass = 0;
PROTECT(t, jclass);
if (methodFlags(t, method) & ACC_STATIC) {
jclass = getJClass(t, methodClass(t, method));
RUNTIME_ARRAY_BODY(args)[argOffset++]
= reinterpret_cast<uintptr_t>(&class_);
= reinterpret_cast<uintptr_t>(&jclass);
} else {
RUNTIME_ARRAY_BODY(args)[argOffset++]
= reinterpret_cast<uintptr_t>(sp++);

View File

@ -2224,7 +2224,11 @@ interpret(Thread* t)
(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
pushObject(t, class_);
pushObject(t, getJClass(t, class_));
} else if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ClassType))
{
pushObject(t, getJClass(t, v));
} else {
pushObject(t, v);
}

View File

@ -248,7 +248,9 @@ FindClass(Thread* t, const char* name)
object n = makeByteArray(t, strlen(name) + 1);
replace('.', '/', name, &byteArrayBody(t, n, 0));
return makeLocalReference(t, resolveClass(t, t->m->loader, n));
object c = resolveClass(t, t->m->loader, n);
return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c));
}
jint JNICALL
@ -270,7 +272,7 @@ ThrowNew(Thread* t, jclass c, const char* message)
object trace = makeTrace(t);
PROTECT(t, trace);
t->exception = make(t, *c);
t->exception = make(t, jclassVmClass(t, *c));
set(t, t->exception, ThrowableMessage, m);
set(t, t->exception, ThrowableTrace, trace);
@ -316,7 +318,7 @@ GetObjectClass(Thread* t, jobject o)
{
ENTER(t, Thread::ActiveState);
return makeLocalReference(t, objectClass(t, *o));
return makeLocalReference(t, getJClass(t, objectClass(t, *o)));
}
jboolean JNICALL
@ -324,7 +326,7 @@ IsInstanceOf(Thread* t, jobject o, jclass c)
{
ENTER(t, Thread::ActiveState);
return instanceOf(t, *c, *o);
return instanceOf(t, jclassVmClass(t, *c), *o);
}
object
@ -334,7 +336,7 @@ findMethod(Thread* t, jclass c, const char* name, const char* spec)
PROTECT(t, n);
object s = makeByteArray(t, "%s", spec);
return vm::findMethod(t, *c, n, s);
return vm::findMethod(t, jclassVmClass(t, *c), n, s);
}
jint
@ -395,7 +397,7 @@ NewObjectV(Thread* t, jclass c, jmethodID m, va_list a)
{
ENTER(t, Thread::ActiveState);
object o = make(t, *c);
object o = make(t, jclassVmClass(t, *c));
PROTECT(t, o);
t->m->processor->invokeList(t, getMethod(t, m), o, true, a);
@ -875,7 +877,7 @@ GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
{
ENTER(t, Thread::ActiveState);
object field = resolveField(t, *c, name, spec);
object field = resolveField(t, jclassVmClass(t, *c), name, spec);
if (UNLIKELY(t->exception)) return 0;
return fieldOffset(t, field);
@ -886,7 +888,7 @@ GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec)
{
ENTER(t, Thread::ActiveState);
object field = resolveField(t, *c, name, spec);
object field = resolveField(t, jclassVmClass(t, *c), name, spec);
if (UNLIKELY(t->exception)) return 0;
return fieldOffset(t, field);
@ -1041,7 +1043,8 @@ GetStaticObjectField(Thread* t, jclass c, jfieldID field)
{
ENTER(t, Thread::ActiveState);
return makeLocalReference(t, cast<object>(classStaticTable(t, *c), field));
return makeLocalReference
(t, cast<object>(classStaticTable(t, jclassVmClass(t, *c)), field));
}
jboolean JNICALL
@ -1049,7 +1052,7 @@ GetStaticBooleanField(Thread* t, jclass c, jfieldID field)
{
ENTER(t, Thread::ActiveState);
return cast<int8_t>(classStaticTable(t, *c), field);
return cast<int8_t>(classStaticTable(t, jclassVmClass(t, *c)), field);
}
jbyte JNICALL
@ -1057,7 +1060,7 @@ GetStaticByteField(Thread* t, jclass c, jfieldID field)
{
ENTER(t, Thread::ActiveState);
return cast<int8_t>(classStaticTable(t, *c), field);
return cast<int8_t>(classStaticTable(t, jclassVmClass(t, *c)), field);
}
jchar JNICALL
@ -1065,7 +1068,7 @@ GetStaticCharField(Thread* t, jclass c, jfieldID field)
{
ENTER(t, Thread::ActiveState);
return cast<uint16_t>(classStaticTable(t, *c), field);
return cast<uint16_t>(classStaticTable(t, jclassVmClass(t, *c)), field);
}
jshort JNICALL
@ -1073,7 +1076,7 @@ GetStaticShortField(Thread* t, jclass c, jfieldID field)
{
ENTER(t, Thread::ActiveState);
return cast<int16_t>(classStaticTable(t, *c), field);
return cast<int16_t>(classStaticTable(t, jclassVmClass(t, *c)), field);
}
jint JNICALL
@ -1081,7 +1084,7 @@ GetStaticIntField(Thread* t, jclass c, jfieldID field)
{
ENTER(t, Thread::ActiveState);
return cast<int32_t>(classStaticTable(t, *c), field);
return cast<int32_t>(classStaticTable(t, jclassVmClass(t, *c)), field);
}
jlong JNICALL
@ -1089,7 +1092,7 @@ GetStaticLongField(Thread* t, jclass c, jfieldID field)
{
ENTER(t, Thread::ActiveState);
return cast<int64_t>(classStaticTable(t, *c), field);
return cast<int64_t>(classStaticTable(t, jclassVmClass(t, *c)), field);
}
jfloat JNICALL
@ -1097,7 +1100,7 @@ GetStaticFloatField(Thread* t, jclass c, jfieldID field)
{
ENTER(t, Thread::ActiveState);
return cast<float>(classStaticTable(t, *c), field);
return cast<float>(classStaticTable(t, jclassVmClass(t, *c)), field);
}
jdouble JNICALL
@ -1105,7 +1108,7 @@ GetStaticDoubleField(Thread* t, jclass c, jfieldID field)
{
ENTER(t, Thread::ActiveState);
return cast<double>(classStaticTable(t, *c), field);
return cast<double>(classStaticTable(t, jclassVmClass(t, *c)), field);
}
void JNICALL
@ -1121,7 +1124,7 @@ SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v)
{
ENTER(t, Thread::ActiveState);
cast<int8_t>(classStaticTable(t, *c), field) = v;
cast<int8_t>(classStaticTable(t, jclassVmClass(t, *c)), field) = v;
}
void JNICALL
@ -1129,7 +1132,7 @@ SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v)
{
ENTER(t, Thread::ActiveState);
cast<int8_t>(classStaticTable(t, *c), field) = v;
cast<int8_t>(classStaticTable(t, jclassVmClass(t, *c)), field) = v;
}
void JNICALL
@ -1137,7 +1140,7 @@ SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v)
{
ENTER(t, Thread::ActiveState);
cast<uint16_t>(classStaticTable(t, *c), field) = v;
cast<uint16_t>(classStaticTable(t, jclassVmClass(t, *c)), field) = v;
}
void JNICALL
@ -1145,7 +1148,7 @@ SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v)
{
ENTER(t, Thread::ActiveState);
cast<int16_t>(classStaticTable(t, *c), field) = v;
cast<int16_t>(classStaticTable(t, jclassVmClass(t, *c)), field) = v;
}
void JNICALL
@ -1153,7 +1156,7 @@ SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v)
{
ENTER(t, Thread::ActiveState);
cast<int32_t>(classStaticTable(t, *c), field) = v;
cast<int32_t>(classStaticTable(t, jclassVmClass(t, *c)), field) = v;
}
void JNICALL
@ -1161,7 +1164,7 @@ SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v)
{
ENTER(t, Thread::ActiveState);
cast<int64_t>(classStaticTable(t, *c), field) = v;
cast<int64_t>(classStaticTable(t, jclassVmClass(t, *c)), field) = v;
}
void JNICALL
@ -1169,7 +1172,7 @@ SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v)
{
ENTER(t, Thread::ActiveState);
cast<float>(classStaticTable(t, *c), field) = v;
cast<float>(classStaticTable(t, jclassVmClass(t, *c)), field) = v;
}
void JNICALL
@ -1177,7 +1180,7 @@ SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v)
{
ENTER(t, Thread::ActiveState);
cast<double>(classStaticTable(t, *c), field) = v;
cast<double>(classStaticTable(t, jclassVmClass(t, *c)), field) = v;
}
jobject JNICALL
@ -1248,7 +1251,9 @@ NewObjectArray(Thread* t, jsize length, jclass class_, jobject init)
{
ENTER(t, Thread::ActiveState);
object a = makeObjectArray(t, classLoader(t, *class_), *class_, length);
object a = makeObjectArray
(t, classLoader(t, jclassVmClass(t, *class_)), jclassVmClass(t, *class_),
length);
object value = (init ? *init : 0);
for (jsize i = 0; i < length; ++i) {
set(t, a, ArrayBody + (i * BytesPerWord), value);

View File

@ -1627,7 +1627,7 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool)
object body = makeByteArray(t, length);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)), length);
object addendum = makeClassAddendum(t, pool, body, 0);
object addendum = makeClassAddendum(t, pool, body, 0, 0);
set(t, class_, ClassAddendum, addendum);
} else {

View File

@ -3000,6 +3000,29 @@ resolveMethod(Thread* t, object method, unsigned index)
(t, classLoader(t, methodClass(t, method)), method, index);
}
inline object
getJClass(Thread* t, object c)
{
if (classAddendum(t, c) == 0) {
ACQUIRE(t, t->m->classLock);
object addendum = makeClassAddendum(t, 0, 0, 0, 0);
set(t, c, ClassAddendum, addendum);
}
object jclass = classAddendumClass(t, classAddendum(t, c));
if (jclass == 0) {
ACQUIRE(t, t->m->classLock);
jclass = makeJclass(t, c);
set(t, classAddendum(t, c), ClassAddendumClass, jclass);
}
return jclass;
}
void
dumpHeap(Thread* t, FILE* out);

View File

@ -1,8 +1,10 @@
(type jobject java/lang/Object)
(type class java/lang/Class
(type class avian/VMClass
(array void* vtable))
(type jclass java/lang/Class)
(type singleton
(array uintptr_t body))
@ -11,13 +13,10 @@
(type systemClassLoader avian/SystemClassLoader)
(type accessibleObject java/lang/reflect/AccessibleObject)
(type field avian/VMField)
(type field java/lang/reflect/Field)
(type method java/lang/reflect/Method)
(type proxy java/lang/reflect/Proxy)
(type method avian/VMMethod
(intptr_t compiled))
(type addendum avian/Addendum)