more Android class library work

This commit is contained in:
Joel Dice 2013-02-21 15:37:17 -07:00
parent 204bbc134d
commit 42d39b1af1
17 changed files with 1327 additions and 513 deletions

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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) {

View File

@ -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);

View File

@ -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 {

View File

@ -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"),

View File

@ -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 $(@)

View File

@ -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)

View File

@ -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),
&parameterCount, &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]));
}

View File

@ -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)

View File

@ -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

View File

@ -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),
&parameterCount, &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),
&parameterCount, &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

View File

@ -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 {

View File

@ -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);

View File

@ -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;
};

View File

@ -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

View File

@ -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))