mirror of
https://github.com/corda/corda.git
synced 2025-01-01 02:36:44 +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.Method;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.io.InputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
@ -262,6 +264,158 @@ public class Classes {
|
||||
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 releaseClassLock();
|
||||
|
@ -28,6 +28,8 @@ public class SystemClassLoader extends ClassLoader {
|
||||
|
||||
public static native Class getClass(VMClass vmClass);
|
||||
|
||||
public static native VMClass vmClass(Class jClass);
|
||||
|
||||
private native VMClass findLoadedVMClass(String name);
|
||||
|
||||
protected Class reallyFindLoadedClass(String name){
|
||||
@ -35,6 +37,30 @@ public class SystemClassLoader extends ClassLoader {
|
||||
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);
|
||||
|
||||
protected URL findResource(String name) {
|
||||
|
@ -145,38 +145,7 @@ public final class Class <T> implements Type, AnnotatedElement {
|
||||
ClassLoader loader)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
if (loader == null) {
|
||||
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);
|
||||
}
|
||||
return Classes.forName(name, initialize, loader);
|
||||
}
|
||||
|
||||
public Class getComponentType() {
|
||||
@ -211,84 +180,36 @@ public final class Class <T> implements Type, AnnotatedElement {
|
||||
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 {
|
||||
Field f = findField(vmClass, name);
|
||||
if (f == null) {
|
||||
int index = Classes.findField(vmClass, name);
|
||||
if (index < 0) {
|
||||
throw new NoSuchFieldException(name);
|
||||
} else {
|
||||
return f;
|
||||
return new Field(vmClass.fieldTable[index]);
|
||||
}
|
||||
}
|
||||
|
||||
public Field getField(String name) throws NoSuchFieldException {
|
||||
for (VMClass c = vmClass; c != null; c = c.super_) {
|
||||
Field f = findField(c, name);
|
||||
if (f != null) {
|
||||
return f;
|
||||
int index = findField(c, name);
|
||||
if (index >= 0) {
|
||||
return new Field(vmClass.fieldTable[index]);
|
||||
}
|
||||
}
|
||||
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)
|
||||
throws NoSuchMethodException
|
||||
{
|
||||
if (name.startsWith("<")) {
|
||||
throw new NoSuchMethodException(name);
|
||||
}
|
||||
Method m = findMethod(vmClass, name, parameterTypes);
|
||||
if (m == null) {
|
||||
int index = Classes.findMethod(vmClass, name, parameterTypes);
|
||||
if (index < 0) {
|
||||
throw new NoSuchMethodException(name);
|
||||
} 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);
|
||||
}
|
||||
for (VMClass c = vmClass; c != null; c = c.super_) {
|
||||
Method m = findMethod(c, name, parameterTypes);
|
||||
if (m != null) {
|
||||
return m;
|
||||
int index = findMethod(c, name, parameterTypes);
|
||||
if (index >= 0) {
|
||||
return new Method(vmClass.methodTable[index]);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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() {
|
||||
return getParameterTypes(vmMethod);
|
||||
}
|
||||
|
||||
public static Class[] getParameterTypes(VMMethod vmMethod) {
|
||||
int count = vmMethod.parameterCount;
|
||||
|
||||
Class[] types = new Class[count];
|
||||
int index = 0;
|
||||
|
||||
String spec = new String
|
||||
(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;
|
||||
return Classes.getParameterTypes(vmMethod);
|
||||
}
|
||||
|
||||
public Object invoke(Object instance, Object ... arguments)
|
||||
@ -160,22 +107,13 @@ public class Method<T> extends AccessibleObject implements Member {
|
||||
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_) {
|
||||
if (vmMethod.hasAnnotations()) {
|
||||
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
|
||||
for (int i = 0; i < table.length; ++i) {
|
||||
Object[] a = (Object[]) table[i];
|
||||
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;
|
||||
Annotation[] array = new Annotation[table.length];
|
||||
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;
|
||||
} else {
|
||||
|
@ -16,6 +16,9 @@ import static avian.Stream.write4;
|
||||
import static avian.Stream.set4;
|
||||
import static avian.Assembler.*;
|
||||
|
||||
import avian.SystemClassLoader;
|
||||
import avian.Classes;
|
||||
|
||||
import avian.ConstantPool;
|
||||
import avian.ConstantPool.PoolEntry;
|
||||
|
||||
@ -87,26 +90,15 @@ public class Proxy {
|
||||
|
||||
write1(out, aload_0);
|
||||
|
||||
write1(out, new_);
|
||||
write2(out, ConstantPool.addClass(pool, "java/lang/reflect/Method") + 1);
|
||||
write1(out, dup);
|
||||
write1(out, ldc_w);
|
||||
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);
|
||||
write2(out, ConstantPool.addInteger(pool, index) + 1);
|
||||
write1(out, aaload);
|
||||
write1(out, invokespecial);
|
||||
write1(out, invokestatic);
|
||||
write2(out, ConstantPool.addMethodRef
|
||||
(pool, "java/lang/reflect/Method",
|
||||
"<init>", "(Lavian/VMMethod;)V") + 1);
|
||||
(pool, "avian/Classes",
|
||||
"makeMethod", "(Ljava/lang/Class;I)Ljava/lang/reflect/Method;")
|
||||
+ 1);
|
||||
|
||||
write1(out, ldc_w);
|
||||
write2(out, ConstantPool.addInteger(pool, parameterCount) + 1);
|
||||
@ -363,10 +355,11 @@ public class Proxy {
|
||||
|
||||
Map<String,avian.VMMethod> virtualMap = new HashMap();
|
||||
for (Class c: interfaces) {
|
||||
avian.VMMethod[] ivtable = c.vmClass.virtualTable;
|
||||
avian.VMMethod[] ivtable = SystemClassLoader.vmClass(c).virtualTable;
|
||||
if (ivtable != null) {
|
||||
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()) {
|
||||
methodTable[i] = new MethodData
|
||||
(0,
|
||||
ConstantPool.addUtf8(pool, Method.getName(m)),
|
||||
ConstantPool.addUtf8(pool, Method.getSpec(m)),
|
||||
ConstantPool.addUtf8(pool, Classes.toString(m.name)),
|
||||
ConstantPool.addUtf8(pool, Classes.toString(m.spec)),
|
||||
makeInvokeCode(pool, name, m.spec, m.parameterCount,
|
||||
m.parameterFootprint, i));
|
||||
++ i;
|
||||
}
|
||||
|
||||
methodTable[i++] = new MethodData
|
||||
(0,
|
||||
(Modifier.PUBLIC,
|
||||
ConstantPool.addUtf8(pool, "<init>"),
|
||||
ConstantPool.addUtf8
|
||||
(pool, "(Ljava/lang/reflect/InvocationHandler;)V"),
|
||||
|
7
makefile
7
makefile
@ -163,7 +163,6 @@ ifneq ($(android),)
|
||||
-I$(android)/libcore/include \
|
||||
-I$(build)/android-src/external/fdlibm \
|
||||
-I$(build)/android-src \
|
||||
-fpermissive \
|
||||
-fno-exceptions \
|
||||
-DHAVE_SYS_UIO_H \
|
||||
-D_FILE_OFFSET_BITS=64 \
|
||||
@ -1200,6 +1199,7 @@ ifneq ($(classpath),avian)
|
||||
# them to synthesize a class:
|
||||
classpath-sources := \
|
||||
$(classpath-src)/avian/Addendum.java \
|
||||
$(classpath-src)/avian/AnnotationInvocationHandler.java \
|
||||
$(classpath-src)/avian/Assembler.java \
|
||||
$(classpath-src)/avian/Callback.java \
|
||||
$(classpath-src)/avian/CallbackReceiver.java \
|
||||
@ -1230,7 +1230,7 @@ ifneq ($(classpath),avian)
|
||||
$(classpath-src)/java/net/StandardProtocolFamily.java \
|
||||
$(classpath-src)/sun/misc/Cleaner.java \
|
||||
$(classpath-src)/sun/misc/Unsafe.java \
|
||||
$(classpath-src)/avian/Android.java
|
||||
$(classpath-src)/java/lang/reflect/Proxy.java
|
||||
endif
|
||||
else
|
||||
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
|
||||
$(javac) -Xmaxerrs 1000 -d $(build)/android -sourcepath $(luni-java) \
|
||||
@$(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)
|
||||
@touch $(@)
|
||||
|
||||
|
@ -50,6 +50,15 @@ resolveSystemClassThrow(Thread* t, object loader, object spec)
|
||||
|
||||
} // 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
|
||||
Avian_avian_Classes_acquireClassLock
|
||||
(Thread* t, object, uintptr_t*)
|
||||
@ -75,6 +84,26 @@ Avian_avian_Classes_resolveVMClass
|
||||
(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
|
||||
Avian_avian_SystemClassLoader_findLoadedVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
@ -85,6 +114,14 @@ Avian_avian_SystemClassLoader_findLoadedVMClass
|
||||
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
|
||||
Avian_avian_SystemClassLoader_findVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
|
@ -26,6 +26,24 @@ namespace {
|
||||
|
||||
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 {
|
||||
public:
|
||||
MyClasspath(Allocator* allocator):
|
||||
@ -85,6 +103,21 @@ class MyClasspath : public Classpath {
|
||||
setObjectClass(t, thread, type(t, Machine::ThreadType));
|
||||
threadPriority(t, thread) = NormalPriority;
|
||||
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;
|
||||
}
|
||||
@ -138,6 +171,30 @@ class MyClasspath : public Classpath {
|
||||
virtual void
|
||||
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);
|
||||
}
|
||||
|
||||
@ -153,6 +210,48 @@ class MyClasspath : public Classpath {
|
||||
// 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
|
||||
dispose()
|
||||
{
|
||||
@ -162,6 +261,47 @@ class MyClasspath : public Classpath {
|
||||
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
|
||||
@ -346,6 +486,23 @@ Avian_java_lang_String_fastIndexOf
|
||||
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
|
||||
Avian_java_lang_Class_getComponentType
|
||||
(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
|
||||
Avian_java_lang_Class_getDeclaredField
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
@ -377,13 +553,17 @@ Avian_java_lang_Class_getDeclaredField
|
||||
PROTECT(t, name);
|
||||
|
||||
object method = resolveMethod
|
||||
(t, root(t, Machine::BootLoader), "avian/Android", "findField",
|
||||
"(Lavian/VMClass;Ljava/lang/String;)Lavian/VMField;");
|
||||
(t, root(t, Machine::BootLoader), "avian/Classes", "findField",
|
||||
"(Lavian/VMClass;Ljava/lang/String;)I");
|
||||
|
||||
object field = t->m->processor->invoke
|
||||
(t, method, 0, jclassVmClass(t, c), name);
|
||||
int index = intValue
|
||||
(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);
|
||||
|
||||
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
|
||||
Avian_dalvik_system_VMRuntime_bootClassPath
|
||||
(Thread* t, object, uintptr_t*)
|
||||
@ -467,3 +716,456 @@ Avian_java_lang_VMThread_currentThread
|
||||
{
|
||||
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]));
|
||||
}
|
||||
|
||||
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
|
||||
Avian_avian_Classes_isAssignableFrom
|
||||
(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
|
||||
|
||||
#endif//CLASSPATH_COMMON_H
|
||||
|
@ -1918,44 +1918,6 @@ loadLibrary(Thread* t, object, uintptr_t* arguments)
|
||||
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
|
||||
interceptFileOperations(Thread* t)
|
||||
{
|
||||
@ -2185,138 +2147,6 @@ countConstructors(Thread* t, object c, bool publicOnly)
|
||||
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
|
||||
makeJmethod(Thread* t, object vmMethod, int index)
|
||||
{
|
||||
@ -2330,18 +2160,18 @@ makeJmethod(Thread* t, object vmMethod, int index)
|
||||
|
||||
unsigned parameterCount;
|
||||
unsigned returnTypeSpec;
|
||||
object parameterTypes = local::resolveParameterJTypes
|
||||
object parameterTypes = resolveParameterJTypes
|
||||
(t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod),
|
||||
¶meterCount, &returnTypeSpec);
|
||||
PROTECT(t, parameterTypes);
|
||||
|
||||
object returnType = local::resolveJType
|
||||
object returnType = resolveJType
|
||||
(t, classLoader(t, methodClass(t, vmMethod)), reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, methodSpec(t, vmMethod), returnTypeSpec)),
|
||||
byteArrayLength(t, methodSpec(t, vmMethod)) - 1 - returnTypeSpec);
|
||||
PROTECT(t, returnType);
|
||||
|
||||
object exceptionTypes = local::resolveExceptionJTypes
|
||||
object exceptionTypes = resolveExceptionJTypes
|
||||
(t, classLoader(t, methodClass(t, vmMethod)),
|
||||
methodAddendum(t, vmMethod));
|
||||
PROTECT(t, exceptionTypes);
|
||||
@ -2406,12 +2236,12 @@ makeJconstructor(Thread* t, object vmMethod, int index)
|
||||
|
||||
unsigned parameterCount;
|
||||
unsigned returnTypeSpec;
|
||||
object parameterTypes = local::resolveParameterJTypes
|
||||
object parameterTypes = resolveParameterJTypes
|
||||
(t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod),
|
||||
¶meterCount, &returnTypeSpec);
|
||||
PROTECT(t, parameterTypes);
|
||||
|
||||
object exceptionTypes = local::resolveExceptionJTypes
|
||||
object exceptionTypes = resolveExceptionJTypes
|
||||
(t, classLoader(t, methodClass(t, vmMethod)),
|
||||
methodAddendum(t, vmMethod));
|
||||
PROTECT(t, exceptionTypes);
|
||||
@ -4777,83 +4607,10 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments)
|
||||
(t, jclassVmClass(t, jmethodClazz(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>
|
||||
(makeLocalReference(t, translateInvokeResult(t, returnCode, result)));
|
||||
(makeLocalReference
|
||||
(t, invoke
|
||||
(t, vmMethod, instance ? *instance : 0, args ? *args : 0)));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
|
@ -3401,27 +3401,56 @@ PopLocalFrame(Thread* t, jobject result)
|
||||
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
|
||||
NewDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
||||
{
|
||||
jclass c = FindClass(t, "java/nio/DirectByteBuffer");
|
||||
return NewObject(t, c, GetMethodID(t, c, "<init>", "(JI)V"),
|
||||
reinterpret_cast<jlong>(p),
|
||||
static_cast<jint>(capacity));
|
||||
uintptr_t arguments[1 + (sizeof(jlong) / BytesPerWord)];
|
||||
arguments[0] = reinterpret_cast<uintptr_t>(p);
|
||||
memcpy(arguments + 1, &capacity, sizeof(jlong));
|
||||
|
||||
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
|
||||
GetDirectBufferAddress(Thread* t, jobject b)
|
||||
{
|
||||
return reinterpret_cast<void*>
|
||||
(GetLongField(t, b, GetFieldID(t, GetObjectClass(t, b), "address", "J")));
|
||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(b) };
|
||||
|
||||
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
|
||||
GetDirectBufferCapacity(Thread* t, jobject b)
|
||||
{
|
||||
return GetIntField
|
||||
(t, b, GetFieldID(t, GetObjectClass(t, b), "capacity", "I"));
|
||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(b) };
|
||||
|
||||
return run(t, getDirectBufferCapacity, arguments);
|
||||
}
|
||||
|
||||
struct JavaVMOption {
|
||||
|
@ -2369,8 +2369,6 @@ object
|
||||
makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
|
||||
object elementClass)
|
||||
{
|
||||
// todo: arrays should implement Cloneable and Serializable
|
||||
|
||||
if (classVmFlags(t, type(t, Machine::JobjectType)) & BootstrapFlag) {
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, spec);
|
||||
@ -2398,7 +2396,7 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
|
||||
spec,
|
||||
0,
|
||||
type(t, Machine::JobjectType),
|
||||
0,
|
||||
root(t, Machine::ArrayInterfaceTable),
|
||||
vtable,
|
||||
0,
|
||||
0,
|
||||
@ -2733,6 +2731,33 @@ boot(Thread* t)
|
||||
|
||||
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);
|
||||
|
||||
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||
|
@ -1227,10 +1227,11 @@ class Machine {
|
||||
OutOfMemoryError,
|
||||
Shutdown,
|
||||
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,
|
||||
Processor* processor, Classpath* classpath, const char** properties,
|
||||
@ -1569,6 +1570,15 @@ class Classpath {
|
||||
virtual void
|
||||
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
|
||||
dispose() = 0;
|
||||
};
|
||||
|
31
src/target.h
31
src/target.h
@ -23,11 +23,9 @@ targetV1(T v)
|
||||
return v;
|
||||
}
|
||||
|
||||
#ifdef TARGET_OPPOSITE_ENDIAN
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetV2(T v)
|
||||
swapV2(T v)
|
||||
{
|
||||
return (((v >> 8) & 0xFF) |
|
||||
((v << 8)));
|
||||
@ -35,7 +33,7 @@ targetV2(T v)
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetV4(T v)
|
||||
swapV4(T v)
|
||||
{
|
||||
return (((v >> 24) & 0x000000FF) |
|
||||
((v >> 8) & 0x0000FF00) |
|
||||
@ -45,7 +43,7 @@ targetV4(T v)
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetV8(T v)
|
||||
swapV8(T v)
|
||||
{
|
||||
return (((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) |
|
||||
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) |
|
||||
@ -57,6 +55,29 @@ targetV8(T v)
|
||||
((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
|
||||
template <class T>
|
||||
inline T
|
||||
|
@ -16,6 +16,10 @@
|
||||
|
||||
(type constantPool sun/reflect/ConstantPool)
|
||||
|
||||
(type serializable java/io/Serializable)
|
||||
|
||||
(type cloneable java/lang/Cloneable)
|
||||
|
||||
(type singleton
|
||||
(array uintptr_t body))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user