mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
more Android class library work
This commit is contained in:
parent
204bbc134d
commit
42d39b1af1
@ -1,30 +0,0 @@
|
|||||||
/* Copyright (c) 2013, 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 Android {
|
|
||||||
public static VMField findField(VMClass vmClass, String name) {
|
|
||||||
if (vmClass.fieldTable != null) {
|
|
||||||
Classes.link(vmClass);
|
|
||||||
|
|
||||||
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
|
||||||
if (getName(vmClass.fieldTable[i]).equals(name)) {
|
|
||||||
return vmClass.fieldTable[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getName(VMField vmField) {
|
|
||||||
return new String(vmField.name, 0, vmField.name.length - 1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,6 +16,8 @@ import static avian.Stream.read2;
|
|||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -262,6 +264,158 @@ public class Classes {
|
|||||||
link(c, c.loader);
|
link(c, c.loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Class forName(String name, boolean initialize,
|
||||||
|
ClassLoader loader)
|
||||||
|
throws ClassNotFoundException
|
||||||
|
{
|
||||||
|
if (loader == null) {
|
||||||
|
loader = Class.class.getClassLoader();
|
||||||
|
}
|
||||||
|
Class c = loader.loadClass(name);
|
||||||
|
VMClass vmc = SystemClassLoader.vmClass(c);
|
||||||
|
Classes.link(vmc, loader);
|
||||||
|
if (initialize) {
|
||||||
|
Classes.initialize(vmc);
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class forCanonicalName(String name) {
|
||||||
|
return forCanonicalName(null, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class forCanonicalName(ClassLoader loader, String name) {
|
||||||
|
try {
|
||||||
|
if (name.startsWith("[")) {
|
||||||
|
return forName(name, true, loader);
|
||||||
|
} else if (name.startsWith("L")) {
|
||||||
|
return forName(name.substring(1, name.length() - 1), true, loader);
|
||||||
|
} else {
|
||||||
|
if (name.length() == 1) {
|
||||||
|
return SystemClassLoader.getClass
|
||||||
|
(Classes.primitiveClass(name.charAt(0)));
|
||||||
|
} else {
|
||||||
|
throw new ClassNotFoundException(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class[] getParameterTypes(VMMethod vmMethod) {
|
||||||
|
int count = vmMethod.parameterCount;
|
||||||
|
|
||||||
|
Class[] types = new Class[count];
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
String spec = new String
|
||||||
|
(vmMethod.spec, 1, vmMethod.spec.length - 1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < spec.length(); ++i) {
|
||||||
|
char c = spec.charAt(i);
|
||||||
|
if (c == ')') {
|
||||||
|
break;
|
||||||
|
} else if (c == 'L') {
|
||||||
|
int start = i + 1;
|
||||||
|
i = next(';', spec, start);
|
||||||
|
String name = spec.substring(start, i).replace('/', '.');
|
||||||
|
types[index++] = Class.forName(name, true, vmMethod.class_.loader);
|
||||||
|
} else if (c == '[') {
|
||||||
|
int start = i;
|
||||||
|
while (spec.charAt(i) == '[') ++i;
|
||||||
|
|
||||||
|
if (spec.charAt(i) == 'L') {
|
||||||
|
i = next(';', spec, i + 1);
|
||||||
|
String name = spec.substring(start, i).replace('/', '.');
|
||||||
|
types[index++] = Class.forName
|
||||||
|
(name, true, vmMethod.class_.loader);
|
||||||
|
} else {
|
||||||
|
String name = spec.substring(start, i + 1);
|
||||||
|
types[index++] = forCanonicalName(vmMethod.class_.loader, name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String name = spec.substring(i, i + 1);
|
||||||
|
types[index++] = forCanonicalName(vmMethod.class_.loader, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
public static int findField(VMClass vmClass, String name) {
|
||||||
|
if (vmClass.fieldTable != null) {
|
||||||
|
Classes.link(vmClass);
|
||||||
|
|
||||||
|
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
||||||
|
if (toString(vmClass.fieldTable[i].name).equals(name)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(byte[] array) {
|
||||||
|
return new String(array, 0, array.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean match(Class[] a, Class[] b) {
|
||||||
|
if (a.length == b.length) {
|
||||||
|
for (int i = 0; i < a.length; ++i) {
|
||||||
|
if (! a[i].isAssignableFrom(b[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findMethod(VMClass vmClass, String name,
|
||||||
|
Class[] parameterTypes)
|
||||||
|
{
|
||||||
|
if (vmClass.methodTable != null) {
|
||||||
|
Classes.link(vmClass);
|
||||||
|
|
||||||
|
if (parameterTypes == null) {
|
||||||
|
parameterTypes = new Class[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < vmClass.methodTable.length; ++i) {
|
||||||
|
if (toString(vmClass.methodTable[i].name).equals(name)
|
||||||
|
&& match(parameterTypes,
|
||||||
|
getParameterTypes(vmClass.methodTable[i])))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Annotation getAnnotation(ClassLoader loader, Object[] a) {
|
||||||
|
if (a[0] == null) {
|
||||||
|
a[0] = Proxy.newProxyInstance
|
||||||
|
(loader, new Class[] { (Class) a[1] },
|
||||||
|
new AnnotationInvocationHandler(a));
|
||||||
|
}
|
||||||
|
return (Annotation) a[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native Method makeMethod(Class c, int slot);
|
||||||
|
|
||||||
private static native void acquireClassLock();
|
private static native void acquireClassLock();
|
||||||
|
|
||||||
private static native void releaseClassLock();
|
private static native void releaseClassLock();
|
||||||
|
@ -28,6 +28,8 @@ public class SystemClassLoader extends ClassLoader {
|
|||||||
|
|
||||||
public static native Class getClass(VMClass vmClass);
|
public static native Class getClass(VMClass vmClass);
|
||||||
|
|
||||||
|
public static native VMClass vmClass(Class jClass);
|
||||||
|
|
||||||
private native VMClass findLoadedVMClass(String name);
|
private native VMClass findLoadedVMClass(String name);
|
||||||
|
|
||||||
protected Class reallyFindLoadedClass(String name){
|
protected Class reallyFindLoadedClass(String name){
|
||||||
@ -35,6 +37,30 @@ public class SystemClassLoader extends ClassLoader {
|
|||||||
return c == null ? null : getClass(c);
|
return c == null ? null : getClass(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Class loadClass(String name, boolean resolve)
|
||||||
|
throws ClassNotFoundException
|
||||||
|
{
|
||||||
|
Class c = findLoadedClass(name);
|
||||||
|
if (c == null) {
|
||||||
|
ClassLoader parent = getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
try {
|
||||||
|
c = parent.loadClass(name);
|
||||||
|
} catch (ClassNotFoundException ok) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == null) {
|
||||||
|
c = findClass(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resolve) {
|
||||||
|
resolveClass(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
private native String resourceURLPrefix(String name);
|
private native String resourceURLPrefix(String name);
|
||||||
|
|
||||||
protected URL findResource(String name) {
|
protected URL findResource(String name) {
|
||||||
|
@ -145,38 +145,7 @@ public final class Class <T> implements Type, AnnotatedElement {
|
|||||||
ClassLoader loader)
|
ClassLoader loader)
|
||||||
throws ClassNotFoundException
|
throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
if (loader == null) {
|
return Classes.forName(name, initialize, loader);
|
||||||
loader = Class.class.vmClass.loader;
|
|
||||||
}
|
|
||||||
Class c = loader.loadClass(name);
|
|
||||||
Classes.link(c.vmClass, loader);
|
|
||||||
if (initialize) {
|
|
||||||
Classes.initialize(c.vmClass);
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Class forCanonicalName(String name) {
|
|
||||||
return forCanonicalName(null, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Class forCanonicalName(ClassLoader loader, String name) {
|
|
||||||
try {
|
|
||||||
if (name.startsWith("[")) {
|
|
||||||
return forName(name, true, loader);
|
|
||||||
} else if (name.startsWith("L")) {
|
|
||||||
return forName(name.substring(1, name.length() - 1), true, loader);
|
|
||||||
} else {
|
|
||||||
if (name.length() == 1) {
|
|
||||||
return SystemClassLoader.getClass
|
|
||||||
(Classes.primitiveClass(name.charAt(0)));
|
|
||||||
} else {
|
|
||||||
throw new ClassNotFoundException(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getComponentType() {
|
public Class getComponentType() {
|
||||||
@ -211,84 +180,36 @@ public final class Class <T> implements Type, AnnotatedElement {
|
|||||||
return Classes.isAssignableFrom(vmClass, c.vmClass);
|
return Classes.isAssignableFrom(vmClass, c.vmClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Field findField(VMClass vmClass, String name) {
|
|
||||||
if (vmClass.fieldTable != null) {
|
|
||||||
Classes.link(vmClass);
|
|
||||||
|
|
||||||
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
|
||||||
if (Field.getName(vmClass.fieldTable[i]).equals(name)) {
|
|
||||||
return new Field(vmClass.fieldTable[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Field getDeclaredField(String name) throws NoSuchFieldException {
|
public Field getDeclaredField(String name) throws NoSuchFieldException {
|
||||||
Field f = findField(vmClass, name);
|
int index = Classes.findField(vmClass, name);
|
||||||
if (f == null) {
|
if (index < 0) {
|
||||||
throw new NoSuchFieldException(name);
|
throw new NoSuchFieldException(name);
|
||||||
} else {
|
} else {
|
||||||
return f;
|
return new Field(vmClass.fieldTable[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Field getField(String name) throws NoSuchFieldException {
|
public Field getField(String name) throws NoSuchFieldException {
|
||||||
for (VMClass c = vmClass; c != null; c = c.super_) {
|
for (VMClass c = vmClass; c != null; c = c.super_) {
|
||||||
Field f = findField(c, name);
|
int index = findField(c, name);
|
||||||
if (f != null) {
|
if (index >= 0) {
|
||||||
return f;
|
return new Field(vmClass.fieldTable[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new NoSuchFieldException(name);
|
throw new NoSuchFieldException(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean match(Class[] a, Class[] b) {
|
|
||||||
if (a.length == b.length) {
|
|
||||||
for (int i = 0; i < a.length; ++i) {
|
|
||||||
if (! a[i].isAssignableFrom(b[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Method findMethod(VMClass vmClass, String name,
|
|
||||||
Class[] parameterTypes)
|
|
||||||
{
|
|
||||||
if (vmClass.methodTable != null) {
|
|
||||||
Classes.link(vmClass);
|
|
||||||
|
|
||||||
if (parameterTypes == null) {
|
|
||||||
parameterTypes = new Class[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < vmClass.methodTable.length; ++i) {
|
|
||||||
if (Method.getName(vmClass.methodTable[i]).equals(name)
|
|
||||||
&& match(parameterTypes,
|
|
||||||
Method.getParameterTypes(vmClass.methodTable[i])))
|
|
||||||
{
|
|
||||||
return new Method(vmClass.methodTable[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Method getDeclaredMethod(String name, Class ... parameterTypes)
|
public Method getDeclaredMethod(String name, Class ... parameterTypes)
|
||||||
throws NoSuchMethodException
|
throws NoSuchMethodException
|
||||||
{
|
{
|
||||||
if (name.startsWith("<")) {
|
if (name.startsWith("<")) {
|
||||||
throw new NoSuchMethodException(name);
|
throw new NoSuchMethodException(name);
|
||||||
}
|
}
|
||||||
Method m = findMethod(vmClass, name, parameterTypes);
|
int index = Classes.findMethod(vmClass, name, parameterTypes);
|
||||||
if (m == null) {
|
if (index < 0) {
|
||||||
throw new NoSuchMethodException(name);
|
throw new NoSuchMethodException(name);
|
||||||
} else {
|
} else {
|
||||||
return m;
|
return new Method(vmClass.methodTable[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,9 +220,9 @@ public final class Class <T> implements Type, AnnotatedElement {
|
|||||||
throw new NoSuchMethodException(name);
|
throw new NoSuchMethodException(name);
|
||||||
}
|
}
|
||||||
for (VMClass c = vmClass; c != null; c = c.super_) {
|
for (VMClass c = vmClass; c != null; c = c.super_) {
|
||||||
Method m = findMethod(c, name, parameterTypes);
|
int index = findMethod(c, name, parameterTypes);
|
||||||
if (m != null) {
|
if (index >= 0) {
|
||||||
return m;
|
return new Method(vmClass.methodTable[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new NoSuchMethodException(name);
|
throw new NoSuchMethodException(name);
|
||||||
|
@ -58,61 +58,8 @@ public class Method<T> extends AccessibleObject implements Member {
|
|||||||
return new String(vmMethod.spec, 0, vmMethod.spec.length - 1, false);
|
return new String(vmMethod.spec, 0, vmMethod.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;
|
|
||||||
}
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class[] getParameterTypes() {
|
public Class[] getParameterTypes() {
|
||||||
return getParameterTypes(vmMethod);
|
return Classes.getParameterTypes(vmMethod);
|
||||||
}
|
|
||||||
|
|
||||||
public static Class[] getParameterTypes(VMMethod vmMethod) {
|
|
||||||
int count = vmMethod.parameterCount;
|
|
||||||
|
|
||||||
Class[] types = new Class[count];
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
String spec = new String
|
|
||||||
(vmMethod.spec, 1, vmMethod.spec.length - 1, false);
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < spec.length(); ++i) {
|
|
||||||
char c = spec.charAt(i);
|
|
||||||
if (c == ')') {
|
|
||||||
break;
|
|
||||||
} else if (c == 'L') {
|
|
||||||
int start = i + 1;
|
|
||||||
i = next(';', spec, start);
|
|
||||||
String name = spec.substring(start, i).replace('/', '.');
|
|
||||||
types[index++] = Class.forName(name, true, vmMethod.class_.loader);
|
|
||||||
} else if (c == '[') {
|
|
||||||
int start = i;
|
|
||||||
while (spec.charAt(i) == '[') ++i;
|
|
||||||
|
|
||||||
if (spec.charAt(i) == 'L') {
|
|
||||||
i = next(';', spec, i + 1);
|
|
||||||
String name = spec.substring(start, i).replace('/', '.');
|
|
||||||
types[index++] = Class.forName
|
|
||||||
(name, true, vmMethod.class_.loader);
|
|
||||||
} else {
|
|
||||||
String name = spec.substring(start, i + 1);
|
|
||||||
types[index++] = Class.forCanonicalName
|
|
||||||
(vmMethod.class_.loader, name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String name = spec.substring(i, i + 1);
|
|
||||||
types[index++] = Class.forCanonicalName
|
|
||||||
(vmMethod.class_.loader, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return types;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object invoke(Object instance, Object ... arguments)
|
public Object invoke(Object instance, Object ... arguments)
|
||||||
@ -160,22 +107,13 @@ public class Method<T> extends AccessibleObject implements Member {
|
|||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Annotation getAnnotation(Object[] a) {
|
|
||||||
if (a[0] == null) {
|
|
||||||
a[0] = Proxy.newProxyInstance
|
|
||||||
(vmMethod.class_.loader, new Class[] { (Class) a[1] },
|
|
||||||
new AnnotationInvocationHandler(a));
|
|
||||||
}
|
|
||||||
return (Annotation) a[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends Annotation> T getAnnotation(Class<T> class_) {
|
public <T extends Annotation> T getAnnotation(Class<T> class_) {
|
||||||
if (vmMethod.hasAnnotations()) {
|
if (vmMethod.hasAnnotations()) {
|
||||||
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
|
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
|
||||||
for (int i = 0; i < table.length; ++i) {
|
for (int i = 0; i < table.length; ++i) {
|
||||||
Object[] a = (Object[]) table[i];
|
Object[] a = (Object[]) table[i];
|
||||||
if (a[1] == class_) {
|
if (a[1] == class_) {
|
||||||
return (T) getAnnotation(a);
|
return (T) Classes.getAnnotation(vmMethod.class_.loader, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,7 +125,8 @@ public class Method<T> extends AccessibleObject implements Member {
|
|||||||
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
|
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
|
||||||
Annotation[] array = new Annotation[table.length];
|
Annotation[] array = new Annotation[table.length];
|
||||||
for (int i = 0; i < table.length; ++i) {
|
for (int i = 0; i < table.length; ++i) {
|
||||||
array[i] = getAnnotation((Object[]) table[i]);
|
array[i] = Classes.getAnnotation
|
||||||
|
(vmMethod.class_.loader, (Object[]) table[i]);
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,6 +16,9 @@ import static avian.Stream.write4;
|
|||||||
import static avian.Stream.set4;
|
import static avian.Stream.set4;
|
||||||
import static avian.Assembler.*;
|
import static avian.Assembler.*;
|
||||||
|
|
||||||
|
import avian.SystemClassLoader;
|
||||||
|
import avian.Classes;
|
||||||
|
|
||||||
import avian.ConstantPool;
|
import avian.ConstantPool;
|
||||||
import avian.ConstantPool.PoolEntry;
|
import avian.ConstantPool.PoolEntry;
|
||||||
|
|
||||||
@ -87,26 +90,15 @@ public class Proxy {
|
|||||||
|
|
||||||
write1(out, aload_0);
|
write1(out, aload_0);
|
||||||
|
|
||||||
write1(out, new_);
|
|
||||||
write2(out, ConstantPool.addClass(pool, "java/lang/reflect/Method") + 1);
|
|
||||||
write1(out, dup);
|
|
||||||
write1(out, ldc_w);
|
write1(out, ldc_w);
|
||||||
write2(out, ConstantPool.addClass(pool, className) + 1);
|
write2(out, ConstantPool.addClass(pool, className) + 1);
|
||||||
write1(out, getfield);
|
|
||||||
write2(out, ConstantPool.addFieldRef
|
|
||||||
(pool, "java/lang/Class",
|
|
||||||
"vmClass", "Lavian/VMClass;") + 1);
|
|
||||||
write1(out, getfield);
|
|
||||||
write2(out, ConstantPool.addFieldRef
|
|
||||||
(pool, "avian/VMClass",
|
|
||||||
"methodTable", "[Lavian/VMMethod;") + 1);
|
|
||||||
write1(out, ldc_w);
|
write1(out, ldc_w);
|
||||||
write2(out, ConstantPool.addInteger(pool, index) + 1);
|
write2(out, ConstantPool.addInteger(pool, index) + 1);
|
||||||
write1(out, aaload);
|
write1(out, invokestatic);
|
||||||
write1(out, invokespecial);
|
|
||||||
write2(out, ConstantPool.addMethodRef
|
write2(out, ConstantPool.addMethodRef
|
||||||
(pool, "java/lang/reflect/Method",
|
(pool, "avian/Classes",
|
||||||
"<init>", "(Lavian/VMMethod;)V") + 1);
|
"makeMethod", "(Ljava/lang/Class;I)Ljava/lang/reflect/Method;")
|
||||||
|
+ 1);
|
||||||
|
|
||||||
write1(out, ldc_w);
|
write1(out, ldc_w);
|
||||||
write2(out, ConstantPool.addInteger(pool, parameterCount) + 1);
|
write2(out, ConstantPool.addInteger(pool, parameterCount) + 1);
|
||||||
@ -363,10 +355,11 @@ public class Proxy {
|
|||||||
|
|
||||||
Map<String,avian.VMMethod> virtualMap = new HashMap();
|
Map<String,avian.VMMethod> virtualMap = new HashMap();
|
||||||
for (Class c: interfaces) {
|
for (Class c: interfaces) {
|
||||||
avian.VMMethod[] ivtable = c.vmClass.virtualTable;
|
avian.VMMethod[] ivtable = SystemClassLoader.vmClass(c).virtualTable;
|
||||||
if (ivtable != null) {
|
if (ivtable != null) {
|
||||||
for (avian.VMMethod m: ivtable) {
|
for (avian.VMMethod m: ivtable) {
|
||||||
virtualMap.put(Method.getName(m) + Method.getSpec(m), m);
|
virtualMap.put
|
||||||
|
(Classes.toString(m.name) + Classes.toString(m.spec), m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,15 +369,15 @@ public class Proxy {
|
|||||||
for (avian.VMMethod m: virtualMap.values()) {
|
for (avian.VMMethod m: virtualMap.values()) {
|
||||||
methodTable[i] = new MethodData
|
methodTable[i] = new MethodData
|
||||||
(0,
|
(0,
|
||||||
ConstantPool.addUtf8(pool, Method.getName(m)),
|
ConstantPool.addUtf8(pool, Classes.toString(m.name)),
|
||||||
ConstantPool.addUtf8(pool, Method.getSpec(m)),
|
ConstantPool.addUtf8(pool, Classes.toString(m.spec)),
|
||||||
makeInvokeCode(pool, name, m.spec, m.parameterCount,
|
makeInvokeCode(pool, name, m.spec, m.parameterCount,
|
||||||
m.parameterFootprint, i));
|
m.parameterFootprint, i));
|
||||||
++ i;
|
++ i;
|
||||||
}
|
}
|
||||||
|
|
||||||
methodTable[i++] = new MethodData
|
methodTable[i++] = new MethodData
|
||||||
(0,
|
(Modifier.PUBLIC,
|
||||||
ConstantPool.addUtf8(pool, "<init>"),
|
ConstantPool.addUtf8(pool, "<init>"),
|
||||||
ConstantPool.addUtf8
|
ConstantPool.addUtf8
|
||||||
(pool, "(Ljava/lang/reflect/InvocationHandler;)V"),
|
(pool, "(Ljava/lang/reflect/InvocationHandler;)V"),
|
||||||
|
7
makefile
7
makefile
@ -163,7 +163,6 @@ ifneq ($(android),)
|
|||||||
-I$(android)/libcore/include \
|
-I$(android)/libcore/include \
|
||||||
-I$(build)/android-src/external/fdlibm \
|
-I$(build)/android-src/external/fdlibm \
|
||||||
-I$(build)/android-src \
|
-I$(build)/android-src \
|
||||||
-fpermissive \
|
|
||||||
-fno-exceptions \
|
-fno-exceptions \
|
||||||
-DHAVE_SYS_UIO_H \
|
-DHAVE_SYS_UIO_H \
|
||||||
-D_FILE_OFFSET_BITS=64 \
|
-D_FILE_OFFSET_BITS=64 \
|
||||||
@ -1200,6 +1199,7 @@ ifneq ($(classpath),avian)
|
|||||||
# them to synthesize a class:
|
# them to synthesize a class:
|
||||||
classpath-sources := \
|
classpath-sources := \
|
||||||
$(classpath-src)/avian/Addendum.java \
|
$(classpath-src)/avian/Addendum.java \
|
||||||
|
$(classpath-src)/avian/AnnotationInvocationHandler.java \
|
||||||
$(classpath-src)/avian/Assembler.java \
|
$(classpath-src)/avian/Assembler.java \
|
||||||
$(classpath-src)/avian/Callback.java \
|
$(classpath-src)/avian/Callback.java \
|
||||||
$(classpath-src)/avian/CallbackReceiver.java \
|
$(classpath-src)/avian/CallbackReceiver.java \
|
||||||
@ -1230,7 +1230,7 @@ ifneq ($(classpath),avian)
|
|||||||
$(classpath-src)/java/net/StandardProtocolFamily.java \
|
$(classpath-src)/java/net/StandardProtocolFamily.java \
|
||||||
$(classpath-src)/sun/misc/Cleaner.java \
|
$(classpath-src)/sun/misc/Cleaner.java \
|
||||||
$(classpath-src)/sun/misc/Unsafe.java \
|
$(classpath-src)/sun/misc/Unsafe.java \
|
||||||
$(classpath-src)/avian/Android.java
|
$(classpath-src)/java/lang/reflect/Proxy.java
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
classpath-sources := $(shell find $(classpath-src) -name '*.java')
|
classpath-sources := $(shell find $(classpath-src) -name '*.java')
|
||||||
@ -1432,7 +1432,8 @@ $(build)/android.dep: $(luni-javas) $(dalvik-javas) $(xml-javas)
|
|||||||
find $(build)/android-src -name '*.java' > $(build)/android.txt
|
find $(build)/android-src -name '*.java' > $(build)/android.txt
|
||||||
$(javac) -Xmaxerrs 1000 -d $(build)/android -sourcepath $(luni-java) \
|
$(javac) -Xmaxerrs 1000 -d $(build)/android -sourcepath $(luni-java) \
|
||||||
@$(build)/android.txt
|
@$(build)/android.txt
|
||||||
rm $(build)/android/sun/misc/Unsafe*
|
rm $(build)/android/sun/misc/Unsafe* \
|
||||||
|
$(build)/android/java/lang/reflect/Proxy*
|
||||||
cp -r $(build)/android/* $(classpath-build)
|
cp -r $(build)/android/* $(classpath-build)
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
|
||||||
|
@ -50,6 +50,15 @@ resolveSystemClassThrow(Thread* t, object loader, object spec)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_avian_Classes_initialize
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
|
initClass(t, this_);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Avian_avian_Classes_acquireClassLock
|
Avian_avian_Classes_acquireClassLock
|
||||||
(Thread* t, object, uintptr_t*)
|
(Thread* t, object, uintptr_t*)
|
||||||
@ -75,6 +84,26 @@ Avian_avian_Classes_resolveVMClass
|
|||||||
(resolveClass(t, loader, spec, true, Machine::ClassNotFoundExceptionType));
|
(resolveClass(t, loader, spec, true, Machine::ClassNotFoundExceptionType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_avian_Classes_defineVMClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object loader = reinterpret_cast<object>(arguments[0]);
|
||||||
|
object b = reinterpret_cast<object>(arguments[1]);
|
||||||
|
int offset = arguments[2];
|
||||||
|
int length = arguments[3];
|
||||||
|
|
||||||
|
uint8_t* buffer = static_cast<uint8_t*>
|
||||||
|
(t->m->heap->allocate(length));
|
||||||
|
|
||||||
|
THREAD_RESOURCE2(t, uint8_t*, buffer, int, length,
|
||||||
|
t->m->heap->free(buffer, length));
|
||||||
|
|
||||||
|
memcpy(buffer, &byteArrayBody(t, b, offset), length);
|
||||||
|
|
||||||
|
return reinterpret_cast<int64_t>(defineClass(t, loader, buffer, length));
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_avian_SystemClassLoader_findLoadedVMClass
|
Avian_avian_SystemClassLoader_findLoadedVMClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
@ -85,6 +114,14 @@ Avian_avian_SystemClassLoader_findLoadedVMClass
|
|||||||
return search(t, loader, name, findLoadedClass, true);
|
return search(t, loader, name, findLoadedClass, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_avian_SystemClassLoader_vmClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<int64_t>
|
||||||
|
(jclassVmClass(t, reinterpret_cast<object>(arguments[0])));
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_avian_SystemClassLoader_findVMClass
|
Avian_avian_SystemClassLoader_findVMClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
@ -26,6 +26,24 @@ namespace {
|
|||||||
|
|
||||||
namespace local {
|
namespace local {
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
loadLibrary(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object name = reinterpret_cast<object>(arguments[1]);
|
||||||
|
|
||||||
|
unsigned length = stringLength(t, name);
|
||||||
|
THREAD_RUNTIME_ARRAY(t, char, n, length + 1);
|
||||||
|
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
||||||
|
|
||||||
|
loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
appLoader(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>(root(t, Machine::AppLoader));
|
||||||
|
}
|
||||||
|
|
||||||
class MyClasspath : public Classpath {
|
class MyClasspath : public Classpath {
|
||||||
public:
|
public:
|
||||||
MyClasspath(Allocator* allocator):
|
MyClasspath(Allocator* allocator):
|
||||||
@ -85,6 +103,21 @@ class MyClasspath : public Classpath {
|
|||||||
setObjectClass(t, thread, type(t, Machine::ThreadType));
|
setObjectClass(t, thread, type(t, Machine::ThreadType));
|
||||||
threadPriority(t, thread) = NormalPriority;
|
threadPriority(t, thread) = NormalPriority;
|
||||||
threadGroup(t, thread) = group;
|
threadGroup(t, thread) = group;
|
||||||
|
PROTECT(t, thread);
|
||||||
|
|
||||||
|
{ object listClass = resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/util/ArrayList");
|
||||||
|
PROTECT(t, listClass);
|
||||||
|
|
||||||
|
object instance = makeNew(t, listClass);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
object constructor = resolveMethod(t, listClass, "<init>", "()V");
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, constructor, instance);
|
||||||
|
|
||||||
|
set(t, thread, ThreadInterruptActions, instance);
|
||||||
|
}
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
@ -138,6 +171,30 @@ class MyClasspath : public Classpath {
|
|||||||
virtual void
|
virtual void
|
||||||
boot(Thread* t)
|
boot(Thread* t)
|
||||||
{
|
{
|
||||||
|
{ object runtimeClass = resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/lang/Runtime", false);
|
||||||
|
|
||||||
|
if (runtimeClass) {
|
||||||
|
PROTECT(t, runtimeClass);
|
||||||
|
|
||||||
|
intercept(t, runtimeClass, "loadLibrary",
|
||||||
|
"(Ljava/lang/String;Ljava/lang/ClassLoader;)V",
|
||||||
|
voidPointer(loadLibrary));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ object classLoaderClass = resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/lang/ClassLoader", false);
|
||||||
|
|
||||||
|
if (classLoaderClass) {
|
||||||
|
PROTECT(t, classLoaderClass);
|
||||||
|
|
||||||
|
intercept(t, classLoaderClass, "createSystemClassLoader",
|
||||||
|
"()Ljava/lang/ClassLoader;",
|
||||||
|
voidPointer(appLoader));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0);
|
JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +210,48 @@ class MyClasspath : public Classpath {
|
|||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
||||||
|
{
|
||||||
|
object c = resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/nio/ReadWriteDirectByteBuffer");
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
object instance = makeNew(t, c);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
object constructor = resolveMethod(t, c, "<init>", "(II)V");
|
||||||
|
|
||||||
|
t->m->processor->invoke
|
||||||
|
(t, constructor, instance, reinterpret_cast<int>(p),
|
||||||
|
static_cast<int>(capacity));
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void*
|
||||||
|
getDirectBufferAddress(Thread* t, object b)
|
||||||
|
{
|
||||||
|
PROTECT(t, b);
|
||||||
|
|
||||||
|
object field = resolveField
|
||||||
|
(t, objectClass(t, b), "effectiveDirectAddress", "I");
|
||||||
|
|
||||||
|
return reinterpret_cast<void*>
|
||||||
|
(fieldAtOffset<int32_t>(b, fieldOffset(t, field)));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int64_t
|
||||||
|
getDirectBufferCapacity(Thread* t, object b)
|
||||||
|
{
|
||||||
|
PROTECT(t, b);
|
||||||
|
|
||||||
|
object field = resolveField
|
||||||
|
(t, objectClass(t, b), "capacity", "I");
|
||||||
|
|
||||||
|
return fieldAtOffset<int32_t>(b, fieldOffset(t, field));
|
||||||
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
dispose()
|
dispose()
|
||||||
{
|
{
|
||||||
@ -162,6 +261,47 @@ class MyClasspath : public Classpath {
|
|||||||
Allocator* allocator;
|
Allocator* allocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
object
|
||||||
|
makeMethodOrConstructor(Thread* t, object c, unsigned index)
|
||||||
|
{
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
object method = arrayBody
|
||||||
|
(t, classMethodTable(t, jclassVmClass(t, c)), index);
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
unsigned parameterCount;
|
||||||
|
unsigned returnTypeSpec;
|
||||||
|
object parameterTypes = resolveParameterJTypes
|
||||||
|
(t, classLoader(t, methodClass(t, method)), methodSpec(t, method),
|
||||||
|
¶meterCount, &returnTypeSpec);
|
||||||
|
PROTECT(t, parameterTypes);
|
||||||
|
|
||||||
|
object returnType = resolveJType
|
||||||
|
(t, classLoader(t, methodClass(t, method)), reinterpret_cast<char*>
|
||||||
|
(&byteArrayBody(t, methodSpec(t, method), returnTypeSpec)),
|
||||||
|
byteArrayLength(t, methodSpec(t, method)) - 1 - returnTypeSpec);
|
||||||
|
PROTECT(t, returnType);
|
||||||
|
|
||||||
|
object exceptionTypes = resolveExceptionJTypes
|
||||||
|
(t, classLoader(t, methodClass(t, method)), methodAddendum(t, method));
|
||||||
|
|
||||||
|
if (byteArrayBody(t, methodName(t, method), 0) == '<') {
|
||||||
|
return makeJconstructor
|
||||||
|
(t, 0, c, parameterTypes, exceptionTypes, 0, 0, 0, 0, index);
|
||||||
|
} else {
|
||||||
|
PROTECT(t, exceptionTypes);
|
||||||
|
|
||||||
|
object name = t->m->classpath->makeString
|
||||||
|
(t, methodName(t, method), 0,
|
||||||
|
byteArrayLength(t, methodName(t, method)) - 1);
|
||||||
|
|
||||||
|
return makeJmethod
|
||||||
|
(t, 0, index, c, name, parameterTypes, exceptionTypes, returnType, 0, 0,
|
||||||
|
0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace local
|
} // namespace local
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -346,6 +486,23 @@ Avian_java_lang_String_fastIndexOf
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_newInstanceImpl
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[0]));
|
||||||
|
|
||||||
|
object method = resolveMethod(t, c, "<init>", "()V");
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
object instance = makeNew(t, c);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, method, instance);
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>(instance);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Class_getComponentType
|
Avian_java_lang_Class_getComponentType
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
@ -366,6 +523,25 @@ Avian_java_lang_Class_getComponentType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_classForName
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object name = reinterpret_cast<object>(arguments[0]);
|
||||||
|
PROTECT(t, name);
|
||||||
|
|
||||||
|
object loader = reinterpret_cast<object>(arguments[2]);
|
||||||
|
PROTECT(t, loader);
|
||||||
|
|
||||||
|
object method = resolveMethod
|
||||||
|
(t, root(t, Machine::BootLoader), "avian/Classes", "forName",
|
||||||
|
"(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(t->m->processor->invoke
|
||||||
|
(t, method, 0, name, static_cast<int>(arguments[1]), loader));
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Class_getDeclaredField
|
Avian_java_lang_Class_getDeclaredField
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
@ -377,13 +553,17 @@ Avian_java_lang_Class_getDeclaredField
|
|||||||
PROTECT(t, name);
|
PROTECT(t, name);
|
||||||
|
|
||||||
object method = resolveMethod
|
object method = resolveMethod
|
||||||
(t, root(t, Machine::BootLoader), "avian/Android", "findField",
|
(t, root(t, Machine::BootLoader), "avian/Classes", "findField",
|
||||||
"(Lavian/VMClass;Ljava/lang/String;)Lavian/VMField;");
|
"(Lavian/VMClass;Ljava/lang/String;)I");
|
||||||
|
|
||||||
object field = t->m->processor->invoke
|
int index = intValue
|
||||||
(t, method, 0, jclassVmClass(t, c), name);
|
(t, t->m->processor->invoke
|
||||||
|
(t, method, 0, jclassVmClass(t, c), name));
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
object field = arrayBody
|
||||||
|
(t, classFieldTable(t, jclassVmClass(t, c)), index);
|
||||||
|
|
||||||
if (field) {
|
|
||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
|
|
||||||
object type = resolveClassBySpec
|
object type = resolveClassBySpec
|
||||||
@ -409,6 +589,75 @@ Avian_java_lang_Class_getDeclaredField
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getDeclaredConstructorOrMethod
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object c = reinterpret_cast<object>(arguments[0]);
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
object name = reinterpret_cast<object>(arguments[1]);
|
||||||
|
PROTECT(t, name);
|
||||||
|
|
||||||
|
object parameterTypes = reinterpret_cast<object>(arguments[2]);
|
||||||
|
PROTECT(t, parameterTypes);
|
||||||
|
|
||||||
|
object method = resolveMethod
|
||||||
|
(t, root(t, Machine::BootLoader), "avian/Classes", "findMethod",
|
||||||
|
"(Lavian/VMClass;Ljava/lang/String;[Ljava/lang/Class;)I");
|
||||||
|
|
||||||
|
int index = intValue
|
||||||
|
(t, t->m->processor->invoke
|
||||||
|
(t, method, 0, jclassVmClass(t, c), name, parameterTypes));
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(local::makeMethodOrConstructor(t, c, index));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_avian_SystemClassLoader_findLoadedVMClass
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMClassLoader_findLoadedClass
|
||||||
|
(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t v = Avian_avian_SystemClassLoader_findLoadedVMClass
|
||||||
|
(t, method, arguments);
|
||||||
|
|
||||||
|
if (v) {
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(getJClass(t, reinterpret_cast<object>(v)));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_avian_Classes_defineVMClass
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMClassLoader_defineClass__Ljava_lang_ClassLoader_2Ljava_lang_String_2_3BII
|
||||||
|
(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
uintptr_t args[]
|
||||||
|
= { arguments[0], arguments[2], arguments[3], arguments[4] };
|
||||||
|
|
||||||
|
int64_t v = Avian_avian_Classes_defineVMClass(t, method, args);
|
||||||
|
|
||||||
|
if (v) {
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(getJClass(t, reinterpret_cast<object>(v)));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_dalvik_system_VMRuntime_bootClassPath
|
Avian_dalvik_system_VMRuntime_bootClassPath
|
||||||
(Thread* t, object, uintptr_t*)
|
(Thread* t, object, uintptr_t*)
|
||||||
@ -467,3 +716,456 @@ Avian_java_lang_VMThread_currentThread
|
|||||||
{
|
{
|
||||||
return reinterpret_cast<uintptr_t>(t->javaThread);
|
return reinterpret_cast<uintptr_t>(t->javaThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_dalvik_system_VMStack_getCallingClassLoader
|
||||||
|
(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
class Visitor: public Processor::StackVisitor {
|
||||||
|
public:
|
||||||
|
Visitor(Thread* t):
|
||||||
|
t(t), loader(0), counter(2)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual bool visit(Processor::StackWalker* walker) {
|
||||||
|
if (counter--) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this->loader = classLoader(t, methodClass(t, walker->method()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread* t;
|
||||||
|
object loader;
|
||||||
|
unsigned counter;
|
||||||
|
} v(t);
|
||||||
|
|
||||||
|
t->m->processor->walkStack(t, &v);
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>(v.loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Math_min
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return min(static_cast<int>(arguments[0]), static_cast<int>(arguments[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Math_max
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return max(static_cast<int>(arguments[0]), static_cast<int>(arguments[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Object_getClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(getJClass(t, objectClass(t, reinterpret_cast<object>(arguments[0]))));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Object_hashCode
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return objectHash(t, reinterpret_cast<object>(arguments[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Object_internalClone
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(clone(t, reinterpret_cast<object>(arguments[1])));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getModifiers
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return classFlags
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getSuperclass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[0]));
|
||||||
|
if (classFlags(t, c) & ACC_INTERFACE) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
object s = classSuper(t, c);
|
||||||
|
return s ? reinterpret_cast<uintptr_t>(getJClass(t, s)) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_desiredAssertionStatus
|
||||||
|
(Thread*, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getNameNative
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object name = className
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0])));
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(t->m->classpath->makeString(t, name, 0, byteArrayLength(t, name) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_isInterface
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return (classFlags
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0])))
|
||||||
|
& ACC_INTERFACE) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_isPrimitive
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return (classVmFlags
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0])))
|
||||||
|
& PrimitiveFlag) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_getClassLoader
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(classLoader
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0]))));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_isAssignableFrom
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
object that = reinterpret_cast<object>(arguments[1]);
|
||||||
|
|
||||||
|
if (LIKELY(that)) {
|
||||||
|
return vm::isAssignableFrom
|
||||||
|
(t, jclassVmClass(t, this_), jclassVmClass(t, that));
|
||||||
|
} else {
|
||||||
|
throwNew(t, Machine::NullPointerExceptionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Method_invokeNative
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object instance = reinterpret_cast<object>(arguments[1]);
|
||||||
|
object args = reinterpret_cast<object>(arguments[2]);
|
||||||
|
object method = arrayBody
|
||||||
|
(t, classMethodTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[3]))),
|
||||||
|
arguments[6]);
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>(invoke(t, method, instance, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Method_getMethodModifiers
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return methodFlags
|
||||||
|
(t, arrayBody
|
||||||
|
(t, classMethodTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0]))),
|
||||||
|
arguments[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Method_isAnnotationPresent
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object method = arrayBody
|
||||||
|
(t, classMethodTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0]))),
|
||||||
|
arguments[1]);
|
||||||
|
|
||||||
|
object addendum = methodAddendum(t, method);
|
||||||
|
if (addendum) {
|
||||||
|
object table = addendumAnnotationTable(t, addendum);
|
||||||
|
if (table) {
|
||||||
|
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
||||||
|
if (objectArrayBody(t, objectArrayBody(t, table, i), 1)
|
||||||
|
== reinterpret_cast<object>(arguments[2]))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Method_getAnnotation
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object method = arrayBody
|
||||||
|
(t, classMethodTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0]))),
|
||||||
|
arguments[1]);
|
||||||
|
|
||||||
|
object addendum = methodAddendum(t, method);
|
||||||
|
if (addendum) {
|
||||||
|
object table = addendumAnnotationTable(t, addendum);
|
||||||
|
if (table) {
|
||||||
|
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
||||||
|
if (objectArrayBody(t, objectArrayBody(t, table, i), 1)
|
||||||
|
== reinterpret_cast<object>(arguments[2]))
|
||||||
|
{
|
||||||
|
PROTECT(t, method);
|
||||||
|
PROTECT(t, table);
|
||||||
|
|
||||||
|
object get = resolveMethod
|
||||||
|
(t, root(t, Machine::BootLoader), "avian/Classes", "getAnnotation",
|
||||||
|
"(Ljava/lang/ClassLoader;[Ljava/lang/Object;)"
|
||||||
|
"Ljava/lang/annotation/Annotation;");
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(t->m->processor->invoke
|
||||||
|
(t, get, 0, classLoader(t, methodClass(t, method)),
|
||||||
|
objectArrayBody(t, table, i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Method_getDeclaredAnnotations
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object method = arrayBody
|
||||||
|
(t, classMethodTable
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0]))),
|
||||||
|
arguments[1]);
|
||||||
|
|
||||||
|
object addendum = methodAddendum(t, method);
|
||||||
|
if (addendum) {
|
||||||
|
object table = addendumAnnotationTable(t, addendum);
|
||||||
|
if (table) {
|
||||||
|
PROTECT(t, method);
|
||||||
|
PROTECT(t, table);
|
||||||
|
|
||||||
|
object array = makeObjectArray
|
||||||
|
(t, resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/lang/annotation/Annotation"),
|
||||||
|
objectArrayLength(t, table));
|
||||||
|
PROTECT(t, array);
|
||||||
|
|
||||||
|
object get = resolveMethod
|
||||||
|
(t, root(t, Machine::BootLoader), "avian/Classes", "getAnnotation",
|
||||||
|
"(Ljava/lang/ClassLoader;[Ljava/lang/Object;)"
|
||||||
|
"Ljava/lang/annotation/Annotation;");
|
||||||
|
PROTECT(t, get);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
||||||
|
object a = t->m->processor->invoke
|
||||||
|
(t, get, 0, classLoader(t, methodClass(t, method)),
|
||||||
|
objectArrayBody(t, table, i));
|
||||||
|
|
||||||
|
set(t, array, ArrayBody + (i * BytesPerWord), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>(array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(makeObjectArray
|
||||||
|
(t, resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/lang/annotation/Annotation"),
|
||||||
|
0));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Constructor_constructNative
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object args = reinterpret_cast<object>(arguments[1]);
|
||||||
|
PROTECT(t, args);
|
||||||
|
|
||||||
|
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[2]));
|
||||||
|
|
||||||
|
object method = arrayBody(t, classMethodTable(t, c), arguments[4]);
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
object instance = makeNew(t, c);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
t->m->processor->invokeArray(t, method, instance, args);
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Throwable_nativeFillInStackTrace
|
||||||
|
(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>(getTrace(t, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_avian_Classes_makeMethod
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(local::makeMethodOrConstructor
|
||||||
|
(t, reinterpret_cast<object>(arguments[0]), arguments[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_reflect_Array_createObjectArray
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(makeObjectArray
|
||||||
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0])),
|
||||||
|
arguments[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_nio_ByteOrder_isLittleEndian
|
||||||
|
(Thread*, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
#ifdef ARCH_powerpc
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_dalvik_system_VMRuntime_newNonMovableArray
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
if (jclassVmClass(t, reinterpret_cast<object>(arguments[1]))
|
||||||
|
== type(t, Machine::JbyteType))
|
||||||
|
{
|
||||||
|
object array = allocate3
|
||||||
|
(t, t->m->heap, Machine::FixedAllocation,
|
||||||
|
ArrayBody + arguments[2], false);
|
||||||
|
|
||||||
|
setObjectClass(t, array, type(t, Machine::ByteArrayType));
|
||||||
|
byteArrayLength(t, array) = arguments[2];
|
||||||
|
|
||||||
|
return reinterpret_cast<intptr_t>(array);
|
||||||
|
} else {
|
||||||
|
// todo
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_dalvik_system_VMRuntime_addressOf
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return arguments[1] + ArrayBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_libcore_io_Memory_pokeLong
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t v; memcpy(&v, arguments + 1, 8);
|
||||||
|
if (arguments[3]) {
|
||||||
|
v = swapV8(v);
|
||||||
|
}
|
||||||
|
memcpy(reinterpret_cast<void*>(arguments[0]), &v, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_libcore_io_Memory_peekLong
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t v; memcpy(&v, reinterpret_cast<void*>(arguments[0]), 8);
|
||||||
|
return arguments[1] ? swapV8(v) : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_libcore_io_Memory_pokeInt
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int32_t v = arguments[2] ? swapV4(arguments[1]) : arguments[1];
|
||||||
|
memcpy(reinterpret_cast<void*>(arguments[0]), &v, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_libcore_io_Memory_peekInt
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int32_t v; memcpy(&v, reinterpret_cast<void*>(arguments[0]), 4);
|
||||||
|
return arguments[1] ? swapV4(v) : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_libcore_io_Memory_pokeShort
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int16_t v = arguments[2] ? swapV2(arguments[1]) : arguments[1];
|
||||||
|
memcpy(reinterpret_cast<void*>(arguments[0]), &v, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_libcore_io_Memory_peekShort
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int16_t v; memcpy(&v, reinterpret_cast<void*>(arguments[0]), 2);
|
||||||
|
return arguments[1] ? swapV2(v) : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_libcore_io_Memory_pokeByte
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
*reinterpret_cast<int8_t*>(arguments[0]) = arguments[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_libcore_io_Memory_peekByte
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<int8_t*>(arguments[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_System_nanoTime
|
||||||
|
(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
return t->m->system->now() * 1000 * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_System_currentTimeMillis
|
||||||
|
(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
return t->m->system->now();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_System_identityHashCode
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return objectHash(t, reinterpret_cast<object>(arguments[0]));
|
||||||
|
}
|
||||||
|
@ -684,35 +684,6 @@ Avian_avian_Classes_primitiveClass
|
|||||||
return reinterpret_cast<int64_t>(primitiveClass(t, arguments[0]));
|
return reinterpret_cast<int64_t>(primitiveClass(t, arguments[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
|
||||||
Avian_avian_Classes_defineVMClass
|
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
|
||||||
object loader = reinterpret_cast<object>(arguments[0]);
|
|
||||||
object b = reinterpret_cast<object>(arguments[1]);
|
|
||||||
int offset = arguments[2];
|
|
||||||
int length = arguments[3];
|
|
||||||
|
|
||||||
uint8_t* buffer = static_cast<uint8_t*>
|
|
||||||
(t->m->heap->allocate(length));
|
|
||||||
|
|
||||||
THREAD_RESOURCE2(t, uint8_t*, buffer, int, length,
|
|
||||||
t->m->heap->free(buffer, length));
|
|
||||||
|
|
||||||
memcpy(buffer, &byteArrayBody(t, b, offset), length);
|
|
||||||
|
|
||||||
return reinterpret_cast<int64_t>(defineClass(t, loader, buffer, length));
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
|
||||||
Avian_avian_Classes_initialize
|
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
|
||||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
|
||||||
|
|
||||||
initClass(t, this_);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_avian_Classes_isAssignableFrom
|
Avian_avian_Classes_isAssignableFrom
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
@ -355,6 +355,260 @@ resolveClassBySpec(Thread* t, object loader, const char* spec,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveJType(Thread* t, object loader, const char* spec, unsigned specLength)
|
||||||
|
{
|
||||||
|
return getJClass(t, resolveClassBySpec(t, loader, spec, specLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveParameterTypes(Thread* t, object loader, object spec,
|
||||||
|
unsigned* parameterCount, unsigned* returnTypeSpec)
|
||||||
|
{
|
||||||
|
PROTECT(t, loader);
|
||||||
|
PROTECT(t, spec);
|
||||||
|
|
||||||
|
object list = 0;
|
||||||
|
PROTECT(t, list);
|
||||||
|
|
||||||
|
unsigned offset = 1;
|
||||||
|
unsigned count = 0;
|
||||||
|
while (byteArrayBody(t, spec, offset) != ')') {
|
||||||
|
switch (byteArrayBody(t, spec, offset)) {
|
||||||
|
case 'L': {
|
||||||
|
unsigned start = offset;
|
||||||
|
++ offset;
|
||||||
|
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
|
||||||
|
++ offset;
|
||||||
|
|
||||||
|
object type = resolveClassBySpec
|
||||||
|
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
|
||||||
|
offset - start);
|
||||||
|
|
||||||
|
list = makePair(t, type, list);
|
||||||
|
|
||||||
|
++ count;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case '[': {
|
||||||
|
unsigned start = offset;
|
||||||
|
while (byteArrayBody(t, spec, offset) == '[') ++ offset;
|
||||||
|
switch (byteArrayBody(t, spec, offset)) {
|
||||||
|
case 'L':
|
||||||
|
++ offset;
|
||||||
|
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
|
||||||
|
++ offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
++ offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
object type = resolveClassBySpec
|
||||||
|
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
|
||||||
|
offset - start);
|
||||||
|
|
||||||
|
list = makePair(t, type, list);
|
||||||
|
++ count;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
list = makePair
|
||||||
|
(t, primitiveClass(t, byteArrayBody(t, spec, offset)), list);
|
||||||
|
++ offset;
|
||||||
|
++ count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*parameterCount = count;
|
||||||
|
*returnTypeSpec = offset + 1;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveParameterJTypes(Thread* t, object loader, object spec,
|
||||||
|
unsigned* parameterCount, unsigned* returnTypeSpec)
|
||||||
|
{
|
||||||
|
object list = resolveParameterTypes
|
||||||
|
(t, loader, spec, parameterCount, returnTypeSpec);
|
||||||
|
|
||||||
|
PROTECT(t, list);
|
||||||
|
|
||||||
|
object array = makeObjectArray
|
||||||
|
(t, type(t, Machine::JclassType), *parameterCount);
|
||||||
|
PROTECT(t, array);
|
||||||
|
|
||||||
|
for (int i = *parameterCount - 1; i >= 0; --i) {
|
||||||
|
object c = getJClass(t, pairFirst(t, list));
|
||||||
|
set(t, array, ArrayBody + (i * BytesPerWord), c);
|
||||||
|
list = pairSecond(t, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveExceptionJTypes(Thread* t, object loader, object addendum)
|
||||||
|
{
|
||||||
|
if (addendum == 0 or methodAddendumExceptionTable(t, addendum) == 0) {
|
||||||
|
return makeObjectArray(t, type(t, Machine::JclassType), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROTECT(t, loader);
|
||||||
|
PROTECT(t, addendum);
|
||||||
|
|
||||||
|
object array = makeObjectArray
|
||||||
|
(t, type(t, Machine::JclassType),
|
||||||
|
shortArrayLength(t, methodAddendumExceptionTable(t, addendum)));
|
||||||
|
PROTECT(t, array);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < shortArrayLength
|
||||||
|
(t, methodAddendumExceptionTable(t, addendum)); ++i)
|
||||||
|
{
|
||||||
|
uint16_t index = shortArrayBody
|
||||||
|
(t, methodAddendumExceptionTable(t, addendum), i) - 1;
|
||||||
|
|
||||||
|
object o = singletonObject(t, addendumPool(t, addendum), index);
|
||||||
|
|
||||||
|
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
|
||||||
|
o = resolveClass(t, loader, referenceName(t, o));
|
||||||
|
|
||||||
|
set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord),
|
||||||
|
o);
|
||||||
|
}
|
||||||
|
|
||||||
|
o = getJClass(t, o);
|
||||||
|
|
||||||
|
set(t, array, ArrayBody + (i * BytesPerWord), o);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
invoke(Thread* t, object method, object instance, object args)
|
||||||
|
{
|
||||||
|
PROTECT(t, method);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
PROTECT(t, args);
|
||||||
|
|
||||||
|
if (methodFlags(t, method) & ACC_STATIC) {
|
||||||
|
instance = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((args == 0 ? 0 : objectArrayLength(t, args))
|
||||||
|
!= methodParameterCount(t, method))
|
||||||
|
{
|
||||||
|
throwNew(t, Machine::IllegalArgumentExceptionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodParameterCount(t, method)) {
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
unsigned specLength = byteArrayLength(t, methodSpec(t, method));
|
||||||
|
THREAD_RUNTIME_ARRAY(t, char, spec, specLength);
|
||||||
|
memcpy(spec, &byteArrayBody(t, methodSpec(t, method), 0), specLength);
|
||||||
|
unsigned i = 0;
|
||||||
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
||||||
|
object type;
|
||||||
|
bool objectType = false;
|
||||||
|
const char* p = it.next();
|
||||||
|
switch (*p) {
|
||||||
|
case 'Z': type = vm::type(t, Machine::BooleanType); break;
|
||||||
|
case 'B': type = vm::type(t, Machine::ByteType); break;
|
||||||
|
case 'S': type = vm::type(t, Machine::ShortType); break;
|
||||||
|
case 'C': type = vm::type(t, Machine::CharType); break;
|
||||||
|
case 'I': type = vm::type(t, Machine::IntType); break;
|
||||||
|
case 'F': type = vm::type(t, Machine::FloatType); break;
|
||||||
|
case 'J': type = vm::type(t, Machine::LongType); break;
|
||||||
|
case 'D': type = vm::type(t, Machine::DoubleType); break;
|
||||||
|
|
||||||
|
case 'L': ++ p;
|
||||||
|
case '[': {
|
||||||
|
objectType = true;
|
||||||
|
unsigned nameLength = it.s - p;
|
||||||
|
THREAD_RUNTIME_ARRAY(t, char, name, nameLength);
|
||||||
|
memcpy(name, p, nameLength - 1);
|
||||||
|
name[nameLength - 1] = 0;
|
||||||
|
type = resolveClass
|
||||||
|
(t, classLoader(t, methodClass(t, method)), name);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
object arg = objectArrayBody(t, args, i++);
|
||||||
|
if ((arg == 0 and (not objectType))
|
||||||
|
or (arg and (not instanceOf(t, type, arg))))
|
||||||
|
{
|
||||||
|
// fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast<const int8_t*>("<null>"), &byteArrayBody(t, className(t, type), 0));
|
||||||
|
|
||||||
|
throwNew(t, Machine::IllegalArgumentExceptionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned returnCode = methodReturnCode(t, method);
|
||||||
|
|
||||||
|
THREAD_RESOURCE0(t, {
|
||||||
|
if (t->exception) {
|
||||||
|
object exception = t->exception;
|
||||||
|
t->exception = makeThrowable
|
||||||
|
(t, Machine::InvocationTargetExceptionType, 0, 0, exception);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
object result;
|
||||||
|
if (args) {
|
||||||
|
result = t->m->processor->invokeArray(t, method, instance, args);
|
||||||
|
} else {
|
||||||
|
result = t->m->processor->invoke(t, method, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return translateInvokeResult(t, returnCode, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// only safe to call during bootstrap when there's only one thread
|
||||||
|
// running:
|
||||||
|
void
|
||||||
|
intercept(Thread* t, object c, const char* name, const char* spec,
|
||||||
|
void* function)
|
||||||
|
{
|
||||||
|
object m = findMethodOrNull(t, c, name, spec);
|
||||||
|
if (m) {
|
||||||
|
PROTECT(t, m);
|
||||||
|
|
||||||
|
object clone = methodClone(t, m);
|
||||||
|
|
||||||
|
// make clone private to prevent vtable updates at compilation
|
||||||
|
// time. Otherwise, our interception might be bypassed by calls
|
||||||
|
// through the vtable.
|
||||||
|
methodFlags(t, clone) |= ACC_PRIVATE;
|
||||||
|
|
||||||
|
methodFlags(t, m) |= ACC_NATIVE;
|
||||||
|
|
||||||
|
object native = makeNativeIntercept(t, function, true, clone);
|
||||||
|
|
||||||
|
PROTECT(t, native);
|
||||||
|
|
||||||
|
object runtimeData = getMethodRuntimeData(t, m);
|
||||||
|
|
||||||
|
set(t, runtimeData, MethodRuntimeDataNative, native);
|
||||||
|
} else {
|
||||||
|
// If we can't find the method, just ignore it, since ProGuard may
|
||||||
|
// have stripped it out as unused. Otherwise, the code below can
|
||||||
|
// be uncommented for debugging purposes.
|
||||||
|
|
||||||
|
// fprintf(stderr, "unable to find %s%s in %s\n",
|
||||||
|
// name, spec, &byteArrayBody(t, className(t, c), 0));
|
||||||
|
|
||||||
|
// abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//CLASSPATH_COMMON_H
|
#endif//CLASSPATH_COMMON_H
|
||||||
|
@ -1918,44 +1918,6 @@ loadLibrary(Thread* t, object, uintptr_t* arguments)
|
|||||||
RUNTIME_ARRAY_BODY(n), not absolute, true);
|
RUNTIME_ARRAY_BODY(n), not absolute, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// only safe to call during bootstrap when there's only one thread
|
|
||||||
// running:
|
|
||||||
void
|
|
||||||
intercept(Thread* t, object c, const char* name, const char* spec,
|
|
||||||
void* function)
|
|
||||||
{
|
|
||||||
object m = findMethodOrNull(t, c, name, spec);
|
|
||||||
if (m) {
|
|
||||||
PROTECT(t, m);
|
|
||||||
|
|
||||||
object clone = methodClone(t, m);
|
|
||||||
|
|
||||||
// make clone private to prevent vtable updates at compilation
|
|
||||||
// time. Otherwise, our interception might be bypassed by calls
|
|
||||||
// through the vtable.
|
|
||||||
methodFlags(t, clone) |= ACC_PRIVATE;
|
|
||||||
|
|
||||||
methodFlags(t, m) |= ACC_NATIVE;
|
|
||||||
|
|
||||||
object native = makeNativeIntercept(t, function, true, clone);
|
|
||||||
|
|
||||||
PROTECT(t, native);
|
|
||||||
|
|
||||||
object runtimeData = getMethodRuntimeData(t, m);
|
|
||||||
|
|
||||||
set(t, runtimeData, MethodRuntimeDataNative, native);
|
|
||||||
} else {
|
|
||||||
// If we can't find the method, just ignore it, since ProGuard may
|
|
||||||
// have stripped it out as unused. Otherwise, the code below can
|
|
||||||
// be uncommented for debugging purposes.
|
|
||||||
|
|
||||||
// fprintf(stderr, "unable to find %s%s in %s\n",
|
|
||||||
// name, spec, &byteArrayBody(t, className(t, c), 0));
|
|
||||||
|
|
||||||
// abort(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
interceptFileOperations(Thread* t)
|
interceptFileOperations(Thread* t)
|
||||||
{
|
{
|
||||||
@ -2185,138 +2147,6 @@ countConstructors(Thread* t, object c, bool publicOnly)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
|
||||||
resolveJType(Thread* t, object loader, const char* spec, unsigned specLength)
|
|
||||||
{
|
|
||||||
return getJClass(t, resolveClassBySpec(t, loader, spec, specLength));
|
|
||||||
}
|
|
||||||
|
|
||||||
object
|
|
||||||
resolveParameterTypes(Thread* t, object loader, object spec,
|
|
||||||
unsigned* parameterCount, unsigned* returnTypeSpec)
|
|
||||||
{
|
|
||||||
PROTECT(t, loader);
|
|
||||||
PROTECT(t, spec);
|
|
||||||
|
|
||||||
object list = 0;
|
|
||||||
PROTECT(t, list);
|
|
||||||
|
|
||||||
unsigned offset = 1;
|
|
||||||
unsigned count = 0;
|
|
||||||
while (byteArrayBody(t, spec, offset) != ')') {
|
|
||||||
switch (byteArrayBody(t, spec, offset)) {
|
|
||||||
case 'L': {
|
|
||||||
unsigned start = offset;
|
|
||||||
++ offset;
|
|
||||||
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
|
|
||||||
++ offset;
|
|
||||||
|
|
||||||
object type = resolveClassBySpec
|
|
||||||
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
|
|
||||||
offset - start);
|
|
||||||
|
|
||||||
list = makePair(t, type, list);
|
|
||||||
|
|
||||||
++ count;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case '[': {
|
|
||||||
unsigned start = offset;
|
|
||||||
while (byteArrayBody(t, spec, offset) == '[') ++ offset;
|
|
||||||
switch (byteArrayBody(t, spec, offset)) {
|
|
||||||
case 'L':
|
|
||||||
++ offset;
|
|
||||||
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
|
|
||||||
++ offset;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
++ offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
object type = resolveClassBySpec
|
|
||||||
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
|
|
||||||
offset - start);
|
|
||||||
|
|
||||||
list = makePair(t, type, list);
|
|
||||||
++ count;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
list = makePair
|
|
||||||
(t, primitiveClass(t, byteArrayBody(t, spec, offset)), list);
|
|
||||||
++ offset;
|
|
||||||
++ count;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*parameterCount = count;
|
|
||||||
*returnTypeSpec = offset + 1;
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
object
|
|
||||||
resolveParameterJTypes(Thread* t, object loader, object spec,
|
|
||||||
unsigned* parameterCount, unsigned* returnTypeSpec)
|
|
||||||
{
|
|
||||||
object list = resolveParameterTypes
|
|
||||||
(t, loader, spec, parameterCount, returnTypeSpec);
|
|
||||||
|
|
||||||
PROTECT(t, list);
|
|
||||||
|
|
||||||
object array = makeObjectArray
|
|
||||||
(t, type(t, Machine::JclassType), *parameterCount);
|
|
||||||
PROTECT(t, array);
|
|
||||||
|
|
||||||
for (int i = *parameterCount - 1; i >= 0; --i) {
|
|
||||||
object c = getJClass(t, pairFirst(t, list));
|
|
||||||
set(t, array, ArrayBody + (i * BytesPerWord), c);
|
|
||||||
list = pairSecond(t, list);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
object
|
|
||||||
resolveExceptionJTypes(Thread* t, object loader, object addendum)
|
|
||||||
{
|
|
||||||
if (addendum == 0 or methodAddendumExceptionTable(t, addendum) == 0) {
|
|
||||||
return makeObjectArray(t, type(t, Machine::JclassType), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
PROTECT(t, loader);
|
|
||||||
PROTECT(t, addendum);
|
|
||||||
|
|
||||||
object array = makeObjectArray
|
|
||||||
(t, type(t, Machine::JclassType),
|
|
||||||
shortArrayLength(t, methodAddendumExceptionTable(t, addendum)));
|
|
||||||
PROTECT(t, array);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < shortArrayLength
|
|
||||||
(t, methodAddendumExceptionTable(t, addendum)); ++i)
|
|
||||||
{
|
|
||||||
uint16_t index = shortArrayBody
|
|
||||||
(t, methodAddendumExceptionTable(t, addendum), i) - 1;
|
|
||||||
|
|
||||||
object o = singletonObject(t, addendumPool(t, addendum), index);
|
|
||||||
|
|
||||||
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
|
|
||||||
o = resolveClass(t, loader, referenceName(t, o));
|
|
||||||
|
|
||||||
set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord),
|
|
||||||
o);
|
|
||||||
}
|
|
||||||
|
|
||||||
o = getJClass(t, o);
|
|
||||||
|
|
||||||
set(t, array, ArrayBody + (i * BytesPerWord), o);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
object
|
object
|
||||||
makeJmethod(Thread* t, object vmMethod, int index)
|
makeJmethod(Thread* t, object vmMethod, int index)
|
||||||
{
|
{
|
||||||
@ -2330,18 +2160,18 @@ makeJmethod(Thread* t, object vmMethod, int index)
|
|||||||
|
|
||||||
unsigned parameterCount;
|
unsigned parameterCount;
|
||||||
unsigned returnTypeSpec;
|
unsigned returnTypeSpec;
|
||||||
object parameterTypes = local::resolveParameterJTypes
|
object parameterTypes = resolveParameterJTypes
|
||||||
(t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod),
|
(t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod),
|
||||||
¶meterCount, &returnTypeSpec);
|
¶meterCount, &returnTypeSpec);
|
||||||
PROTECT(t, parameterTypes);
|
PROTECT(t, parameterTypes);
|
||||||
|
|
||||||
object returnType = local::resolveJType
|
object returnType = resolveJType
|
||||||
(t, classLoader(t, methodClass(t, vmMethod)), reinterpret_cast<char*>
|
(t, classLoader(t, methodClass(t, vmMethod)), reinterpret_cast<char*>
|
||||||
(&byteArrayBody(t, methodSpec(t, vmMethod), returnTypeSpec)),
|
(&byteArrayBody(t, methodSpec(t, vmMethod), returnTypeSpec)),
|
||||||
byteArrayLength(t, methodSpec(t, vmMethod)) - 1 - returnTypeSpec);
|
byteArrayLength(t, methodSpec(t, vmMethod)) - 1 - returnTypeSpec);
|
||||||
PROTECT(t, returnType);
|
PROTECT(t, returnType);
|
||||||
|
|
||||||
object exceptionTypes = local::resolveExceptionJTypes
|
object exceptionTypes = resolveExceptionJTypes
|
||||||
(t, classLoader(t, methodClass(t, vmMethod)),
|
(t, classLoader(t, methodClass(t, vmMethod)),
|
||||||
methodAddendum(t, vmMethod));
|
methodAddendum(t, vmMethod));
|
||||||
PROTECT(t, exceptionTypes);
|
PROTECT(t, exceptionTypes);
|
||||||
@ -2406,12 +2236,12 @@ makeJconstructor(Thread* t, object vmMethod, int index)
|
|||||||
|
|
||||||
unsigned parameterCount;
|
unsigned parameterCount;
|
||||||
unsigned returnTypeSpec;
|
unsigned returnTypeSpec;
|
||||||
object parameterTypes = local::resolveParameterJTypes
|
object parameterTypes = resolveParameterJTypes
|
||||||
(t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod),
|
(t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod),
|
||||||
¶meterCount, &returnTypeSpec);
|
¶meterCount, &returnTypeSpec);
|
||||||
PROTECT(t, parameterTypes);
|
PROTECT(t, parameterTypes);
|
||||||
|
|
||||||
object exceptionTypes = local::resolveExceptionJTypes
|
object exceptionTypes = resolveExceptionJTypes
|
||||||
(t, classLoader(t, methodClass(t, vmMethod)),
|
(t, classLoader(t, methodClass(t, vmMethod)),
|
||||||
methodAddendum(t, vmMethod));
|
methodAddendum(t, vmMethod));
|
||||||
PROTECT(t, exceptionTypes);
|
PROTECT(t, exceptionTypes);
|
||||||
@ -4777,83 +4607,10 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments)
|
|||||||
(t, jclassVmClass(t, jmethodClazz(t, *method))),
|
(t, jclassVmClass(t, jmethodClazz(t, *method))),
|
||||||
jmethodSlot(t, *method));
|
jmethodSlot(t, *method));
|
||||||
|
|
||||||
if (methodFlags(t, vmMethod) & ACC_STATIC) {
|
|
||||||
instance = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((args == 0 ? 0 : objectArrayLength(t, *args))
|
|
||||||
!= methodParameterCount(t, vmMethod))
|
|
||||||
{
|
|
||||||
throwNew(t, Machine::IllegalArgumentExceptionType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (methodParameterCount(t, vmMethod)) {
|
|
||||||
PROTECT(t, vmMethod);
|
|
||||||
|
|
||||||
unsigned specLength = byteArrayLength(t, methodSpec(t, vmMethod));
|
|
||||||
THREAD_RUNTIME_ARRAY(t, char, spec, specLength);
|
|
||||||
memcpy(spec, &byteArrayBody(t, methodSpec(t, vmMethod), 0), specLength);
|
|
||||||
unsigned i = 0;
|
|
||||||
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
|
||||||
object type;
|
|
||||||
bool objectType = false;
|
|
||||||
const char* p = it.next();
|
|
||||||
switch (*p) {
|
|
||||||
case 'Z': type = vm::type(t, Machine::BooleanType); break;
|
|
||||||
case 'B': type = vm::type(t, Machine::ByteType); break;
|
|
||||||
case 'S': type = vm::type(t, Machine::ShortType); break;
|
|
||||||
case 'C': type = vm::type(t, Machine::CharType); break;
|
|
||||||
case 'I': type = vm::type(t, Machine::IntType); break;
|
|
||||||
case 'F': type = vm::type(t, Machine::FloatType); break;
|
|
||||||
case 'J': type = vm::type(t, Machine::LongType); break;
|
|
||||||
case 'D': type = vm::type(t, Machine::DoubleType); break;
|
|
||||||
|
|
||||||
case 'L': ++ p;
|
|
||||||
case '[': {
|
|
||||||
objectType = true;
|
|
||||||
unsigned nameLength = it.s - p;
|
|
||||||
THREAD_RUNTIME_ARRAY(t, char, name, nameLength);
|
|
||||||
memcpy(name, p, nameLength - 1);
|
|
||||||
name[nameLength - 1] = 0;
|
|
||||||
type = resolveClass
|
|
||||||
(t, classLoader(t, methodClass(t, vmMethod)), name);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
object arg = objectArrayBody(t, *args, i++);
|
|
||||||
if ((arg == 0 and (not objectType))
|
|
||||||
or (arg and (not instanceOf(t, type, arg))))
|
|
||||||
{
|
|
||||||
// fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast<const int8_t*>("<null>"), &byteArrayBody(t, className(t, type), 0));
|
|
||||||
|
|
||||||
throwNew(t, Machine::IllegalArgumentExceptionType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned returnCode = methodReturnCode(t, vmMethod);
|
|
||||||
|
|
||||||
THREAD_RESOURCE0(t, {
|
|
||||||
if (t->exception) {
|
|
||||||
object exception = t->exception;
|
|
||||||
t->exception = makeThrowable
|
|
||||||
(t, Machine::InvocationTargetExceptionType, 0, 0, exception);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
object result;
|
|
||||||
if (args) {
|
|
||||||
result = t->m->processor->invokeArray
|
|
||||||
(t, vmMethod, instance ? *instance : 0, *args);
|
|
||||||
} else {
|
|
||||||
result = t->m->processor->invoke(t, vmMethod, instance ? *instance : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return reinterpret_cast<uint64_t>
|
return reinterpret_cast<uint64_t>
|
||||||
(makeLocalReference(t, translateInvokeResult(t, returnCode, result)));
|
(makeLocalReference
|
||||||
|
(t, invoke
|
||||||
|
(t, vmMethod, instance ? *instance : 0, args ? *args : 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jobject JNICALL
|
extern "C" JNIEXPORT jobject JNICALL
|
||||||
|
@ -3401,27 +3401,56 @@ PopLocalFrame(Thread* t, jobject result)
|
|||||||
return reinterpret_cast<jobject>(run(t, popLocalFrame, arguments));
|
return reinterpret_cast<jobject>(run(t, popLocalFrame, arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
newDirectByteBuffer(Thread* t, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
jlong capacity; memcpy(&capacity, arguments + 1, sizeof(jlong));
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(makeLocalReference
|
||||||
|
(t, t->m->classpath->makeDirectByteBuffer
|
||||||
|
(t, reinterpret_cast<void*>(arguments[0]), capacity)));
|
||||||
|
}
|
||||||
|
|
||||||
jobject JNICALL
|
jobject JNICALL
|
||||||
NewDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
NewDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
||||||
{
|
{
|
||||||
jclass c = FindClass(t, "java/nio/DirectByteBuffer");
|
uintptr_t arguments[1 + (sizeof(jlong) / BytesPerWord)];
|
||||||
return NewObject(t, c, GetMethodID(t, c, "<init>", "(JI)V"),
|
arguments[0] = reinterpret_cast<uintptr_t>(p);
|
||||||
reinterpret_cast<jlong>(p),
|
memcpy(arguments + 1, &capacity, sizeof(jlong));
|
||||||
static_cast<jint>(capacity));
|
|
||||||
|
return reinterpret_cast<jobject>(run(t, newDirectByteBuffer, arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
getDirectBufferAddress(Thread* t, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(t->m->classpath->getDirectBufferAddress
|
||||||
|
(t, *reinterpret_cast<jobject>(arguments[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* JNICALL
|
void* JNICALL
|
||||||
GetDirectBufferAddress(Thread* t, jobject b)
|
GetDirectBufferAddress(Thread* t, jobject b)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<void*>
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(b) };
|
||||||
(GetLongField(t, b, GetFieldID(t, GetObjectClass(t, b), "address", "J")));
|
|
||||||
|
return reinterpret_cast<void*>(run(t, getDirectBufferAddress, arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
getDirectBufferCapacity(Thread* t, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return t->m->classpath->getDirectBufferCapacity
|
||||||
|
(t, *reinterpret_cast<jobject>(arguments[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong JNICALL
|
jlong JNICALL
|
||||||
GetDirectBufferCapacity(Thread* t, jobject b)
|
GetDirectBufferCapacity(Thread* t, jobject b)
|
||||||
{
|
{
|
||||||
return GetIntField
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(b) };
|
||||||
(t, b, GetFieldID(t, GetObjectClass(t, b), "capacity", "I"));
|
|
||||||
|
return run(t, getDirectBufferCapacity, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct JavaVMOption {
|
struct JavaVMOption {
|
||||||
|
@ -2369,8 +2369,6 @@ object
|
|||||||
makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
|
makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
|
||||||
object elementClass)
|
object elementClass)
|
||||||
{
|
{
|
||||||
// todo: arrays should implement Cloneable and Serializable
|
|
||||||
|
|
||||||
if (classVmFlags(t, type(t, Machine::JobjectType)) & BootstrapFlag) {
|
if (classVmFlags(t, type(t, Machine::JobjectType)) & BootstrapFlag) {
|
||||||
PROTECT(t, loader);
|
PROTECT(t, loader);
|
||||||
PROTECT(t, spec);
|
PROTECT(t, spec);
|
||||||
@ -2398,7 +2396,7 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
|
|||||||
spec,
|
spec,
|
||||||
0,
|
0,
|
||||||
type(t, Machine::JobjectType),
|
type(t, Machine::JobjectType),
|
||||||
0,
|
root(t, Machine::ArrayInterfaceTable),
|
||||||
vtable,
|
vtable,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -2733,6 +2731,33 @@ boot(Thread* t)
|
|||||||
|
|
||||||
setRoot(t, Machine::StringMap, makeWeakHashMap(t, 0, 0));
|
setRoot(t, Machine::StringMap, makeWeakHashMap(t, 0, 0));
|
||||||
|
|
||||||
|
{ object interfaceTable = makeArray(t, 4);
|
||||||
|
|
||||||
|
set(t, interfaceTable, ArrayBody, type(t, Machine::SerializableType));
|
||||||
|
|
||||||
|
set(t, interfaceTable, ArrayBody + (2 * BytesPerWord),
|
||||||
|
type(t, Machine::CloneableType));
|
||||||
|
|
||||||
|
setRoot(t, Machine::ArrayInterfaceTable, interfaceTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(t, type(t, Machine::BooleanArrayType), ClassInterfaceTable,
|
||||||
|
root(t, Machine::ArrayInterfaceTable));
|
||||||
|
set(t, type(t, Machine::ByteArrayType), ClassInterfaceTable,
|
||||||
|
root(t, Machine::ArrayInterfaceTable));
|
||||||
|
set(t, type(t, Machine::CharArrayType), ClassInterfaceTable,
|
||||||
|
root(t, Machine::ArrayInterfaceTable));
|
||||||
|
set(t, type(t, Machine::ShortArrayType), ClassInterfaceTable,
|
||||||
|
root(t, Machine::ArrayInterfaceTable));
|
||||||
|
set(t, type(t, Machine::IntArrayType), ClassInterfaceTable,
|
||||||
|
root(t, Machine::ArrayInterfaceTable));
|
||||||
|
set(t, type(t, Machine::LongArrayType), ClassInterfaceTable,
|
||||||
|
root(t, Machine::ArrayInterfaceTable));
|
||||||
|
set(t, type(t, Machine::FloatArrayType), ClassInterfaceTable,
|
||||||
|
root(t, Machine::ArrayInterfaceTable));
|
||||||
|
set(t, type(t, Machine::DoubleArrayType), ClassInterfaceTable,
|
||||||
|
root(t, Machine::ArrayInterfaceTable));
|
||||||
|
|
||||||
m->processor->boot(t, 0, 0);
|
m->processor->boot(t, 0, 0);
|
||||||
|
|
||||||
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 0, 1);
|
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||||
|
@ -1227,10 +1227,11 @@ class Machine {
|
|||||||
OutOfMemoryError,
|
OutOfMemoryError,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
VirtualFileFinders,
|
VirtualFileFinders,
|
||||||
VirtualFiles
|
VirtualFiles,
|
||||||
|
ArrayInterfaceTable
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned RootCount = VirtualFiles + 1;
|
static const unsigned RootCount = ArrayInterfaceTable + 1;
|
||||||
|
|
||||||
Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder,
|
Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder,
|
||||||
Processor* processor, Classpath* classpath, const char** properties,
|
Processor* processor, Classpath* classpath, const char** properties,
|
||||||
@ -1569,6 +1570,15 @@ class Classpath {
|
|||||||
virtual void
|
virtual void
|
||||||
updatePackageMap(Thread* t, object class_) = 0;
|
updatePackageMap(Thread* t, object class_) = 0;
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
makeDirectByteBuffer(Thread* t, void* p, jlong capacity) = 0;
|
||||||
|
|
||||||
|
virtual void*
|
||||||
|
getDirectBufferAddress(Thread* t, object buffer) = 0;
|
||||||
|
|
||||||
|
virtual int64_t
|
||||||
|
getDirectBufferCapacity(Thread* t, object buffer) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
dispose() = 0;
|
dispose() = 0;
|
||||||
};
|
};
|
||||||
|
31
src/target.h
31
src/target.h
@ -23,11 +23,9 @@ targetV1(T v)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_OPPOSITE_ENDIAN
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T
|
||||||
targetV2(T v)
|
swapV2(T v)
|
||||||
{
|
{
|
||||||
return (((v >> 8) & 0xFF) |
|
return (((v >> 8) & 0xFF) |
|
||||||
((v << 8)));
|
((v << 8)));
|
||||||
@ -35,7 +33,7 @@ targetV2(T v)
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T
|
||||||
targetV4(T v)
|
swapV4(T v)
|
||||||
{
|
{
|
||||||
return (((v >> 24) & 0x000000FF) |
|
return (((v >> 24) & 0x000000FF) |
|
||||||
((v >> 8) & 0x0000FF00) |
|
((v >> 8) & 0x0000FF00) |
|
||||||
@ -45,7 +43,7 @@ targetV4(T v)
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T
|
||||||
targetV8(T v)
|
swapV8(T v)
|
||||||
{
|
{
|
||||||
return (((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) |
|
return (((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) |
|
||||||
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) |
|
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) |
|
||||||
@ -57,6 +55,29 @@ targetV8(T v)
|
|||||||
((static_cast<uint64_t>(v) << 56)));
|
((static_cast<uint64_t>(v) << 56)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TARGET_OPPOSITE_ENDIAN
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T
|
||||||
|
targetV2(T v)
|
||||||
|
{
|
||||||
|
return swapV2(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T
|
||||||
|
targetV4(T v)
|
||||||
|
{
|
||||||
|
return swapV4(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T
|
||||||
|
targetV8(T v)
|
||||||
|
{
|
||||||
|
return swapV8(v);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T
|
||||||
|
@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
(type constantPool sun/reflect/ConstantPool)
|
(type constantPool sun/reflect/ConstantPool)
|
||||||
|
|
||||||
|
(type serializable java/io/Serializable)
|
||||||
|
|
||||||
|
(type cloneable java/lang/Cloneable)
|
||||||
|
|
||||||
(type singleton
|
(type singleton
|
||||||
(array uintptr_t body))
|
(array uintptr_t body))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user