move proxy and annotation code from C++ to Java

This allows code shrinkers to remove it if it's not used by the application.
This commit is contained in:
Joel Dice 2009-09-19 16:21:15 -06:00
parent 1a2eb3836c
commit 953cb69e5e
15 changed files with 1056 additions and 783 deletions

View File

@ -0,0 +1,16 @@
/* Copyright (c) 2009, 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 Addendum {
public Object pool;
public Object annotationTable;
}

View File

@ -10,7 +10,6 @@
package avian;
public class Pair<A,B> {
public A first;
public B second;
public class ClassAddendum extends Addendum {
public Object[] signers;
}

View File

@ -0,0 +1,17 @@
/* Copyright (c) 2009, 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 abstract class Singleton {
public static native int getInt(Object singleton, int offset);
public static native long getLong(Object singleton, int offset);
public static native Object getObject(Object singleton, int offset);
}

View File

@ -0,0 +1,74 @@
/* Copyright (c) 2009, 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 java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.EOFException;
public abstract class Stream {
public static void write1(OutputStream out, int v) throws IOException {
out.write(v & 0xFF);
}
public static int read1(InputStream in) throws IOException {
return in.read();
}
public static void write2(OutputStream out, int v) throws IOException {
out.write((v >>> 8) & 0xFF);
out.write((v ) & 0xFF);
}
public static int read2(InputStream in) throws IOException {
int b1 = in.read();
int b2 = in.read();
if (b2 == -1) throw new EOFException();
return ((b1 << 8) | (b2 & 0xFF));
}
public static void write4(OutputStream out, int v) throws IOException {
out.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v ) & 0xFF);
}
public static int read4(InputStream in) throws IOException {
int b1 = in.read();
int b2 = in.read();
int b3 = in.read();
int b4 = in.read();
if (b4 == -1) throw new EOFException();
return ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4));
}
public static void write8(OutputStream out, long v) throws IOException {
write4(out, (int) (v >>> 32) & 0xFFFFFFFF);
write4(out, (int) (v ) & 0xFFFFFFFF);
}
public static long read8(InputStream in) throws IOException {
long b1 = in.read();
long b2 = in.read();
long b3 = in.read();
long b4 = in.read();
long b5 = in.read();
long b6 = in.read();
long b7 = in.read();
long b8 = in.read();
if (b8 == -1) throw new EOFException();
return ((b1 << 56) | (b2 << 48) | (b3 << 40) | (b4 << 32) |
(b5 << 24) | (b6 << 16) | (b7 << 8) | (b8));
}
}

View File

@ -10,10 +10,23 @@
package avian;
import static avian.Stream.read1;
import static avian.Stream.read2;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
public class SystemClassLoader extends ClassLoader {
private static final int LinkFlag = 1 << 8;
public static native Class defineClass
(ClassLoader loader, byte[] b, int offset, int length);
protected native Class findClass(String name) throws ClassNotFoundException;
protected native Class findLoadedClass(String name);
@ -28,4 +41,225 @@ public class SystemClassLoader extends ClassLoader {
}
return null;
}
private static Class loadClass(ClassLoader loader,
byte[] nameBytes, int offset, int length)
{
String name = new String(nameBytes, offset, length, false);
try {
return loader.loadClass(name);
} catch (ClassNotFoundException e) {
NoClassDefFoundError error = new NoClassDefFoundError(name);
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
(loadClass(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);
}
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] = loadClass(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 != null) {
try {
addendum.annotationTable = parseAnnotationTable
(loader, addendum.pool, new ByteArrayInputStream
((byte[]) addendum.annotationTable));
} catch (IOException e) {
AssertionError error = new AssertionError();
error.initCause(e);
throw error;
}
addendum.pool = null;
}
}
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;
}
loadClass(loader, spec, start, end - start);
return result;
}
private static native void acquireClassLock();
private static native void releaseClassLock();
public static void link(Class 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.isInterface() ? 1 : 2);
for (int i = 0; i < c.interfaceTable.length; i += stride) {
link((Class) c.interfaceTable[i], loader);
}
}
if (c.methodTable != null) {
for (int i = 0; i < c.methodTable.length; ++i) {
Method 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) {
Field f = c.fieldTable[i];
resolveSpec(loader, f.spec, 0);
parseAnnotationTable(loader, f.addendum);
}
}
c.vmFlags |= LinkFlag;
}
} finally {
releaseClassLock();
}
}
public static void link(Class c) {
link(c, c.getClassLoader());
}
}

View File

@ -11,7 +11,6 @@
package java.lang;
import avian.AnnotationInvocationHandler;
import avian.Pair;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@ -38,22 +37,21 @@ public final class Class <T>
implements Type, GenericDeclaration, AnnotatedElement
{
private static final int PrimitiveFlag = 1 << 5;
private static final int LinkFlag = 1 << 8;
private short flags;
private short vmFlags;
public short vmFlags;
private short fixedSize;
private byte arrayElementSize;
private byte arrayDimensions;
private int[] objectMask;
private byte[] name;
private byte[] sourceFile;
private Class super_;
private Object[] interfaceTable;
private Method[] virtualTable;
private Field[] fieldTable;
private Method[] methodTable;
private Addendum addendum;
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;
@ -149,157 +147,6 @@ public final class Class <T>
}
}
private static Class loadClass(ClassLoader loader,
byte[] nameBytes, int offset, int length)
{
String name = new String(nameBytes, offset, length, false);
try {
return loader.loadClass(name);
} catch (ClassNotFoundException e) {
NoClassDefFoundError error = new NoClassDefFoundError(name);
error.initCause(e);
throw error;
}
}
private static Object resolveAnnotationValue(ClassLoader loader,
Object raw)
{
if (raw instanceof Pair) {
Pair<byte[],byte[]> p = (Pair<byte[],byte[]>) raw;
return Enum.valueOf
(loadClass(loader, p.first, 1, p.first.length - 3),
new String(p.second, 0, p.second.length - 1, false));
} else if (raw instanceof byte[]) {
byte[] typeName = (byte[]) raw;
return loadClass(loader, typeName, 0, typeName.length - 1);
} else if (raw.getClass().isArray()) {
Object[] array = (Object[]) raw;
if (array.length > 0 && array[0] == null) {
resolveAnnotation(loader, array);
} else {
for (int i = 0; i < array.length; ++i) {
array[i] = resolveAnnotationValue(loader, array[i]);
}
}
}
return raw;
}
private static void resolveAnnotation(ClassLoader loader,
Object[] annotation)
{
byte[] typeName = (byte[]) annotation[1];
annotation[1] = loadClass(loader, typeName, 1, typeName.length - 3);
for (int i = 2; i < annotation.length; i += 2) {
byte[] name = (byte[]) annotation[i];
annotation[i] = new String(name, 0, name.length - 1, false).intern();
annotation[i + 1] = resolveAnnotationValue(loader, annotation[i + 1]);
}
}
private static void resolveAnnotationTable(ClassLoader loader,
Object[] table)
{
for (int i = 0; i < table.length; ++i) {
resolveAnnotation(loader, (Object[]) table[i]);
}
}
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;
}
loadClass(loader, spec, start, end - start);
return result;
}
private static native void acquireClassLock();
private static native void releaseClassLock();
void link(ClassLoader loader) {
acquireClassLock();
try {
if ((vmFlags & LinkFlag) == 0) {
if (super_ != null) {
super_.link(loader);
}
if (addendum != null && addendum.annotationTable != null) {
resolveAnnotationTable(loader, addendum.annotationTable);
}
if (interfaceTable != null) {
int stride = (isInterface() ? 1 : 2);
for (int i = 0; i < interfaceTable.length; i += stride) {
((Class) interfaceTable[i]).link(loader);
}
}
if (methodTable != null) {
for (int i = 0; i < methodTable.length; ++i) {
Method m = methodTable[i];
for (int j = 1; j < m.spec.length;) {
j = resolveSpec(loader, m.spec, j);
}
if (m.addendum != null && m.addendum.annotationTable != null) {
resolveAnnotationTable(loader, m.addendum.annotationTable);
}
}
}
if (fieldTable != null) {
for (int i = 0; i < fieldTable.length; ++i) {
Field f = fieldTable[i];
resolveSpec(loader, f.spec, 0);
if (f.addendum != null && f.addendum.annotationTable != null) {
resolveAnnotationTable(loader, f.addendum.annotationTable);
}
}
}
vmFlags |= LinkFlag;
}
} finally {
releaseClassLock();
}
}
public static Class forName(String name) throws ClassNotFoundException {
return forName
(name, true, Method.getCaller().getDeclaringClass().getClassLoader());
@ -313,7 +160,7 @@ public final class Class <T>
loader = Class.class.loader;
}
Class c = loader.loadClass(name);
c.link(loader);
avian.SystemClassLoader.link(c, loader);
if (initialize) {
c.initialize();
}
@ -378,7 +225,7 @@ public final class Class <T>
private Field findField(String name) {
if (fieldTable != null) {
link(loader);
avian.SystemClassLoader.link(this);
for (int i = 0; i < fieldTable.length; ++i) {
if (fieldTable[i].getName().equals(name)) {
@ -423,7 +270,7 @@ public final class Class <T>
private Method findMethod(String name, Class[] parameterTypes) {
if (methodTable != null) {
link(loader);
avian.SystemClassLoader.link(this);
if (parameterTypes == null) {
parameterTypes = new Class[0];
@ -517,7 +364,7 @@ public final class Class <T>
public Constructor[] getDeclaredConstructors() {
Constructor[] array = new Constructor[countConstructors(false)];
if (methodTable != null) {
link(loader);
avian.SystemClassLoader.link(this);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
@ -533,7 +380,7 @@ public final class Class <T>
public Constructor[] getConstructors() {
Constructor[] array = new Constructor[countConstructors(true)];
if (methodTable != null) {
link(loader);
avian.SystemClassLoader.link(this);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
@ -573,7 +420,7 @@ public final class Class <T>
public Field[] getFields() {
Field[] array = new Field[countPublicFields()];
if (fieldTable != null) {
link(loader);
avian.SystemClassLoader.link(this);
int ai = 0;
for (int i = 0; i < fieldTable.length; ++i) {
@ -603,7 +450,7 @@ public final class Class <T>
public Method[] getDeclaredMethods() {
Method[] array = new Method[countMethods(false)];
if (methodTable != null) {
link(loader);
avian.SystemClassLoader.link(this);
int ai = 0;
for (int i = 0; i < methodTable.length; ++i) {
@ -619,7 +466,7 @@ public final class Class <T>
public Method[] getMethods() {
Method[] array = new Method[countMethods(true)];
if (methodTable != null) {
link(loader);
avian.SystemClassLoader.link(this);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
@ -636,7 +483,7 @@ public final class Class <T>
public Class[] getInterfaces() {
if (interfaceTable != null) {
link(loader);
avian.SystemClassLoader.link(this);
int stride = (isInterface() ? 1 : 2);
Class[] array = new Class[interfaceTable.length / stride];
@ -762,9 +609,9 @@ public final class Class <T>
public <T extends Annotation> T getAnnotation(Class<T> class_) {
for (Class c = this; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
link(c.loader);
avian.SystemClassLoader.link(c, c.loader);
Object[] table = c.addendum.annotationTable;
Object[] table = (Object[]) c.addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
Object[] a = (Object[]) table[i];
if (a[1] == class_) {
@ -778,9 +625,9 @@ public final class Class <T>
public Annotation[] getDeclaredAnnotations() {
if (addendum != null && addendum.annotationTable != null) {
link(loader);
avian.SystemClassLoader.link(this);
Object[] table = addendum.annotationTable;
Object[] table = (Object[]) addendum.annotationTable;
Annotation[] array = new Annotation[table.length];
for (int i = 0; i < table.length; ++i) {
array[i] = getAnnotation((Object[]) table[i]);
@ -795,7 +642,7 @@ public final class Class <T>
int count = 0;
for (Class c = this; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
count += c.addendum.annotationTable.length;
count += ((Object[]) c.addendum.annotationTable).length;
}
}
return count;
@ -806,7 +653,7 @@ public final class Class <T>
int i = 0;
for (Class c = this; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
Object[] table = c.addendum.annotationTable;
Object[] table = (Object[]) c.addendum.annotationTable;
for (int j = 0; j < table.length; ++j) {
array[i++] = getAnnotation((Object[]) table[j]);
}
@ -850,14 +697,9 @@ public final class Class <T>
void setSigners(Object[] signers) {
if (signers != null && signers.length > 0) {
if (addendum == null) {
addendum = new Addendum();
addendum = new avian.ClassAddendum();
}
addendum.signers = signers;
}
}
private static class Addendum {
public Object[] annotationTable;
public Object[] signers;
}
}

View File

@ -33,9 +33,6 @@ public abstract class ClassLoader {
return ClassLoader.class.getClassLoader();
}
private static native Class defineClass
(ClassLoader loader, byte[] b, int offset, int length);
protected Class defineClass(String name, byte[] b, int offset, int length) {
if (b == null) {
throw new NullPointerException();
@ -45,7 +42,7 @@ public abstract class ClassLoader {
throw new IndexOutOfBoundsException();
}
return defineClass(this, b, offset, length);
return avian.SystemClassLoader.defineClass(this, b, offset, length);
}
protected Class findClass(String name) throws ClassNotFoundException {
@ -84,7 +81,7 @@ public abstract class ClassLoader {
}
protected void resolveClass(Class c) {
c.link(this);
avian.SystemClassLoader.link(c, this);
}
private ClassLoader getParent() {

View File

@ -32,7 +32,7 @@ public class Field<T> extends AccessibleObject {
private short offset;
private byte[] name;
public byte[] spec;
public Addendum addendum;
public avian.Addendum addendum;
private Class<T> class_;
private Field() { }
@ -211,7 +211,7 @@ public class Field<T> extends AccessibleObject {
public <T extends Annotation> T getAnnotation(Class<T> class_) {
if (addendum != null && addendum.annotationTable != null) {
Object[] table = addendum.annotationTable;
Object[] table = (Object[]) addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
Object[] a = (Object[]) table[i];
if (a[1] == class_) {
@ -224,7 +224,7 @@ public class Field<T> extends AccessibleObject {
public Annotation[] getAnnotations() {
if (addendum != null && addendum.annotationTable != null) {
Object[] table = addendum.annotationTable;
Object[] table = (Object[]) addendum.annotationTable;
Annotation[] array = new Annotation[table.length];
for (int i = 0; i < table.length; ++i) {
array[i] = getAnnotation((Object[]) table[i]);
@ -256,6 +256,7 @@ public class Field<T> extends AccessibleObject {
(Object instance, int offset, Object value);
public static class Addendum {
public Object[] annotationTable;
public Object pool;
public Object annotationTable;
}
}

View File

@ -19,14 +19,14 @@ public class Method<T> extends AccessibleObject
{
private byte vmFlags;
private byte returnCode;
private byte parameterCount;
private byte parameterFootprint;
public byte parameterCount;
public byte parameterFootprint;
private short flags;
private short offset;
private int nativeID;
private byte[] name;
public byte[] spec;
public Addendum addendum;
public avian.Addendum addendum;
private Class<T> class_;
private Object code;
private long compiled;
@ -55,6 +55,10 @@ public class Method<T> extends AccessibleObject
return new String(name, 0, name.length - 1, false);
}
String getSpec() {
return new String(spec, 0, spec.length - 1, false);
}
private static int next(char c, String s, int start) {
for (int i = start; i < s.length(); ++i) {
if (s.charAt(i) == c) return i;
@ -158,7 +162,7 @@ public class Method<T> extends AccessibleObject
public <T extends Annotation> T getAnnotation(Class<T> class_) {
if (addendum != null && addendum.annotationTable != null) {
Object[] table = addendum.annotationTable;
Object[] table = (Object[]) addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
Object[] a = (Object[]) table[i];
if (a[1] == class_) {
@ -171,7 +175,7 @@ public class Method<T> extends AccessibleObject
public Annotation[] getAnnotations() {
if (addendum != null && addendum.annotationTable != null) {
Object[] table = addendum.annotationTable;
Object[] table = (Object[]) addendum.annotationTable;
Annotation[] array = new Annotation[table.length];
for (int i = 0; i < table.length; ++i) {
array[i] = getAnnotation((Object[]) table[i]);
@ -209,8 +213,4 @@ public class Method<T> extends AccessibleObject
public TypeVariable<Method<T>>[] getTypeParameters() {
throw new UnsupportedOperationException();
}
public static class Addendum {
public Object[] annotationTable;
}
}

View File

@ -10,7 +10,51 @@
package java.lang.reflect;
import static avian.Stream.write1;
import static avian.Stream.write2;
import static avian.Stream.write4;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class Proxy {
private static final int CONSTANT_Integer = 3;
private static final int CONSTANT_Utf8 = 1;
private static final int CONSTANT_Class = 7;
private static final int CONSTANT_NameAndType = 12;
private static final int CONSTANT_Fieldref = 9;
private static final int CONSTANT_Methodref = 10;
private static final int aaload = 0x32;
private static final int aastore = 0x53;
private static final int aload = 0x19;
private static final int aload_0 = 0x2a;
private static final int aload_1 = 0x2b;
private static final int anewarray = 0xbd;
private static final int areturn = 0xb0;
private static final int dload = 0x18;
private static final int dreturn = 0xaf;
private static final int dup = 0x59;
private static final int fload = 0x17;
private static final int freturn = 0xae;
private static final int getfield = 0xb4;
private static final int iload = 0x15;
private static final int invokeinterface = 0xb9;
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 pop = 0x57;
private static final int putfield = 0xb5;
private static final int return_ = 0xb1;
private static int nextNumber;
protected InvocationHandler h;
@ -29,13 +73,429 @@ public class Proxy {
number = nextNumber++;
}
return makeClass
(loader, interfaces, ("Proxy-" + number + "\0").getBytes());
try {
return makeClass(loader, interfaces, "Proxy-" + number);
} catch (IOException e) {
AssertionError error = new AssertionError();
error.initCause(e);
throw error;
}
}
private static native Class makeClass(ClassLoader loader,
Class[] interfaces,
byte[] name);
private static void set4(byte[] array, int offset, int v) {
array[offset ] = (byte) ((v >>> 24) & 0xFF);
array[offset + 1] = (byte) ((v >>> 16) & 0xFF);
array[offset + 2] = (byte) ((v >>> 8) & 0xFF);
array[offset + 3] = (byte) ((v ) & 0xFF);
}
private static int poolAdd(List<PoolEntry> pool, PoolEntry e) {
int i = 0;
for (PoolEntry existing: pool) {
if (existing.equals(e)) {
return i;
} else {
++i;
}
}
pool.add(e);
return pool.size() - 1;
}
private static int poolAddInteger(List<PoolEntry> pool, int value) {
return poolAdd(pool, new IntegerPoolEntry(value));
}
private static int poolAddUtf8(List<PoolEntry> pool, String value) {
return poolAdd(pool, new Utf8PoolEntry(value));
}
private static int poolAddClass(List<PoolEntry> pool, String name) {
return poolAdd(pool, new ClassPoolEntry(poolAddUtf8(pool, name)));
}
private static int poolAddNameAndType(List<PoolEntry> pool,
String name,
String type)
{
return poolAdd(pool, new NameAndTypePoolEntry
(poolAddUtf8(pool, name),
poolAddUtf8(pool, type)));
}
private static int poolAddFieldRef(List<PoolEntry> pool,
String className,
String name,
String spec)
{
return poolAdd(pool, new FieldRefPoolEntry
(poolAddClass(pool, className),
poolAddNameAndType(pool, name, spec)));
}
private static int poolAddMethodRef(List<PoolEntry> pool,
String className,
String name,
String spec)
{
return poolAdd(pool, new MethodRefPoolEntry
(poolAddClass(pool, className),
poolAddNameAndType(pool, name, spec)));
}
private static byte[] makeInvokeCode(List<PoolEntry> pool,
String className,
byte[] spec,
int parameterCount,
int parameterFootprint,
int index)
throws IOException
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
write2(out, 8); // max stack
write2(out, parameterFootprint); // max locals
write4(out, 0); // length (we'll set the real value later)
write1(out, aload_0);
write1(out, getfield);
write2(out, poolAddFieldRef
(pool, "java/lang/reflect/Proxy",
"h", "Ljava/lang/reflect/InvocationHandler;") + 1);
write1(out, aload_0);
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);
write1(out, ldc_w);
write2(out, poolAddInteger(pool, index) + 1);
write1(out, aaload);
write1(out, ldc_w);
write2(out, poolAddInteger(pool, parameterCount) + 1);
write1(out, anewarray);
write2(out, poolAddClass(pool, "java/lang/Object") + 1);
int ai = 0;
int si;
for (si = 1; spec[si] != ')'; ++si) {
write1(out, dup);
write1(out, ldc_w);
write2(out, poolAddInteger(pool, ai) + 1);
switch (spec[si]) {
case 'L':
++ si;
while (spec[si] != ';') ++si;
write1(out, aload);
write1(out, ai + 1);
break;
case '[':
++ si;
while (spec[si] == '[') ++si;
switch (spec[si]) {
case 'L':
++ si;
while (spec[si] != ';') ++si;
break;
default:
break;
}
write1(out, aload);
write1(out, ai + 1);
break;
case 'Z':
write1(out, iload);
write1(out, ai + 1);
write1(out, invokestatic);
write2(out, poolAddMethodRef
(pool, "java/lang/Boolean",
"valueOf", "(Z)Ljava/lang/Boolean;") + 1);
break;
case 'B':
write1(out, iload);
write1(out, ai + 1);
write1(out, invokestatic);
write2(out, poolAddMethodRef
(pool, "java/lang/Byte",
"valueOf", "(B)Ljava/lang/Byte;") + 1);
break;
case 'S':
write1(out, iload);
write1(out, ai + 1);
write1(out, invokestatic);
write2(out, poolAddMethodRef
(pool, "java/lang/Short",
"valueOf", "(S)Ljava/lang/Short;") + 1);
break;
case 'C':
write1(out, iload);
write1(out, ai + 1);
write1(out, invokestatic);
write2(out, poolAddMethodRef
(pool, "java/lang/Character",
"valueOf", "(C)Ljava/lang/Character;") + 1);
break;
case 'I':
write1(out, iload);
write1(out, ai + 1);
write1(out, invokestatic);
write2(out, poolAddMethodRef
(pool, "java/lang/Integer",
"valueOf", "(I)Ljava/lang/Integer;") + 1);
break;
case 'F':
write1(out, fload);
write1(out, ai + 1);
write1(out, invokestatic);
write2(out, poolAddMethodRef
(pool, "java/lang/Float",
"valueOf", "(F)Ljava/lang/Float;") + 1);
break;
case 'J':
write1(out, lload);
write1(out, ai + 1);
write1(out, invokestatic);
write2(out, poolAddMethodRef
(pool, "java/lang/Long",
"valueOf", "(J)Ljava/lang/Long;") + 1);
++ ai;
break;
case 'D':
write1(out, dload);
write1(out, ai + 1);
write1(out, invokestatic);
write2(out, poolAddMethodRef
(pool, "java/lang/Double",
"valueOf", "(D)Ljava/lang/Double;") + 1);
++ ai;
break;
default: throw new IllegalArgumentException();
}
write1(out, aastore);
++ ai;
}
write1(out, invokeinterface);
write2(out, poolAddMethodRef
(pool, "java/lang/reflect/InvocationHandler",
"invoke",
"(Ljava/lang/Object;"
+ "Ljava/lang/reflect/Method;"
+ "[Ljava/lang/Object;)"
+ "Ljava/lang/Object;") + 1);
write2(out, 0); // this will be ignored by the VM
switch (spec[si + 1]) {
case 'L':
case '[':
write1(out, areturn);
break;
case 'Z':
write1(out, invokevirtual);
write2(out, poolAddMethodRef
(pool, "java/lang/Boolean", "booleanValue", "()Z") + 1);
write1(out, ireturn);
break;
case 'B':
write1(out, invokevirtual);
write2(out, poolAddMethodRef
(pool, "java/lang/Byte", "byteValue", "()B") + 1);
write1(out, ireturn);
break;
case 'C':
write1(out, invokevirtual);
write2(out, poolAddMethodRef
(pool, "java/lang/Character", "charValue", "()B") + 1);
write1(out, ireturn);
break;
case 'S':
write1(out, invokevirtual);
write2(out, poolAddMethodRef
(pool, "java/lang/Short", "shortValue", "()S") + 1);
write1(out, ireturn);
break;
case 'I':
write1(out, invokevirtual);
write2(out, poolAddMethodRef
(pool, "java/lang/Integer", "intValue", "()I") + 1);
write1(out, ireturn);
break;
case 'F':
write1(out, invokevirtual);
write2(out, poolAddMethodRef
(pool, "java/lang/Float", "floatValue", "()F") + 1);
write1(out, freturn);
break;
case 'J':
write1(out, invokevirtual);
write2(out, poolAddMethodRef
(pool, "java/lang/Long", "longValue", "()J") + 1);
write1(out, lreturn);
break;
case 'D':
write1(out, invokevirtual);
write2(out, poolAddMethodRef
(pool, "java/lang/Double", "doubleValue", "()D") + 1);
write1(out, dreturn);
break;
case 'V':
write1(out, pop);
write1(out, return_);
break;
default: throw new IllegalArgumentException();
}
write2(out, 0); // exception handler table length
write2(out, 0); // attribute count
byte[] result = out.toByteArray();
set4(result, 4, result.length - 12);
return result;
}
private static byte[] makeConstructorCode(List<PoolEntry> pool)
throws IOException
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
write2(out, 2); // max stack
write2(out, 2); // max locals
write4(out, 6); // length
write1(out, aload_0);
write1(out, aload_1);
write1(out, putfield);
write2(out, poolAddFieldRef
(pool, "java/lang/reflect/Proxy",
"h", "Ljava/lang/reflect/InvocationHandler;") + 1);
write1(out, return_);
write2(out, 0); // exception handler table length
write2(out, 0); // attribute count
return out.toByteArray();
}
private static Class makeClass(ClassLoader loader,
Class[] interfaces,
String name)
throws IOException
{
List<PoolEntry> pool = new ArrayList();
int[] interfaceIndexes = new int[interfaces.length];
for (int i = 0; i < interfaces.length; ++i) {
interfaceIndexes[i] = poolAddClass(pool, interfaces[i].getName());
}
Map<String,Method> virtualMap = new HashMap();
for (Class c: interfaces) {
Method[] ivtable = c.virtualTable;
if (ivtable != null) {
for (Method m: ivtable) {
virtualMap.put(m.getName() + m.getSpec(), m);
}
}
}
MethodData[] methodTable = new MethodData[virtualMap.size() + 1];
{ int i = 0;
for (Method m: virtualMap.values()) {
methodTable[i] = new MethodData
(poolAddUtf8(pool, m.getName()),
poolAddUtf8(pool, m.getSpec()),
makeInvokeCode(pool, name, m.spec, m.parameterCount,
m.parameterFootprint, i));
++ i;
}
methodTable[i++] = new MethodData
(poolAddUtf8(pool, "<init>"),
poolAddUtf8(pool, "(Ljava/lang/reflect/InvocationHandler;)V"),
makeConstructorCode(pool));
}
int nameIndex = poolAddClass(pool, name);
int superIndex = poolAddClass(pool, "java/lang/reflect/Proxy");
int codeAttributeNameIndex = poolAddUtf8(pool, "Code");
ByteArrayOutputStream out = new ByteArrayOutputStream();
write4(out, 0xCAFEBABE);
write2(out, 0); // minor version
write2(out, 0); // major version
write2(out, pool.size() + 1);
for (PoolEntry e: pool) {
e.writeTo(out);
}
write2(out, 0); // flags
write2(out, nameIndex + 1);
write2(out, superIndex + 1);
write2(out, interfaces.length);
for (int i: interfaceIndexes) {
write2(out, i + 1);
}
write2(out, 0); // field count
write2(out, methodTable.length);
for (MethodData m: methodTable) {
write2(out, 0); // flags
write2(out, m.nameIndex + 1);
write2(out, m.specIndex + 1);
write2(out, 1); // attribute count
write2(out, codeAttributeNameIndex + 1);
write4(out, m.code.length);
out.write(m.code);
}
write2(out, 0); // attribute count
byte[] classData = out.toByteArray();
return avian.SystemClassLoader.defineClass
(loader, classData, 0, classData.length);
}
public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
@ -51,4 +511,153 @@ public class Proxy {
throw error;
}
}
private static class MethodData {
public final int nameIndex;
public final int specIndex;
public final byte[] code;
public MethodData(int nameIndex, int specIndex, byte[] code) {
this.nameIndex = nameIndex;
this.specIndex = specIndex;
this.code = code;
}
}
public interface PoolEntry {
public void writeTo(OutputStream out) throws IOException;
}
public static class IntegerPoolEntry implements PoolEntry {
private final int value;
public IntegerPoolEntry(int value) {
this.value = value;
}
public void writeTo(OutputStream out) throws IOException {
write1(out, CONSTANT_Integer);
write4(out, value);
}
public boolean equals(Object o) {
return o instanceof IntegerPoolEntry
&& ((IntegerPoolEntry) o).value == value;
}
}
public static class Utf8PoolEntry implements PoolEntry {
private final String data;
public Utf8PoolEntry(String data) {
this.data = data;
}
public void writeTo(OutputStream out) throws IOException {
write1(out, CONSTANT_Utf8);
byte[] bytes = data.getBytes();
write2(out, bytes.length);
out.write(bytes);
}
public boolean equals(Object o) {
return o instanceof Utf8PoolEntry
&& ((Utf8PoolEntry) o).data.equals(data);
}
}
public static class ClassPoolEntry implements PoolEntry {
private final int nameIndex;
public ClassPoolEntry(int nameIndex) {
this.nameIndex = nameIndex;
}
public void writeTo(OutputStream out) throws IOException {
write1(out, CONSTANT_Class);
write2(out, nameIndex + 1);
}
public boolean equals(Object o) {
return o instanceof ClassPoolEntry
&& ((ClassPoolEntry) o).nameIndex == nameIndex;
}
}
public static class NameAndTypePoolEntry implements PoolEntry {
private final int nameIndex;
private final int typeIndex;
public NameAndTypePoolEntry(int nameIndex, int typeIndex) {
this.nameIndex = nameIndex;
this.typeIndex = typeIndex;
}
public void writeTo(OutputStream out) throws IOException {
write1(out, CONSTANT_NameAndType);
write2(out, nameIndex + 1);
write2(out, typeIndex + 1);
}
public boolean equals(Object o) {
if (o instanceof NameAndTypePoolEntry) {
NameAndTypePoolEntry other = (NameAndTypePoolEntry) o;
return other.nameIndex == nameIndex && other.typeIndex == typeIndex;
} else {
return false;
}
}
}
public static class FieldRefPoolEntry implements PoolEntry {
private final int classIndex;
private final int nameAndTypeIndex;
public FieldRefPoolEntry(int classIndex, int nameAndTypeIndex) {
this.classIndex = classIndex;
this.nameAndTypeIndex = nameAndTypeIndex;
}
public void writeTo(OutputStream out) throws IOException {
write1(out, CONSTANT_Fieldref);
write2(out, classIndex + 1);
write2(out, nameAndTypeIndex + 1);
}
public boolean equals(Object o) {
if (o instanceof FieldRefPoolEntry) {
FieldRefPoolEntry other = (FieldRefPoolEntry) o;
return other.classIndex == classIndex
&& other.nameAndTypeIndex == nameAndTypeIndex;
} else {
return false;
}
}
}
public static class MethodRefPoolEntry implements PoolEntry {
private final int classIndex;
private final int nameAndTypeIndex;
public MethodRefPoolEntry(int classIndex, int nameAndTypeIndex) {
this.classIndex = classIndex;
this.nameAndTypeIndex = nameAndTypeIndex;
}
public void writeTo(OutputStream out) throws IOException {
write1(out, CONSTANT_Methodref);
write2(out, classIndex + 1);
write2(out, nameAndTypeIndex + 1);
}
public boolean equals(Object o) {
if (o instanceof MethodRefPoolEntry) {
MethodRefPoolEntry other = (MethodRefPoolEntry) o;
return other.classIndex == classIndex
&& other.nameAndTypeIndex == nameAndTypeIndex;
} else {
return false;
}
}
}
}

View File

@ -79,242 +79,6 @@ runOnLoadIfFound(Thread* t, System::Library* library)
}
}
void JNICALL
proxyConstruct(Thread* t, object, uintptr_t* arguments)
{
set(t, reinterpret_cast<object>(arguments[0]), ProxyH,
reinterpret_cast<object>(arguments[1]));
}
int64_t JNICALL
proxyInvoke(Thread* t, object method, uintptr_t* arguments)
{
PROTECT(t, method);
unsigned size = methodParameterFootprint(t, method);
RUNTIME_ARRAY(bool, objectMask, size);
assert(t, (methodFlags(t, method) & ACC_STATIC) == 0);
unsigned i = 0;
RUNTIME_ARRAY_BODY(objectMask)[i++] = true;
unsigned argumentCount = 0;
for (MethodSpecIterator it
(t, reinterpret_cast<char*>
(&byteArrayBody(t, methodSpec(t, method), 0)));
it.hasNext();)
{
++ argumentCount;
switch (*it.next()) {
case 'L':
case '[':
RUNTIME_ARRAY_BODY(objectMask)[i++] = true;
break;
case 'J':
case 'D':
RUNTIME_ARRAY_BODY(objectMask)[i++] = false;
RUNTIME_ARRAY_BODY(objectMask)[i++] = false;
break;
default:
RUNTIME_ARRAY_BODY(objectMask)[i++] = false;
break;
}
}
class MyProtector: public Thread::Protector {
public:
MyProtector(Thread* t, uintptr_t* array, bool* mask, unsigned count):
Protector(t), array(array), mask(mask), count(count) { }
virtual void visit(Heap::Visitor* v) {
for (unsigned i = 0; i < count; ++i) {
if (mask[i]) {
v->visit(reinterpret_cast<object*>(array + i));
}
}
}
uintptr_t* array;
bool* mask;
unsigned count;
} protector(t, arguments, RUNTIME_ARRAY_BODY(objectMask), i);
object array = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JobjectType),
argumentCount);
PROTECT(t, array);
i = 0;
unsigned ai = 1;
for (MethodSpecIterator it
(t, reinterpret_cast<char*>
(&byteArrayBody(t, methodSpec(t, method), 0)));
it.hasNext();)
{
object a;
unsigned size;
switch (*it.next()) {
case 'L':
case '[':
a = reinterpret_cast<object>(arguments[ai]);
size = 1;
break;
case 'Z':
a = makeBoolean(t, static_cast<int8_t>(arguments[ai]));
size = 1;
break;
case 'B':
a = makeByte(t, static_cast<int8_t>(arguments[ai]));
size = 1;
break;
case 'S':
a = makeShort(t, static_cast<int16_t>(arguments[ai]));
size = 1;
break;
case 'C':
a = makeChar(t, static_cast<uint16_t>(arguments[ai]));
size = 1;
break;
case 'I':
a = makeInt(t, static_cast<int32_t>(arguments[ai]));
size = 1;
break;
case 'F':
a = makeFloat(t, bitsToFloat(static_cast<int32_t>(arguments[ai])));
size = 1;
break;
case 'J': {
int64_t v; memcpy(&v, arguments + ai, 8);
a = makeLong(t, v);
size = 2;
} break;
case 'D': {
double v; memcpy(&v, arguments + ai, 8);
a = makeDouble(t, v);
size = 2;
} break;
default:
abort(t);
}
set(t, array, ArrayBody + (i * BytesPerWord), a);
++ i;
ai += size;
}
if (t->m->invokeMethod == 0) {
object m = resolveMethod
(t, t->m->loader, "java/lang/reflect/InvocationHandler", "invoke",
"(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)"
"Ljava/lang/Object;");
if (m) {
t->m->invokeMethod = m;
}
if (UNLIKELY(t->exception)) return 0;
}
object invoke = findInterfaceMethod
(t, t->m->invokeMethod, objectClass
(t, proxyH(t, reinterpret_cast<object>(arguments[0]))));
PROTECT(t, invoke);
object result = t->m->processor->invoke
(t, invoke, proxyH(t, reinterpret_cast<object>(arguments[0])),
reinterpret_cast<object>(arguments[0]), method, array);
if (UNLIKELY(t->exception)) return 0;
switch (methodReturnCode(t, method)) {
case BooleanField:
return booleanValue(t, result);
case ByteField:
return byteValue(t, result);
case CharField:
return charValue(t, result);
case ShortField:
return shortValue(t, result);
case FloatField:
return floatToBits(floatValue(t, result));
case IntField:
return intValue(t, result);
case LongField:
return longValue(t, result);
case DoubleField:
return doubleToBits(doubleValue(t, result));
case ObjectField:
return reinterpret_cast<int64_t>(result);
case VoidField:
return 0;
default:
abort(t);
}
}
void
addInterface(Thread* t, object map, object interface)
{
hashMapInsertMaybe
(t, map, className(t, interface), interface, byteArrayHash,
byteArrayEqual);
}
object
allInterfaces(Thread* t, object array)
{
PROTECT(t, array);
object map = makeHashMap(t, 0, 0);
PROTECT(t, map);
for (unsigned i = 0; i < objectArrayLength(t, array); ++i) {
addInterface(t, map, objectArrayBody(t, array, i));
object itable = classInterfaceTable(t, objectArrayBody(t, array, i));
if (itable) {
PROTECT(t, itable);
for (unsigned j = 0; j < arrayLength(t, itable); ++j) {
addInterface(t, map, arrayBody(t, itable, j));
}
}
}
object result = makeArray(t, hashMapSize(t, map));
unsigned i = 0;
for (HashMapIterator it(t, map); it.hasMore();) {
set(t, result, ArrayBody + (i * BytesPerWord), tripleSecond(t, it.next()));
++ i;
}
return result;
}
} // namespace
extern "C" JNIEXPORT int64_t JNICALL
@ -404,8 +168,22 @@ Avian_java_lang_Object_clone
return reinterpret_cast<int64_t>(clone);
}
extern "C" JNIEXPORT void JNICALL
Avian_avian_SystemClassLoader_acquireClassLock
(Thread* t, object)
{
acquire(t, t->m->classLock);
}
extern "C" JNIEXPORT void JNICALL
Avian_avian_SystemClassLoader_releaseClassLock
(Thread* t, object)
{
release(t, t->m->classLock);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_ClassLoader_defineClass
Avian_avian_SystemClassLoader_defineClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
@ -527,20 +305,6 @@ Avian_java_lang_Class_initialize
initClass(t, this_);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Class_acquireClassLock
(Thread* t, object)
{
acquire(t, t->m->classLock);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Class_releaseClassLock
(Thread* t, object)
{
release(t, t->m->classLock);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Class_isAssignableFrom
(Thread* t, object, uintptr_t* arguments)
@ -729,195 +493,6 @@ Avian_java_lang_reflect_Array_makeObjectArray
(makeObjectArray(t, classLoader(t, elementType), elementType, length));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Proxy_makeClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
PROTECT(t, loader);
object interfaces = allInterfaces(t, reinterpret_cast<object>(arguments[1]));
PROTECT(t, interfaces);
object name = reinterpret_cast<object>(arguments[2]);
PROTECT(t, name);
object virtualMap = makeHashMap(t, 0, 0);
PROTECT(t, virtualMap);
object superVtable = classVirtualTable
(t, arrayBody(t, t->m->types, Machine::ProxyType));
PROTECT(t, superVtable);
for (unsigned i = 0; i < arrayLength(t, superVtable); ++i) {
object method = arrayBody(t, superVtable, i);
hashMapInsert(t, virtualMap, method, method, methodHash);
}
unsigned virtualCount = arrayLength(t, superVtable);
object newVirtuals = makeList(t, 0, 0, 0);
PROTECT(t, newVirtuals);
object ivtable = 0;
PROTECT(t, ivtable);
object method = 0;
PROTECT(t, method);
for (unsigned i = 0; i < arrayLength(t, interfaces); ++i) {
ivtable = classVirtualTable(t, arrayBody(t, interfaces, i));
if (ivtable) {
for (unsigned j = 0; j < arrayLength(t, ivtable); ++j) {
method = arrayBody(t, ivtable, j);
method = makeMethod
(t,
methodVmFlags(t, method) | FastNative,
methodReturnCode(t, method),
methodParameterCount(t, method),
methodParameterFootprint(t, method),
methodFlags(t, method) | ACC_NATIVE,
0,
0,
methodName(t, method),
methodSpec(t, method),
0,
0,
0,
reinterpret_cast<int64_t>(proxyInvoke));
object p = hashMapFindNode
(t, virtualMap, method, methodHash, methodEqual);
if (p) {
methodOffset(t, method) = methodOffset(t, tripleFirst(t, p));
set(t, p, TripleSecond, method);
} else {
methodOffset(t, method) = virtualCount++;
listAppend(t, newVirtuals, method);
hashMapInsert(t, virtualMap, method, method, methodHash);
}
}
}
}
object vtable = makeArray(t, virtualCount);
PROTECT(t, vtable);
unsigned i = 0;
for (; i < arrayLength(t, superVtable); ++i) {
method = hashMapFind
(t, virtualMap, arrayBody(t, superVtable, i), methodHash, methodEqual);
set(t, vtable, ArrayBody + (i * BytesPerWord), method);
}
object methodTable = makeArray(t, listSize(t, newVirtuals) + 1);
PROTECT(t, methodTable);
unsigned mti = 0;
for (object p = listFront(t, newVirtuals); p; p = pairSecond(t, p)) {
set(t, vtable, ArrayBody + (i * BytesPerWord), pairFirst(t, p));
++ i;
set(t, methodTable, ArrayBody + (mti * BytesPerWord), pairFirst(t, p));
++ mti;
}
#define NAME "<init>"
object constructorName = makeByteArray(t, sizeof(NAME));
PROTECT(t, constructorName);
memcpy(&byteArrayBody(t, constructorName, 0), NAME, sizeof(NAME));
#define SPEC "(Ljava/lang/reflect/InvocationHandler;)V"
object constructorSpec = makeByteArray(t, sizeof(SPEC));
PROTECT(t, constructorSpec);
memcpy(&byteArrayBody(t, constructorSpec, 0), SPEC, sizeof(SPEC));
object constructor = makeMethod
(t,
methodVmFlags(t, method) | FastNative,
VoidField,
1,
2,
methodFlags(t, method) | ACC_NATIVE,
0,
0,
constructorName,
constructorSpec,
0,
0,
0,
reinterpret_cast<int64_t>(proxyConstruct));
set(t, methodTable, ArrayBody + (mti * BytesPerWord), constructor);
++ mti;
assert(t, arrayLength(t, vtable) == i);
assert(t, arrayLength(t, methodTable) == mti);
object itable = makeArray(t, arrayLength(t, interfaces) * 2);
PROTECT(t, itable);
object newIVTable = 0;
PROTECT(t, newIVTable);
for (unsigned i = 0; i < arrayLength(t, interfaces); ++i) {
object interface = arrayBody(t, interfaces, i);
set(t, itable, ArrayBody + ((i * 2) * BytesPerWord), interface);
ivtable = classVirtualTable(t, interface);
if (ivtable) {
newIVTable = makeArray(t, arrayLength(t, ivtable));
set(t, itable, ArrayBody + (((i * 2) + 1) * BytesPerWord), newIVTable);
for (unsigned j = 0; j < arrayLength(t, ivtable); ++j) {
method = hashMapFind
(t, virtualMap, arrayBody(t, ivtable, j), methodHash, methodEqual);
assert(t, method);
set(t, newIVTable, ArrayBody + (j * BytesPerWord), method);
}
}
}
object c = t->m->processor->makeClass
(t,
0,
0,
classFixedSize(t, arrayBody(t, t->m->types, Machine::ProxyType)),
0,
0,
classObjectMask(t, arrayBody(t, t->m->types, Machine::ProxyType)),
name,
0,
arrayBody(t, t->m->types, Machine::ProxyType),
itable,
vtable,
0,
methodTable,
0,
0,
loader,
arrayLength(t, vtable));
PROTECT(t, c);
t->m->processor->initVtable(t, c);
for (unsigned i = 0; i < arrayLength(t, methodTable); ++i) {
set(t, arrayBody(t, methodTable, i), MethodClass, c);
}
return reinterpret_cast<int64_t>(c);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Float_floatToRawIntBits
(Thread*, object, uintptr_t* arguments)
@ -1469,3 +1044,29 @@ Avian_avian_Continuations_00024Continuation_handleException
abort(t);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Singleton_getObject
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(singletonObject(t, reinterpret_cast<object>(arguments[0]), arguments[1]));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Singleton_getInt
(Thread* t, object, uintptr_t* arguments)
{
return singletonValue
(t, reinterpret_cast<object>(arguments[0]), arguments[1]);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Singleton_getLong
(Thread* t, object, uintptr_t* arguments)
{
int64_t v;
memcpy(&singletonValue
(t, reinterpret_cast<object>(arguments[0]), arguments[1]), &v, 8);
return v;
}

View File

@ -134,12 +134,6 @@ class Site {
Site* next;
};
class SitePair {
public:
Site* low;
Site* high;
};
class Stack {
public:
Stack(unsigned index, Value* value, Stack* next):

View File

@ -970,122 +970,6 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
set(t, class_, ClassInterfaceTable, interfaceTable);
}
object
parseAnnotation(Thread* t, Stream& s, object pool);
object
parseAnnotationValue(Thread* t, Stream& s, object pool)
{
unsigned tag = s.read1();
switch (tag) {
case 'Z':
return makeBoolean(t, singletonValue(t, pool, s.read2() - 1));
case 'B':
return makeByte(t, singletonValue(t, pool, s.read2() - 1));
case 'C':
return makeChar(t, singletonValue(t, pool, s.read2() - 1));
case 'S':
return makeShort(t, singletonValue(t, pool, s.read2() - 1));
case 'I':
return makeInt(t, singletonValue(t, pool, s.read2() - 1));
case 'F':
return makeFloat(t, bitsToFloat(singletonValue(t, pool, s.read2() - 1)));
case 'J': {
int64_t v; memcpy(&v, &singletonValue(t, pool, s.read2() - 1), 8);
return makeLong(t, v);
}
case 'D': {
double v; memcpy(&v, &singletonValue(t, pool, s.read2() - 1), 8);
return makeDouble(t, v);
}
case 's': {
object value = singletonObject(t, pool, s.read2() - 1);
return intern
(t, makeString(t, value, 0, byteArrayLength(t, value) - 1, 0));
}
case 'e': {
unsigned typeNameIndex = s.read2() - 1;
unsigned nameIndex = s.read2() - 1;
return makePair(t, singletonObject(t, pool, typeNameIndex),
singletonObject(t, pool, nameIndex));
}
case 'c':
return singletonObject(t, pool, s.read2() - 1);
case '@':
return parseAnnotation(t, s, pool);
case '[': {
unsigned count = s.read2();
object array = makeObjectArray(t, count);
PROTECT(t, array);
for (unsigned i = 0; i < count; ++i) {
object value = parseAnnotationValue(t, s, pool);
if (UNLIKELY(t->exception)) return 0;
set(t, array, ArrayBody + (i * BytesPerWord), value);
}
return array;
}
default: abort(t);
}
}
object
parseAnnotation(Thread* t, Stream& s, object pool)
{
PROTECT(t, pool);
unsigned typeIndex = s.read2() - 1;
unsigned elementCount = s.read2();
object array = makeObjectArray(t, (elementCount * 2) + 2);
PROTECT(t, array);
set(t, array, ArrayBody + BytesPerWord, singletonObject(t, pool, typeIndex));
for (unsigned i = 0; i < elementCount; ++i) {
set(t, array, ArrayBody + (((i * 2) + 2) * BytesPerWord),
singletonObject(t, pool, s.read2() - 1));
object value = parseAnnotationValue(t, s, pool);
if (UNLIKELY(t->exception)) return 0;
set(t, array, ArrayBody + (((i * 2) + 3) * BytesPerWord), value);
}
return array;
}
object
parseAnnotationTable(Thread* t, Stream& s, object pool)
{
PROTECT(t, pool);
unsigned annotationCount = s.read2();
object annotations = makeArray(t, annotationCount);
PROTECT(t, annotations);
for (unsigned i = 0; i < annotationCount; ++i) {
object annotation = parseAnnotation(t, s, pool);
if (UNLIKELY(t->exception)) return 0;
set(t, annotations, ArrayBody + (i * BytesPerWord), annotation);
}
return annotations;
}
void
parseFieldTable(Thread* t, Stream& s, object class_, object pool)
{
@ -1136,7 +1020,10 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
("RuntimeVisibleAnnotations"),
&byteArrayBody(t, name, 0)) == 0)
{
addendum = makeFieldAddendum(t, parseAnnotationTable(t, s, pool));
object body = makeByteArray(t, length);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)),
length);
addendum = makeAddendum(t, pool, body);
} else {
s.skip(length);
}
@ -1486,7 +1373,10 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
("RuntimeVisibleAnnotations"),
&byteArrayBody(t, name, 0)) == 0)
{
addendum = makeMethodAddendum(t, parseAnnotationTable(t, s, pool));
object body = makeByteArray(t, length);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)),
length);
addendum = makeAddendum(t, pool, body);
} else {
s.skip(length);
}
@ -1711,8 +1601,10 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool)
("RuntimeVisibleAnnotations"),
&byteArrayBody(t, name, 0)) == 0)
{
object addendum = makeClassAddendum
(t, parseAnnotationTable(t, s, pool), 0);
object body = makeByteArray(t, length);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)), length);
object addendum = makeClassAddendum(t, pool, body, 0);
set(t, class_, ClassAddendum, addendum);
} else {
@ -2189,7 +2081,6 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
tenuredWeakReferences(0),
shutdownHooks(0),
objectsToFinalize(0),
invokeMethod(0),
unsafe(false),
triedBuiltinOnLoad(false),
heapPoolIndex(0)
@ -3627,7 +3518,6 @@ visitRoots(Machine* m, Heap::Visitor* v)
v->visit(&(m->jniMethodTable));
v->visit(&(m->shutdownHooks));
v->visit(&(m->objectsToFinalize));
v->visit(&(m->invokeMethod));
for (Thread* t = m->rootThread; t; t = t->peer) {
::visitRoots(t, v);

View File

@ -1204,7 +1204,6 @@ class Machine {
object tenuredWeakReferences;
object shutdownHooks;
object objectsToFinalize;
object invokeMethod;
bool unsafe;
bool triedBuiltinOnLoad;
JavaVMVTable javaVMVTable;

View File

@ -13,19 +13,15 @@
(type accessibleObject java/lang/reflect/AccessibleObject)
(type classAddendum java/lang/Class$Addendum)
(type field java/lang/reflect/Field)
(type fieldAddendum java/lang/reflect/Field$Addendum)
(type method java/lang/reflect/Method)
(type methodAddendum java/lang/reflect/Method$Addendum)
(type proxy java/lang/reflect/Proxy)
(type pair avian/Pair)
(type addendum avian/Addendum)
(type classAddendum avian/ClassAddendum)
(type nativeMethodData
(void* function)
@ -111,6 +107,10 @@
(type array
(noassert array object body))
(type pair
(object first)
(object second))
(type continuationContext
(object next)
(object before)