mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
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:
parent
1a2eb3836c
commit
953cb69e5e
16
classpath/avian/Addendum.java
Normal file
16
classpath/avian/Addendum.java
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
17
classpath/avian/Singleton.java
Normal file
17
classpath/avian/Singleton.java
Normal 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);
|
||||
}
|
74
classpath/avian/Stream.java
Normal file
74
classpath/avian/Stream.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
481
src/builtin.cpp
481
src/builtin.cpp
@ -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;
|
||||
}
|
||||
|
@ -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):
|
||||
|
134
src/machine.cpp
134
src/machine.cpp
@ -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);
|
||||
|
@ -1204,7 +1204,6 @@ class Machine {
|
||||
object tenuredWeakReferences;
|
||||
object shutdownHooks;
|
||||
object objectsToFinalize;
|
||||
object invokeMethod;
|
||||
bool unsafe;
|
||||
bool triedBuiltinOnLoad;
|
||||
JavaVMVTable javaVMVTable;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user