diff --git a/README.md b/README.md index a33af84539..42b3e99859 100644 --- a/README.md +++ b/README.md @@ -370,7 +370,7 @@ the following, starting from the Avian directory: git clone https://android.googlesource.com/platform/system/core \ system/core (cd system/core && \ - git checkout fafcabd0dd4432de3c7f5956edec23f6ed241b56) + git checkout 373c77583f9d8eab88e4321d1a2e2af8f5ae8ea7) git clone https://android.googlesource.com/platform/external/fdlibm \ external/fdlibm @@ -380,11 +380,11 @@ the following, starting from the Avian directory: git clone https://android.googlesource.com/platform/external/icu4c \ external/icu4c (cd external/icu4c && \ - git checkout 8fd45e08f1054d80a356ef8aa05659a2ba84707c) + git checkout e5311394ca22b280da41cd17059288dab3fb1ea6) git clone https://android.googlesource.com/platform/libnativehelper (cd libnativehelper && \ - git checkout cf5ac0ec696fce7fac6b324ec7d4d6da217e501c) + git checkout b14825c7c75420049e03849994265be651cc4a4e) git clone https://android.googlesource.com/platform/external/openssl \ external/openssl @@ -396,10 +396,16 @@ the following, starting from the Avian directory: (cd external/zlib && \ git checkout 15b6223aa57a347ce113729253802cb2fdeb4ad0) + git clone https://github.com/dicej/android-conscrypt external/conscrypt + (cd external/conscrypt && \ + git checkout a96719f834232634e9160873bd4c44834b84eb15) + git clone git://git.openssl.org/openssl.git openssl-upstream (cd openssl-upstream && git checkout OpenSSL_1_0_1h) git clone https://github.com/dicej/android-libcore64 libcore + (cd libcore && \ + git checkout 69a1fd8623b85f978ead36dcf1c6c78c5ff79932) curl -Of http://oss.readytalk.com/avian-web/expat-2.1.0.tar.gz (cd external && tar xzf ../expat-2.1.0.tar.gz && mv expat-2.1.0 expat) @@ -427,7 +433,11 @@ for x86_64 OS X instead of 'CC="gcc -fPIC" ./config': Note that we use https://github.com/dicej/android-libcore64 above instead of the upstream https://android.googlesource.com/platform/libcore repository, since -the former has patches to provide better support for non-Linux platforms. +the former has patches to provide better support for non-Linux +platforms. We have also forked +https://android.googlesource.com/platform/external/conscrypt as +https://github.com/dicej/android-conscrypt to patch that project as +well. Also note that we use the upstream OpenSSL repository and apply the Android patches to it. This is because it is not clear how to build diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index 0bd05310fb..34877d5ef2 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -576,4 +576,6 @@ public class Classes { private static native void acquireClassLock(); private static native void releaseClassLock(); + + public static native String makeString(byte[] array, int offset, int length); } diff --git a/classpath/dalvik/system/BaseDexClassLoader.java b/classpath/dalvik/system/BaseDexClassLoader.java new file mode 100644 index 0000000000..27049cea21 --- /dev/null +++ b/classpath/dalvik/system/BaseDexClassLoader.java @@ -0,0 +1,5 @@ +package dalvik.system; + +public class BaseDexClassLoader extends ClassLoader { + public native String getLdLibraryPath(); +} diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index 6e2708d39e..36db9bd1e0 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -18,10 +18,12 @@ import avian.Classes; import avian.InnerClassReference; import java.lang.reflect.Constructor; +import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Method; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; import java.lang.reflect.Proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; @@ -38,7 +40,9 @@ import java.security.ProtectionDomain; import java.security.Permissions; import java.security.AllPermission; -public final class Class implements Type, AnnotatedElement { +public final class Class + implements Type, AnnotatedElement, GenericDeclaration +{ private static final int PrimitiveFlag = 1 << 5; private static final int EnumFlag = 1 << 14; @@ -96,9 +100,8 @@ public final class Class implements Type, AnnotatedElement { } } - return new String - (replace('/', '.', c.name, 0, c.name.length - 1), 0, c.name.length - 1, - false); + return Classes.makeString + (replace('/', '.', c.name, 0, c.name.length - 1), 0, c.name.length - 1); } public String getCanonicalName() { @@ -495,6 +498,10 @@ public final class Class implements Type, AnnotatedElement { return (vmClass.flags & Modifier.INTERFACE) != 0; } + public boolean isAnnotation() { + return (vmClass.flags & 0x2000) != 0; + } + public Class getSuperclass() { return (vmClass.super_ == null ? null : SystemClassLoader.getClass(vmClass.super_)); } @@ -521,9 +528,11 @@ public final class Class implements Type, AnnotatedElement { } public URL getResource(String path) { - if (! path.startsWith("/")) { - String name = new String - (vmClass.name, 0, vmClass.name.length - 1, false); + if (path.startsWith("/")) { + path = path.substring(1); + } else { + String name = Classes.makeString + (vmClass.name, 0, vmClass.name.length - 1); int index = name.lastIndexOf('/'); if (index >= 0) { path = name.substring(0, index) + "/" + path; @@ -646,4 +655,12 @@ public final class Class implements Type, AnnotatedElement { public ProtectionDomain getProtectionDomain() { return Classes.getProtectionDomain(vmClass); } + + public TypeVariable[] getTypeParameters() { + throw new UnsupportedOperationException("not yet implemented"); + } + + public Type[] getGenericInterfaces() { + throw new UnsupportedOperationException("not yet implemented"); + } } diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index 0a75c98b6f..8f7ec5a1f9 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -19,6 +19,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.Map; import java.util.HashMap; +import java.security.ProtectionDomain; public abstract class ClassLoader { private final ClassLoader parent; @@ -92,6 +93,12 @@ public abstract class ClassLoader { (avian.Classes.defineVMClass(this, b, offset, length)); } + protected Class defineClass(String name, byte[] b, int offset, int length, + ProtectionDomain domain) + { + return defineClass(name, b, offset, length); + } + protected Class findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(); } @@ -196,6 +203,10 @@ public abstract class ClassLoader { return urls; } + protected String findLibrary(String name) { + return null; + } + static native Class getCaller(); static native void load(String name, Class caller, boolean mapName); diff --git a/classpath/java/lang/reflect/Constructor.java b/classpath/java/lang/reflect/Constructor.java index e28b56c1be..c320350846 100644 --- a/classpath/java/lang/reflect/Constructor.java +++ b/classpath/java/lang/reflect/Constructor.java @@ -44,6 +44,10 @@ public class Constructor extends AccessibleObject implements Member { return method.getModifiers(); } + public boolean isSynthetic() { + return method.isSynthetic(); + } + public String getName() { return method.getName(); } @@ -70,4 +74,8 @@ public class Constructor extends AccessibleObject implements Member { method.invoke(v, arguments); return v; } + + public Class[] getExceptionTypes() { + throw new UnsupportedOperationException("not yet implemented"); + } } diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index eb5303e742..c66a3f9bc9 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -57,13 +57,13 @@ public class Field extends AccessibleObject { } public static String getName(VMField vmField) { - return new String(vmField.name, 0, vmField.name.length - 1, false); + return Classes.makeString(vmField.name, 0, vmField.name.length - 1); } public Class getType() { return Classes.forCanonicalName (vmField.class_.loader, - new String(vmField.spec, 0, vmField.spec.length - 1, false)); + Classes.makeString(vmField.spec, 0, vmField.spec.length - 1)); } public Type getGenericType() { diff --git a/classpath/java/lang/reflect/GenericDeclaration.java b/classpath/java/lang/reflect/GenericDeclaration.java new file mode 100644 index 0000000000..d167aeb549 --- /dev/null +++ b/classpath/java/lang/reflect/GenericDeclaration.java @@ -0,0 +1,5 @@ +package java.lang.reflect; + +public interface GenericDeclaration { + TypeVariable[] getTypeParameters(); +} diff --git a/classpath/java/lang/reflect/Member.java b/classpath/java/lang/reflect/Member.java index 7f8dc10595..a21d231ff0 100644 --- a/classpath/java/lang/reflect/Member.java +++ b/classpath/java/lang/reflect/Member.java @@ -19,4 +19,6 @@ public interface Member { public int getModifiers(); public String getName(); + + public boolean isSynthetic(); } diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 6a8e8e189d..4c6443e488 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -52,7 +52,7 @@ public class Method extends AccessibleObject implements Member { } public static String getName(VMMethod vmMethod) { - return new String(vmMethod.name, 0, vmMethod.name.length - 1, false); + return Classes.makeString(vmMethod.name, 0, vmMethod.name.length - 1); } private String getSpec() { @@ -60,7 +60,7 @@ public class Method extends AccessibleObject implements Member { } public static String getSpec(VMMethod vmMethod) { - return new String(vmMethod.spec, 0, vmMethod.spec.length - 1, false); + return Classes.makeString(vmMethod.spec, 0, vmMethod.spec.length - 1); } public Class[] getParameterTypes() { @@ -107,8 +107,8 @@ public class Method extends AccessibleObject implements Member { if (vmMethod.spec[i] == ')') { return Classes.forCanonicalName (vmMethod.class_.loader, - new String - (vmMethod.spec, i + 1, vmMethod.spec.length - i - 2, false)); + Classes.makeString + (vmMethod.spec, i + 1, vmMethod.spec.length - i - 2)); } } throw new RuntimeException(); @@ -149,8 +149,16 @@ public class Method extends AccessibleObject implements Member { return (getModifiers() & 0x80) != 0; } + public boolean isSynthetic() { + return (getModifiers() & 0x1000) != 0; + } + public Object getDefaultValue() { ClassLoader loader = getDeclaringClass().getClassLoader(); return Classes.getAnnotationDefaultValue(loader, vmMethod.addendum); } + + public Class[] getExceptionTypes() { + throw new UnsupportedOperationException("not yet implemented"); + } } diff --git a/classpath/java/lang/reflect/TypeVariable.java b/classpath/java/lang/reflect/TypeVariable.java new file mode 100644 index 0000000000..63f9dcb499 --- /dev/null +++ b/classpath/java/lang/reflect/TypeVariable.java @@ -0,0 +1,5 @@ +package java.lang.reflect; + +public interface TypeVariable extends Type { + +} diff --git a/classpath/libcore/reflect/AnnotationAccess.java b/classpath/libcore/reflect/AnnotationAccess.java new file mode 100644 index 0000000000..750fe9cadf --- /dev/null +++ b/classpath/libcore/reflect/AnnotationAccess.java @@ -0,0 +1,8 @@ +package libcore.reflect; + +import java.lang.reflect.AccessibleObject; + +public class AnnotationAccess { + public static native AccessibleObject getEnclosingMethodOrConstructor + (Class c); +} diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java index 10325b04b1..6d733aa801 100644 --- a/classpath/sun/misc/Unsafe.java +++ b/classpath/sun/misc/Unsafe.java @@ -88,6 +88,14 @@ public final class Unsafe { public native void putLongVolatile(Object o, long offset, long x); + public long getLong(Object o, long offset) { + return getLongVolatile(o, offset); + } + + public void putLong(Object o, long offset, long x) { + putLongVolatile(o, offset, x); + } + public native void putOrderedLong(Object o, long offset, long x); public native void putOrderedInt(Object o, long offset, int x); diff --git a/makefile b/makefile index 7b5a44a30f..ff4fbb8fb2 100755 --- a/makefile +++ b/makefile @@ -219,12 +219,14 @@ ifneq ($(android),) classpath-cflags = -DBOOT_JAVAHOME android-cflags = -I$(luni-native) \ -I$(android)/libnativehelper/include/nativehelper \ + -I$(android)/libnativehelper \ -I$(android)/system/core/include \ -I$(android)/external/zlib \ -I$(android)/external/icu4c/i18n \ -I$(android)/external/icu4c/common \ -I$(android)/external/expat \ -I$(android)/external/openssl/include \ + -I$(android)/external/openssl \ -I$(android)/libcore/include \ -I$(build)/android-src/external/fdlibm \ -I$(build)/android-src \ @@ -234,33 +236,38 @@ ifneq ($(android),) -DJNI_JARJAR_PREFIX= \ -D__DARWIN_UNIX03=1 \ -D__PROVIDE_FIXMES \ + -DSTATIC_LIB \ -g3 \ - -Werror + -Werror \ + -Wno-shift-count-overflow luni-cpps := $(shell find $(luni-native) -name '*.cpp') + libziparchive-native := $(android)/system/core/libziparchive + libziparchive-ccs := $(libziparchive-native)/zip_archive.cc + + libutils-native := $(android)/system/core/libutils + libutils-cpps := $(libutils-native)/FileMap.cpp + libnativehelper-native := $(android)/libnativehelper libnativehelper-cpps := $(libnativehelper-native)/JniConstants.cpp \ $(libnativehelper-native)/toStringArray.cpp - crypto-native := $(android)/libcore/crypto/src/main/native - + crypto-native := $(android)/external/conscrypt/src/main/native crypto-cpps := $(crypto-native)/org_conscrypt_NativeCrypto.cpp ifeq ($(platform),windows) - android-cflags += -D__STDC_CONSTANT_MACROS + android-cflags += -D__STDC_CONSTANT_MACROS -DHAVE_WIN32_FILEMAP blacklist = $(luni-native)/java_io_Console.cpp \ - $(luni-native)/java_lang_ProcessManager.cpp \ - $(luni-native)/java_math_NativeBN.cpp \ - $(luni-native)/libcore_net_RawSocket.cpp + $(luni-native)/java_lang_ProcessManager.cpp icu-libs := $(android)/external/icu4c/lib/sicuin.a \ $(android)/external/icu4c/lib/sicuuc.a \ $(android)/external/icu4c/lib/sicudt.a platform-lflags := -lgdi32 -lshlwapi -lwsock32 else - android-cflags += -fPIC -DHAVE_SYS_UIO_H - blacklist = $(luni-native)/java_math_NativeBN.cpp + android-cflags += -fPIC -DHAVE_SYS_UIO_H -DHAVE_POSIX_FILEMAP + blacklist = icu-libs := $(android)/external/icu4c/lib/libicui18n.a \ $(android)/external/icu4c/lib/libicuuc.a \ @@ -278,30 +285,61 @@ ifneq ($(android),) -lstdc++ ifeq ($(platform),linux) + android-cflags += -DHAVE_OFF64_T classpath-lflags += -lrt endif classpath-objects = \ $(call cpp-objects,$(luni-cpps),$(luni-native),$(build)) \ $(call cpp-objects,$(crypto-cpps),$(crypto-native),$(build)) \ - $(call cpp-objects,$(libnativehelper-cpps),$(libnativehelper-native),$(build)) + $(call cpp-objects,$(libnativehelper-cpps),$(libnativehelper-native),$(build)) \ + $(call cc-objects,$(libziparchive-ccs),$(libziparchive-native),$(build)) \ + $(call cpp-objects,$(libutils-cpps),$(libutils-native),$(build)) luni-java = $(android)/libcore/luni/src/main/java - luni-javas := $(shell find $(luni-java) -name '*.java') + + luni-blacklist = \ + $(luni-java)/libcore/reflect/AnnotationAccess.java + + luni-javas := \ + $(filter-out $(luni-blacklist),$(shell find $(luni-java) -name '*.java')) + luni-nonjavas := $(shell find $(luni-java) -not -type d -not -name '*.java') luni-copied-nonjavas = $(call noop-files,$(luni-nonjavas),$(luni-java),) - libdvm-java = $(android)/libcore/libdvm/src/main/java - libdvm-javas := $(shell find $(libdvm-java) -name '*.java') - crypto-java = $(android)/libcore/crypto/src/main/java + + crypto-java = $(android)/external/conscrypt/src/main/java crypto-javas := $(shell find $(crypto-java) -name '*.java') + + crypto-platform-java = $(android)/external/conscrypt/src/platform/java + crypto-platform-javas := $(shell find $(crypto-platform-java) -name '*.java') + dalvik-java = $(android)/libcore/dalvik/src/main/java - dalvik-javas := $(shell find $(dalvik-java) -name '*.java') + dalvik-javas := \ + $(dalvik-java)/dalvik/system/DalvikLogHandler.java \ + $(dalvik-java)/dalvik/system/CloseGuard.java \ + $(dalvik-java)/dalvik/system/VMDebug.java \ + $(dalvik-java)/dalvik/system/BlockGuard.java \ + $(dalvik-java)/dalvik/system/SocketTagger.java \ + $(dalvik-java)/dalvik/system/DalvikLogging.java \ + + libart-java = $(android)/libcore/libart/src/main/java + libart-javas := \ + $(libart-java)/dalvik/system/VMRuntime.java \ + $(libart-java)/dalvik/system/VMStack.java \ + $(libart-java)/java/lang/Thread.java \ + $(libart-java)/java/lang/ThreadGroup.java \ + $(libart-java)/java/lang/Enum.java \ + $(libart-java)/java/lang/String.java \ + $(libart-java)/java/lang/ref/Reference.java \ + $(libart-java)/java/lang/reflect/AccessibleObject.java \ + xml-java = $(android)/libcore/xml/src/main/java xml-javas := $(shell find $(xml-java) -name '*.java') android-classes = \ $(call java-classes,$(luni-javas),$(luni-java),$(build)/android) \ - $(call java-classes,$(libdvm-javas),$(libdvm-java),$(build)/android) \ $(call java-classes,$(crypto-javas),$(crypto-java),$(build)/android) \ + $(call java-classes,$(crypto-platform-javas),$(crypto-platform-java),$(build)/android) \ $(call java-classes,$(dalvik-javas),$(dalvik-java),$(build)/android) \ + $(call java-classes,$(libart-javas),$(libart-java),$(build)/android) \ $(call java-classes,$(xml-javas),$(xml-java),$(build)/android) classpath = android @@ -1114,6 +1152,7 @@ endif c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x))) +cc-objects = $(foreach x,$(1),$(patsubst $(2)/%.cc,$(3)/%.o,$(x))) asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.$(asm-format),$(3)/%-asm.o,$(x))) java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x))) noop-files = $(foreach x,$(1),$(patsubst $(2)/%,$(3)/%,$(x))) @@ -1384,13 +1423,23 @@ ifneq ($(classpath),avian) ifeq ($(openjdk),) classpath-sources := $(classpath-sources) \ + $(classpath-src)/dalvik/system/BaseDexClassLoader.java \ + $(classpath-src)/libcore/reflect/AnnotationAccess.java \ $(classpath-src)/sun/reflect/ConstantPool.java \ - $(classpath-src)/java/lang/ReflectiveOperationException.java \ $(classpath-src)/java/net/ProtocolFamily.java \ $(classpath-src)/java/net/StandardProtocolFamily.java \ $(classpath-src)/sun/misc/Cleaner.java \ $(classpath-src)/sun/misc/Unsafe.java \ - $(classpath-src)/java/lang/reflect/Proxy.java + $(classpath-src)/java/lang/Object.java \ + $(classpath-src)/java/lang/Class.java \ + $(classpath-src)/java/lang/ClassLoader.java \ + $(classpath-src)/java/lang/Package.java \ + $(classpath-src)/java/lang/reflect/Proxy.java \ + $(classpath-src)/java/lang/reflect/Field.java \ + $(classpath-src)/java/lang/reflect/SignatureParser.java \ + $(classpath-src)/java/lang/reflect/Constructor.java \ + $(classpath-src)/java/lang/reflect/AccessibleObject.java \ + $(classpath-src)/java/lang/reflect/Method.java endif else classpath-sources := $(shell find $(classpath-src) -name '*.java') @@ -1594,14 +1643,20 @@ $(build)/android-src/%.cpp: $(libnativehelper-native)/%.cpp $(build)/android-src/%.cpp: $(crypto-native)/%.cpp cp $(<) $(@) +$(build)/android-src/%.cpp: $(libziparchive-native)/%.cc + cp $(<) $(@) + +$(build)/android-src/%.cpp: $(libutils-native)/%.cpp + cp $(<) $(@) + $(build)/%.o: $(build)/android-src/%.cpp $(build)/android.dep @echo "compiling $(@)" @mkdir -p $(dir $(@)) $(cxx) $(android-cflags) $(classpath-extra-cflags) -c \ $$($(windows-path) $(<)) $(call output,$(@)) -$(build)/android.dep: $(luni-javas) $(libdvm-javas) $(crypto-javas) \ - $(dalvik-javas) $(xml-javas) $(luni-nonjavas) +$(build)/android.dep: $(luni-javas) $(dalvik-javas) $(libart-javas) \ + $(xml-javas) $(luni-nonjavas) $(crypto-javas) $(crypto-platform-javas) @echo "compiling luni classes" @mkdir -p $(classpath-build) @mkdir -p $(build)/android @@ -1609,11 +1664,26 @@ $(build)/android.dep: $(luni-javas) $(libdvm-javas) $(crypto-javas) \ @mkdir -p $(build)/android-src/libexpat cp $(android)/external/fdlibm/fdlibm.h $(build)/android-src/external/fdlibm/ cp $(android)/external/expat/lib/expat*.h $(build)/android-src/libexpat/ - cp -a $(luni-java)/* $(libdvm-java)/* $(crypto-java)/* $(dalvik-java)/* \ - $(xml-java)/* $(build)/android-src/ + cp -a $(luni-java)/* $(xml-java)/* $(build)/android-src/ + rm $(call noop-files,$(luni-blacklist),$(luni-java),$(build)/android-src) + (cd $(dalvik-java) && \ + jar c $(call noop-files,$(dalvik-javas),$(dalvik-java),.)) \ + | (cd $(build)/android-src && jar x) + (cd $(libart-java) && \ + jar c $(call noop-files,$(libart-javas),$(libart-java),.)) \ + | (cd $(build)/android-src && jar x) + (cd $(crypto-java) && \ + jar c $(call noop-files,$(crypto-javas),$(crypto-java),.)) \ + | (cd $(build)/android-src && jar x) + (cd $(crypto-platform-java) && \ + jar c $(call noop-files,$(crypto-platform-javas),$(crypto-platform-java),.)) \ + | (cd $(build)/android-src && jar x) + (cd $(classpath-src) && \ + jar c $(call noop-files,$(classpath-sources),$(classpath-src),.)) \ + | (cd $(build)/android-src && jar x) +# (cd android && jar c *) | (cd $(build)/android-src && jar x) find $(build)/android-src -name '*.java' > $(build)/android.txt - $(javac) -Xmaxerrs 1000 -d $(build)/android -sourcepath $(luni-java) \ - @$(build)/android.txt + $(javac) -Xmaxerrs 1000 -d $(build)/android @$(build)/android.txt rm $(build)/android/sun/misc/Unsafe* \ $(build)/android/java/lang/reflect/Proxy* for x in $(luni-copied-nonjavas); \ diff --git a/src/android/stubs.cpp b/src/android/stubs.cpp index 7fe9362a3d..0c1295d464 100644 --- a/src/android/stubs.cpp +++ b/src/android/stubs.cpp @@ -15,3 +15,10 @@ void JniConstants::init(_JNIEnv*) { // ignore } + +struct _JavaVM; + +int libconscrypt_JNI_OnLoad(_JavaVM*, void*) +{ + return 0; +} diff --git a/src/avian/classpath-common.h b/src/avian/classpath-common.h index 8c915c3a83..449167ea31 100644 --- a/src/avian/classpath-common.h +++ b/src/avian/classpath-common.h @@ -781,6 +781,116 @@ unsigned classModifiers(Thread* t, GcClass* c) return c->flags(); } +object makeMethod(Thread* t, GcJclass* class_, int index) +{ + GcMethod* method = cast( + t, cast(t, class_->vmClass()->methodTable())->body()[index]); + PROTECT(t, method); + + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "java/lang/reflect/Method"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + GcMethod* constructor = resolveMethod(t, c, "", "(Lavian/VMMethod;)V"); + + t->m->processor->invoke(t, constructor, instance, method); + + if (method->name()->body()[0] == '<') { + object oldInstance = instance; + + c = resolveClass( + t, roots(t)->bootLoader(), "java/lang/reflect/Constructor"); + + object instance = makeNew(t, c); + + GcMethod* constructor + = resolveMethod(t, c, "", "(Ljava/lang/Method;)V"); + + t->m->processor->invoke(t, constructor, instance, oldInstance); + } + + return instance; +} + +int64_t getPrimitive(Thread* t, object instance, int code, int offset) +{ + switch (code) { + case ByteField: + return fieldAtOffset(instance, offset); + case BooleanField: + return fieldAtOffset(instance, offset); + case CharField: + return fieldAtOffset(instance, offset); + case ShortField: + return fieldAtOffset(instance, offset); + case IntField: + return fieldAtOffset(instance, offset); + case LongField: + return fieldAtOffset(instance, offset); + case FloatField: + return fieldAtOffset(instance, offset); + case DoubleField: + return fieldAtOffset(instance, offset); + default: + abort(t); + } +} + +void setPrimitive(Thread* t, + object instance, + int code, + int offset, + int64_t value) +{ + switch (code) { + case ByteField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case BooleanField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case CharField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case ShortField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case IntField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case LongField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case FloatField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case DoubleField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + default: + abort(t); + } +} + +int64_t invokeMethod(Thread* t, GcMethod* method, object instance, object args) +{ + THREAD_RESOURCE0(t, { + if (t->exception) { + GcThrowable* exception = t->exception; + t->exception = makeThrowable( + t, GcInvocationTargetException::Type, 0, 0, exception); + } + }); + + unsigned returnCode = method->returnCode(); + + return reinterpret_cast(translateInvokeResult( + t, returnCode, t->m->processor->invokeArray(t, method, instance, args))); +} + } // namespace vm #endif // CLASSPATH_COMMON_H diff --git a/src/builtin.cpp b/src/builtin.cpp index ef535e74fd..a43c18d953 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -164,6 +164,18 @@ extern "C" AVIAN_EXPORT int64_t JNICALL return reinterpret_cast(defineClass(t, loader, buffer, length)); } +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_makeString(Thread* t, object, uintptr_t* arguments) +{ + GcByteArray* array + = cast(t, reinterpret_cast(arguments[0])); + int offset = arguments[1]; + int length = arguments[2]; + + return reinterpret_cast( + t->m->classpath->makeString(t, array, offset, length)); +} + extern "C" AVIAN_EXPORT int64_t JNICALL Avian_avian_SystemClassLoader_findLoadedVMClass(Thread* t, object, diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 52740558e5..0d71913b0d 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -9,6 +9,7 @@ details. */ struct JavaVM; +struct _JavaVM; struct _JNIEnv; struct JniConstants { @@ -17,6 +18,8 @@ struct JniConstants { extern "C" int JNI_OnLoad(JavaVM*, void*); +int libconscrypt_JNI_OnLoad(_JavaVM*, void*); + #define _POSIX_C_SOURCE 200112L #undef _GNU_SOURCE #include "avian/machine.h" @@ -69,6 +72,11 @@ void JNICALL loadLibrary(Thread* t, object, uintptr_t* arguments) } } +void JNICALL gc(Thread* t, object, uintptr_t*) +{ + collect(t, Heap::MajorCollection); +} + void JNICALL finalizeAllEnqueued(Thread*, object, uintptr_t*) { // ignore @@ -97,116 +105,6 @@ int64_t JNICALL mapData(Thread*, object, uintptr_t*); void JNICALL closeMemoryMappedFile(Thread*, GcMethod*, uintptr_t*); -object makeMethodOrConstructor(Thread* t, GcJclass* c, unsigned index) -{ - PROTECT(t, c); - - GcMethod* method = cast( - t, cast(t, c->vmClass()->methodTable())->body()[index]); - PROTECT(t, method); - - unsigned parameterCount; - unsigned returnTypeSpec; - object parameterTypes = resolveParameterJTypes(t, - method->class_()->loader(), - method->spec(), - ¶meterCount, - &returnTypeSpec); - PROTECT(t, parameterTypes); - - GcJclass* returnType = resolveJType( - t, - method->class_()->loader(), - reinterpret_cast(&method->spec()->body()[returnTypeSpec]), - method->spec()->length() - 1 - returnTypeSpec); - PROTECT(t, returnType); - - object exceptionTypes = resolveExceptionJTypes( - t, method->class_()->loader(), method->addendum()); - - if (method->name()->body()[0] == '<') { - return makeJconstructor( - t, 0, c, parameterTypes, exceptionTypes, 0, 0, 0, 0, index); - } else { - PROTECT(t, exceptionTypes); - - GcString* name = t->m->classpath->makeString( - t, method->name(), 0, method->name()->length() - 1); - - return makeJmethod(t, - 0, - index, - c, - name, - parameterTypes, - exceptionTypes, - returnType, - 0, - 0, - 0, - 0, - 0); - } -} - -object makeField(Thread* t, GcJclass* c, unsigned index) -{ - PROTECT(t, c); - - GcField* field = cast( - t, cast(t, c->vmClass()->fieldTable())->body()[index]); - - PROTECT(t, field); - - GcJclass* type = getJClass( - t, - resolveClassBySpec(t, - field->class_()->loader(), - reinterpret_cast(field->spec()->body().begin()), - field->spec()->length() - 1)); - PROTECT(t, type); - - GcString* name = t->m->classpath->makeString( - t, field->name(), 0, field->name()->length() - 1); - - return makeJfield(t, 0, c, type, 0, 0, name, index); -} - -void initVmThread(Thread* t, GcThread* thread, unsigned offset) -{ - PROTECT(t, thread); - - if (fieldAtOffset(thread, offset) == 0) { - GcClass* c = resolveClass(t, roots(t)->bootLoader(), "java/lang/VMThread"); - PROTECT(t, c); - - object instance = makeNew(t, c); - PROTECT(t, instance); - - GcMethod* constructor - = resolveMethod(t, c, "", "(Ljava/lang/Thread;)V"); - - t->m->processor->invoke(t, constructor, instance, thread); - - setField(t, thread, offset, instance); - } - - if (thread->group() == 0) { - thread->setGroup(t, t->javaThread->group()); - expect(t, thread->group()); - } -} - -void initVmThread(Thread* t, GcThread* thread) -{ - initVmThread(t, - thread, - resolveField(t, - objectClass(t, thread), - "vmThread", - "Ljava/lang/VMThread;")->offset()); -} - object translateStackTrace(Thread* t, object raw) { PROTECT(t, raw); @@ -253,9 +151,10 @@ class MyClasspath : public Classpath { { if (objectClass(t, array) == type(t, GcByteArray::Type)) { GcByteArray* byteArray = cast(t, array); - PROTECT(t, array); PROTECT(t, byteArray); + assertT(t, offset + length <= static_cast(byteArray->length())); + GcCharArray* charArray = makeCharArray(t, length); for (int i = 0; i < length; ++i) { expect(t, (byteArray->body()[offset + i] & 0x80) == 0); @@ -264,8 +163,13 @@ class MyClasspath : public Classpath { } array = charArray; + offset = 0; } else { expect(t, objectClass(t, array) == type(t, GcCharArray::Type)); + + assertT(t, + offset + length + <= static_cast(cast(t, array)->length())); } return vm::makeString(t, array, offset, length, 0); @@ -310,58 +214,35 @@ class MyClasspath : public Classpath { thread->setContextClassLoader(t, roots(t)->appLoader()); - initVmThread(t, thread); - return thread; } virtual object makeJMethod(Thread* t, GcMethod* vmMethod) { - GcArray* table = cast(t, vmMethod->class_()->methodTable()); - for (unsigned i = 0; i < table->length(); ++i) { - if (vmMethod == table->body()[i]) { - return makeMethodOrConstructor(t, getJClass(t, vmMethod->class_()), i); - } - } - abort(t); + PROTECT(t, vmMethod); + + GcJmethod* jmethod = makeJmethod(t, vmMethod, false); + + return vmMethod->name()->body()[0] == '<' + ? static_cast(makeJconstructor(t, jmethod)) + : static_cast(jmethod); } virtual GcMethod* getVMMethod(Thread* t, object jmethod) { - return cast( - t, - objectClass(t, jmethod) == type(t, GcJmethod::Type) - ? cast(t, - cast(t, jmethod) - ->declaringClass() - ->vmClass() - ->methodTable()) - ->body()[cast(t, jmethod)->slot()] - : cast(t, - cast(t, jmethod) - ->declaringClass() - ->vmClass() - ->methodTable()) - ->body()[cast(t, jmethod)->slot()]); + return objectClass(t, jmethod) == type(t, GcJmethod::Type) + ? cast(t, jmethod)->vmMethod() + : cast(t, jmethod)->method()->vmMethod(); } virtual object makeJField(Thread* t, GcField* vmField) { - GcArray* table = cast(t, vmField->class_()->fieldTable()); - for (unsigned i = 0; i < table->length(); ++i) { - if (vmField == table->body()[i]) { - return makeField(t, getJClass(t, vmField->class_()), i); - } - } - abort(t); + return makeJfield(t, vmField, false); } - virtual GcField* getVMField(Thread* t, GcJfield* jfield) + virtual GcField* getVMField(Thread* t UNUSED, GcJfield* jfield) { - return cast( - t, - cast(t, jfield->declaringClass()->vmClass()->fieldTable()) - ->body()[jfield->slot()]); + return jfield->vmField(); } virtual void clearInterrupted(Thread*) @@ -373,31 +254,16 @@ class MyClasspath : public Classpath { { // force monitor creation so we don't get an OutOfMemory error // later when we try to acquire it: - objectMonitor(t, t->javaThread, true); + objectMonitor(t, t->javaThread->lock(), true); - GcField* field = resolveField( - t, objectClass(t, t->javaThread), "vmThread", "Ljava/lang/VMThread;"); - - unsigned offset = field->offset(); - - THREAD_RESOURCE(t, unsigned, offset, { - object vmt = fieldAtOffset(t->javaThread, offset); - if (vmt) { - PROTECT(t, vmt); - vm::acquire(t, vmt); - fieldAtOffset(t->javaThread, offset) = 0; - vm::notifyAll(t, vmt); - vm::release(t, vmt); - } - - vm::acquire(t, t->javaThread); + THREAD_RESOURCE0(t, { + vm::acquire(t, t->javaThread->lock()); t->clearFlag(Thread::ActiveFlag); - vm::notifyAll(t, t->javaThread); - vm::release(t, t->javaThread); + t->javaThread->peer() = 0; + vm::notifyAll(t, t->javaThread->lock()); + vm::release(t, t->javaThread->lock()); }); - initVmThread(t, t->javaThread, offset); - GcMethod* method = resolveMethod( t, roots(t)->bootLoader(), "java/lang/Thread", "run", "()V"); @@ -427,6 +293,17 @@ class MyClasspath : public Classpath { } } + { + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "java/lang/System", false); + + if (c) { + PROTECT(t, c); + + intercept(t, c, "gc", "()V", voidPointer(gc), updateRuntimeData); + } + } + { GcClass* c = resolveClass( t, roots(t)->bootLoader(), "java/lang/ref/FinalizerReference", false); @@ -520,6 +397,8 @@ class MyClasspath : public Classpath { JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0); + libconscrypt_JNI_OnLoad(reinterpret_cast< ::_JavaVM*>(t->m), 0); + mayInitClasses_ = true; } @@ -528,20 +407,9 @@ class MyClasspath : public Classpath { return mayInitClasses_; } - virtual void boot(Thread* t) + virtual void boot(Thread*) { - GcClass* c - = resolveClass(t, roots(t)->bootLoader(), "java/lang/ClassLoader"); - PROTECT(t, c); - - GcMethod* constructor - = resolveMethod(t, c, "", "(Ljava/lang/ClassLoader;Z)V"); - PROTECT(t, constructor); - - t->m->processor->invoke(t, constructor, roots(t)->bootLoader(), 0, true); - - t->m->processor->invoke( - t, constructor, roots(t)->appLoader(), roots(t)->bootLoader(), false); + // ignore } virtual const char* bootClasspath() @@ -698,175 +566,6 @@ void JNICALL file); } -bool matchType(Thread* t, GcField* field, object o) -{ - switch (field->code()) { - case ByteField: - return objectClass(t, o) == type(t, GcByte::Type); - - case BooleanField: - return objectClass(t, o) == type(t, GcBoolean::Type); - - case CharField: - return objectClass(t, o) == type(t, GcChar::Type); - - case ShortField: - return objectClass(t, o) == type(t, GcShort::Type); - - case IntField: - return objectClass(t, o) == type(t, GcInt::Type); - - case LongField: - return objectClass(t, o) == type(t, GcLong::Type); - - case FloatField: - return objectClass(t, o) == type(t, GcFloat::Type); - - case DoubleField: - return objectClass(t, o) == type(t, GcDouble::Type); - - case ObjectField: - if (o == 0) { - return true; - } else { - PROTECT(t, o); - - GcByteArray* spec; - if (field->spec()->body()[0] == '[') { - spec = field->spec(); - } else { - spec = makeByteArray(t, field->spec()->length() - 2); - - memcpy(spec->body().begin(), - &field->spec()->body()[1], - field->spec()->length() - 3); - - spec->body()[field->spec()->length() - 3] = 0; - } - - return instanceOf(t, resolveClass(t, field->class_()->loader(), spec), o); - } - - default: - abort(t); - } -} - -object getField(Thread* t, GcField* field, object instance) -{ - PROTECT(t, field); - PROTECT(t, instance); - - initClass(t, field->class_()); - - object target; - if (field->flags() & ACC_STATIC) { - target = field->class_()->staticTable(); - } else if (instanceOf(t, field->class_(), instance)) { - target = instance; - } else { - throwNew(t, GcIllegalArgumentException::Type); - } - - unsigned offset = field->offset(); - switch (field->code()) { - case ByteField: - return makeByte(t, fieldAtOffset(target, offset)); - - case BooleanField: - return makeBoolean(t, fieldAtOffset(target, offset)); - - case CharField: - return makeChar(t, fieldAtOffset(target, offset)); - - case ShortField: - return makeShort(t, fieldAtOffset(target, offset)); - - case IntField: - return makeInt(t, fieldAtOffset(target, offset)); - - case LongField: - return makeLong(t, fieldAtOffset(target, offset)); - - case FloatField: - return makeFloat(t, fieldAtOffset(target, offset)); - - case DoubleField: - return makeDouble(t, fieldAtOffset(target, offset)); - - case ObjectField: - return fieldAtOffset(target, offset); - - default: - abort(t); - } -} - -void setField(Thread* t, GcField* field, object instance, object value) -{ - PROTECT(t, field); - PROTECT(t, instance); - PROTECT(t, value); - - if (not matchType(t, field, value)) { - throwNew(t, GcIllegalArgumentException::Type); - } - - object target; - if ((field->flags() & ACC_STATIC) != 0) { - target = field->class_()->staticTable(); - } else if (instanceOf(t, field->class_(), instance)) { - target = instance; - } else { - throwNew(t, GcIllegalArgumentException::Type); - } - PROTECT(t, target); - - initClass(t, field->class_()); - - unsigned offset = field->offset(); - switch (field->code()) { - case ByteField: - fieldAtOffset(target, offset) = cast(t, value)->value(); - break; - - case BooleanField: - fieldAtOffset(target, offset) = cast(t, value)->value(); - break; - - case CharField: - fieldAtOffset(target, offset) = cast(t, value)->value(); - break; - - case ShortField: - fieldAtOffset(target, offset) = cast(t, value)->value(); - break; - - case IntField: - fieldAtOffset(target, offset) = cast(t, value)->value(); - break; - - case LongField: - fieldAtOffset(target, offset) = cast(t, value)->value(); - break; - - case FloatField: - fieldAtOffset(target, offset) = cast(t, value)->value(); - break; - - case DoubleField: - fieldAtOffset(target, offset) = cast(t, value)->value(); - break; - - case ObjectField: - setField(t, target, offset, value); - break; - - default: - abort(t); - } -} - } // namespace local } // namespace @@ -1044,12 +743,6 @@ int register_org_apache_harmony_dalvik_NativeTestTarget(_JNIEnv*) return 0; } -int register_java_math_NativeBN(_JNIEnv*) -{ - // ignore - return 0; -} - extern "C" AVIAN_EXPORT int64_t JNICALL Avian_java_lang_String_compareTo(Thread* t, object, uintptr_t* arguments) { @@ -1123,208 +816,11 @@ extern "C" AVIAN_EXPORT int64_t JNICALL return -1; } -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getInterfaces(Thread* t, object, uintptr_t* arguments) -{ - GcJclass* c = cast(t, reinterpret_cast(arguments[0])); - - GcClassAddendum* addendum = c->vmClass()->addendum(); - if (addendum) { - GcArray* table = cast(t, addendum->interfaceTable()); - if (table) { - PROTECT(t, table); - - object array = makeObjectArray(t, table->length()); - PROTECT(t, array); - - for (unsigned i = 0; i < table->length(); ++i) { - GcJclass* c = getJClass(t, cast(t, table->body()[i])); - setField(t, - array, - ArrayBody + (i * BytesPerWord), - reinterpret_cast(c)); - } - - return reinterpret_cast(array); - } - } - - return reinterpret_cast( - makeObjectArray(t, type(t, GcJclass::Type), 0)); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getDeclaredClasses(Thread* t, - object, - uintptr_t* arguments) -{ - return reinterpret_cast(getDeclaredClasses( - t, - cast(t, reinterpret_cast(arguments[0]))->vmClass(), - arguments[1])); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_newInstanceImpl(Thread* t, - object, - uintptr_t* arguments) -{ - GcClass* c - = cast(t, reinterpret_cast(arguments[0]))->vmClass(); - - GcMethod* method = resolveMethod(t, c, "", "()V"); - PROTECT(t, method); - - object instance = makeNew(t, c); - PROTECT(t, instance); - - t->m->processor->invoke(t, method, instance); - - return reinterpret_cast(instance); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getComponentType(Thread* t, - object, - uintptr_t* arguments) -{ - GcJclass* c = cast(t, reinterpret_cast(arguments[0])); - - if (c->vmClass()->arrayDimensions()) { - uint8_t n = c->vmClass()->name()->body()[1]; - if (n != 'L' and n != '[') { - return reinterpret_cast(getJClass(t, primitiveClass(t, n))); - } else { - return reinterpret_cast( - getJClass(t, c->vmClass()->arrayElementClass())); - } - } else { - return 0; - } -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_classForName(Thread* t, object, uintptr_t* arguments) -{ - object name = reinterpret_cast(arguments[0]); - PROTECT(t, name); - - GcClassLoader* loader - = cast(t, reinterpret_cast(arguments[2])); - PROTECT(t, loader); - - GcMethod* method = resolveMethod( - t, - roots(t)->bootLoader(), - "avian/Classes", - "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); - - return reinterpret_cast(t->m->processor->invoke( - t, method, 0, name, static_cast(arguments[1]), loader)); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getDeclaredField(Thread* t, - object, - uintptr_t* arguments) -{ - GcJclass* c = cast(t, reinterpret_cast(arguments[0])); - PROTECT(t, c); - - object name = reinterpret_cast(arguments[1]); - PROTECT(t, name); - - GcMethod* method = resolveMethod(t, - roots(t)->bootLoader(), - "avian/Classes", - "findField", - "(Lavian/VMClass;Ljava/lang/String;)I"); - - int index = cast( - t, t->m->processor->invoke(t, method, 0, c->vmClass(), name)) - ->value(); - - if (index >= 0) { - return reinterpret_cast(local::makeField(t, c, index)); - } else { - return 0; - } -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getDeclaredConstructorOrMethod(Thread* t, - object, - uintptr_t* arguments) -{ - GcJclass* c = cast(t, reinterpret_cast(arguments[0])); - PROTECT(t, c); - - object name = reinterpret_cast(arguments[1]); - PROTECT(t, name); - - object parameterTypes = reinterpret_cast(arguments[2]); - PROTECT(t, parameterTypes); - - GcMethod* method - = resolveMethod(t, - roots(t)->bootLoader(), - "avian/Classes", - "findMethod", - "(Lavian/VMClass;Ljava/lang/String;[Ljava/lang/Class;)I"); - - int index = cast(t, - t->m->processor->invoke( - t, method, 0, c->vmClass(), name, parameterTypes)) - ->value(); - - if (index >= 0) { - return reinterpret_cast( - local::makeMethodOrConstructor(t, c, index)); - } else { - return 0; - } -} - extern "C" AVIAN_EXPORT int64_t JNICALL Avian_avian_SystemClassLoader_findLoadedVMClass(Thread*, object, uintptr_t*); -extern "C" AVIAN_EXPORT 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( - getJClass(t, cast(t, reinterpret_cast(v)))); - } else { - return 0; - } -} - -extern "C" AVIAN_EXPORT 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( - getJClass(t, cast(t, reinterpret_cast(v)))); - } else { - return 0; - } -} - extern "C" AVIAN_EXPORT int64_t JNICALL Avian_dalvik_system_VMRuntime_bootClassPath(Thread* t, object, uintptr_t*) { @@ -1374,6 +870,12 @@ extern "C" AVIAN_EXPORT void JNICALL collect(t, Heap::MajorCollection); } +extern "C" AVIAN_EXPORT jlong JNICALL + Avian_java_lang_Runtime_maxMemory(Thread* t, object, uintptr_t*) +{ + return t->m->heap->limit(); +} + extern "C" AVIAN_EXPORT void JNICALL Avian_java_lang_Runtime_nativeExit(Thread* t, object, uintptr_t* arguments) { @@ -1410,108 +912,111 @@ extern "C" AVIAN_EXPORT void JNICALL arguments[4]); } +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_System_arraycopyCharUnchecked(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_java_lang_System_arraycopy(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_System_arraycopyByteUnchecked(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_java_lang_System_arraycopy(t, method, arguments); +} + extern "C" AVIAN_EXPORT int64_t JNICALL Avian_sun_misc_Unsafe_objectFieldOffset(Thread* t, object, uintptr_t* arguments) { - GcJfield* jfield = cast(t, reinterpret_cast(arguments[1])); - return cast( - t, - cast(t, jfield->declaringClass()->vmClass()->fieldTable()) - ->body()[jfield->slot()])->offset(); + return cast(t, reinterpret_cast(arguments[1])) + ->vmField() + ->offset(); } extern "C" AVIAN_EXPORT void JNICALL - Avian_java_lang_VMThread_interrupt(Thread* t, object, uintptr_t* arguments) + Avian_java_lang_Thread_nativeInterrupt(Thread* t, + object, + uintptr_t* arguments) { - object vmThread = reinterpret_cast(arguments[0]); - PROTECT(t, vmThread); - - GcField* field = resolveField( - t, objectClass(t, vmThread), "thread", "Ljava/lang/Thread;"); - interrupt( t, reinterpret_cast( - cast(t, fieldAtOffset(vmThread, field->offset())) - ->peer())); + cast(t, reinterpret_cast(arguments[0]))->peer())); } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_VMThread_interrupted(Thread* t, object, uintptr_t*) + Avian_java_lang_Thread_interrupted(Thread* t, object, uintptr_t*) { return getAndClearInterrupted(t, t); } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_VMThread_isInterrupted(Thread* t, - object, - uintptr_t* arguments) + Avian_java_lang_Thread_isInterrupted(Thread* t, + object, + uintptr_t* arguments) { - object vmThread = reinterpret_cast(arguments[0]); - PROTECT(t, vmThread); - - GcField* field = resolveField( - t, objectClass(t, vmThread), "thread", "Ljava/lang/Thread;"); - - return cast(t, fieldAtOffset(vmThread, field->offset())) + return cast(t, reinterpret_cast(arguments[0])) ->interrupted(); } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_VMThread_getStatus(Thread*, object, uintptr_t*) + Avian_java_lang_Thread_nativeGetStatus(Thread*, + object, + uintptr_t* arguments) { - // todo - return 1; + enum { New, Runnable, Blocked, Waiting, TimedWaiting, Terminated }; + + // todo: more detail? (e.g. waiting, terminated, etc.) + return arguments[1] ? Runnable : New; } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_VMThread_currentThread(Thread* t, object, uintptr_t*) + Avian_java_lang_Thread_currentThread(Thread* t, object, uintptr_t*) { return reinterpret_cast(t->javaThread); } extern "C" AVIAN_EXPORT void JNICALL - Avian_java_lang_VMThread_create(Thread* t, object, uintptr_t* arguments) + Avian_java_lang_Thread_nativeCreate(Thread* t, object, uintptr_t* arguments) { - GcThread* thread = cast(t, reinterpret_cast(arguments[0])); - PROTECT(t, thread); - - local::initVmThread(t, thread); - startThread(t, thread); + startThread(t, cast(t, reinterpret_cast(arguments[0]))); } extern "C" AVIAN_EXPORT void JNICALL - Avian_java_lang_VMThread_sleep(Thread* t, object, uintptr_t* arguments) + Avian_java_lang_Thread_nativeSetName(Thread*, object, uintptr_t*) { + // ignore +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Thread_sleep(Thread* t, object, uintptr_t* arguments) +{ + object lock = reinterpret_cast(arguments[0]); + PROTECT(t, lock); + int64_t milliseconds; - memcpy(&milliseconds, arguments, 8); + memcpy(&milliseconds, arguments + 1, 8); if (arguments[2] > 0) ++milliseconds; if (milliseconds <= 0) milliseconds = 1; - if (t->javaThread->sleepLock() == 0) { - object lock = makeJobject(t); - t->javaThread->setSleepLock(t, lock); - } - - acquire(t, t->javaThread->sleepLock()); - vm::wait(t, t->javaThread->sleepLock(), milliseconds); - release(t, t->javaThread->sleepLock()); + acquire(t, lock); + vm::wait(t, lock, milliseconds); + release(t, lock); } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_VMThread_holdsLock(Thread* t, object, uintptr_t* arguments) + Avian_java_lang_Thread_nativeHoldsLock(Thread* t, + object, + uintptr_t* arguments) { - object vmThread = reinterpret_cast(arguments[0]); - PROTECT(t, vmThread); - - GcField* field = resolveField( - t, objectClass(t, vmThread), "thread", "Ljava/lang/Thread;"); - - if (cast(t, fieldAtOffset(vmThread, field->offset())) + if (cast(t, reinterpret_cast(arguments[0])) != t->javaThread) { throwNew(t, GcIllegalStateException::Type, @@ -1525,7 +1030,7 @@ extern "C" AVIAN_EXPORT int64_t JNICALL } extern "C" AVIAN_EXPORT void JNICALL - Avian_java_lang_VMThread_yield(Thread* t, object, uintptr_t*) + Avian_java_lang_Thread_yield(Thread* t, object, uintptr_t*) { t->m->system->yield(); } @@ -1573,6 +1078,46 @@ extern "C" AVIAN_EXPORT int64_t JNICALL return reinterpret_cast(v.loader); } +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMStack_getClosestUserClassLoader(Thread* t, + object, + uintptr_t* arguments) +{ + GcClassLoader* boot + = cast(t, reinterpret_cast(arguments[0])); + + GcClassLoader* app + = cast(t, reinterpret_cast(arguments[1])); + + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t, GcClassLoader* boot, GcClassLoader* app) + : t(t), loader(0), boot(boot), app(app) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + GcClassLoader* loader = walker->method()->class_()->loader(); + if (loader == boot or loader == app) { + return true; + } else { + this->loader = loader; + return false; + } + } + + Thread* t; + GcClassLoader* loader; + GcClassLoader* boot; + GcClassLoader* app; + } v(t, boot, app); + + t->m->processor->walkStack(t, &v); + + return reinterpret_cast(v.loader); +} + extern "C" AVIAN_EXPORT int64_t JNICALL Avian_dalvik_system_VMStack_getClasses(Thread* t, object, uintptr_t*) { @@ -1700,6 +1245,32 @@ extern "C" AVIAN_EXPORT int64_t JNICALL return v; } +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Object_toString(Thread* t, object, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + + unsigned hash = objectHash(t, this_); + GcString* s = makeString( + t, "%s@0x%x", objectClass(t, this_)->name()->body().begin(), hash); + + return reinterpret_cast(s); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Object_getVMClass(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + objectClass(t, reinterpret_cast(arguments[0]))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Object_clone(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + clone(t, reinterpret_cast(arguments[0]))); +} + extern "C" AVIAN_EXPORT void JNICALL Avian_java_lang_Object_wait(Thread* t, object, uintptr_t* arguments) { @@ -1715,13 +1286,6 @@ extern "C" AVIAN_EXPORT void JNICALL notifyAll(t, reinterpret_cast(arguments[0])); } -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Object_getClass(Thread* t, object, uintptr_t* arguments) -{ - return reinterpret_cast( - getJClass(t, objectClass(t, reinterpret_cast(arguments[0])))); -} - extern "C" AVIAN_EXPORT int64_t JNICALL Avian_java_lang_Object_hashCode(Thread* t, object, uintptr_t* arguments) { @@ -1729,633 +1293,80 @@ extern "C" AVIAN_EXPORT int64_t JNICALL } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Object_internalClone(Thread* t, - object, - uintptr_t* arguments) + Avian_java_lang_reflect_Method_getCaller(Thread* t, object, uintptr_t*) { - return reinterpret_cast( - clone(t, reinterpret_cast(arguments[1]))); + return reinterpret_cast(getCaller(t, 2)); } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getModifiers(Thread* t, object, uintptr_t* arguments) + Avian_java_lang_reflect_Method_invoke(Thread* t, + object, + uintptr_t* arguments) { - return classModifiers( - t, cast(t, reinterpret_cast(arguments[0]))->vmClass()); + return invokeMethod(t, + cast(t, reinterpret_cast(arguments[0])), + reinterpret_cast(arguments[1]), + reinterpret_cast(arguments[2])); } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getSuperclass(Thread* t, object, uintptr_t* arguments) + Avian_java_lang_reflect_Field_getObject(Thread*, + object, + uintptr_t* arguments) { - GcClass* c - = cast(t, reinterpret_cast(arguments[0]))->vmClass(); - if (c->flags() & ACC_INTERFACE) { - return 0; - } else { - GcClass* s = c->super(); - return s ? reinterpret_cast(getJClass(t, s)) : 0; - } + return reinterpret_cast(fieldAtOffset( + reinterpret_cast(arguments[0]), arguments[1])); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_reflect_Field_setObject(Thread* t, + object, + uintptr_t* arguments) +{ + setField(t, + reinterpret_cast(arguments[0]), + arguments[1], + reinterpret_cast(arguments[2])); } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_desiredAssertionStatus(Thread*, object, uintptr_t*) + Avian_java_lang_reflect_Field_getPrimitive(Thread* t, + object, + uintptr_t* arguments) { - return 1; + return getPrimitive( + t, reinterpret_cast(arguments[0]), arguments[1], arguments[2]); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_reflect_Field_setPrimitive(Thread* t, + object, + uintptr_t* arguments) +{ + int64_t value; + memcpy(&value, arguments + 3, 8); + + setPrimitive(t, + reinterpret_cast(arguments[0]), + arguments[1], + arguments[2], + value); } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getNameNative(Thread* t, object, uintptr_t* arguments) -{ - GcByteArray* name = cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->name(); - - THREAD_RUNTIME_ARRAY(t, char, s, name->length()); - replace('/', - '.', - RUNTIME_ARRAY_BODY(s), - reinterpret_cast(name->body().begin())); - - return reinterpret_cast( - makeString(t, "%s", RUNTIME_ARRAY_BODY(s))); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_isInterface(Thread* t, object, uintptr_t* arguments) -{ - return (cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->flags() & ACC_INTERFACE) != 0; -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_isPrimitive(Thread* t, object, uintptr_t* arguments) -{ - return (cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->vmFlags() & PrimitiveFlag) != 0; -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_isAnonymousClass(Thread* t, - object, - uintptr_t* arguments) -{ - GcByteArray* name = cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->name(); - - for (unsigned i = 0; i < name->length() - 1; ++i) { - int c = name->body()[i]; - if (c != '$' and (c < '0' or c > '9')) { - return false; - } - } - - return true; -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getClassLoader(Thread* t, - object, - uintptr_t* arguments) -{ - return reinterpret_cast( - cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->loader()); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_isAssignableFrom(Thread* t, - object, - uintptr_t* arguments) -{ - GcJclass* this_ = cast(t, reinterpret_cast(arguments[0])); - GcJclass* that = cast(t, reinterpret_cast(arguments[1])); - - if (LIKELY(that)) { - return isAssignableFrom(t, this_->vmClass(), that->vmClass()); - } else { - throwNew(t, GcNullPointerException::Type); - } -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_isInstance(Thread* t, object, uintptr_t* arguments) -{ - GcJclass* this_ = cast(t, reinterpret_cast(arguments[0])); - object o = reinterpret_cast(arguments[1]); - - if (o) { - return instanceOf(t, this_->vmClass(), o); - } else { - return 0; - } -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getDeclaredMethods(Thread* t, + Avian_java_lang_reflect_Constructor_make(Thread* t, object, uintptr_t* arguments) { - GcJclass* c = cast(t, reinterpret_cast(arguments[0])); - PROTECT(t, c); - - bool publicOnly = arguments[1]; - - GcMethod* get - = resolveMethod(t, - roots(t)->bootLoader(), - "avian/Classes", - "getMethods", - "(Lavian/VMClass;Z)[Ljava/lang/reflect/Method;"); + return reinterpret_cast( + make(t, cast(t, reinterpret_cast(arguments[0])))); +} +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_ref_Reference_get(Thread* t, object, uintptr_t* arguments) +{ return reinterpret_cast( - t->m->processor->invoke(t, get, 0, c->vmClass(), publicOnly)); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_Class_getDeclaredFields(Thread* t, - object, - uintptr_t* arguments) -{ - GcJclass* c = cast(t, reinterpret_cast(arguments[0])); - PROTECT(t, c); - - bool publicOnly = arguments[1]; - - GcMethod* get = resolveMethod(t, - roots(t)->bootLoader(), - "avian/Classes", - "getFields", - "(Lavian/VMClass;Z)[Ljava/lang/reflect/Field;"); - - return reinterpret_cast( - t->m->processor->invoke(t, get, 0, c->vmClass(), publicOnly)); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Method_invokeNative(Thread* t, - object, - uintptr_t* arguments) -{ - object instance = reinterpret_cast(arguments[1]); - object args = reinterpret_cast(arguments[2]); - GcMethod* method = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[3])) - ->vmClass() - ->methodTable())->body()[arguments[6]]); - - return reinterpret_cast(invoke(t, method, instance, args)); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Method_getMethodModifiers(Thread* t, - object, - uintptr_t* arguments) -{ - return cast( - t, - cast( - t, - cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->methodTable())->body()[arguments[1]])->flags(); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Method_isAnnotationPresent(Thread* t, - object, - uintptr_t* arguments) -{ - GcMethod* method = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->methodTable())->body()[arguments[1]]); - - GcMethodAddendum* addendum = method->addendum(); - if (addendum) { - object table = addendum->annotationTable(); - if (table) { - for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { - if (objectArrayBody(t, objectArrayBody(t, table, i), 1) - == reinterpret_cast(arguments[2])) { - return true; - } - } - } - } - - return false; -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Method_getAnnotation(Thread* t, - object, - uintptr_t* arguments) -{ - GcMethod* method = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->methodTable())->body()[arguments[1]]); - - GcMethodAddendum* addendum = method->addendum(); - if (addendum) { - object table = addendum->annotationTable(); - if (table) { - for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { - if (objectArrayBody(t, objectArrayBody(t, table, i), 1) - == reinterpret_cast(arguments[2])) { - PROTECT(t, method); - PROTECT(t, table); - - GcMethod* get - = resolveMethod(t, - roots(t)->bootLoader(), - "avian/Classes", - "getAnnotation", - "(Ljava/lang/ClassLoader;[Ljava/lang/Object;)" - "Ljava/lang/annotation/Annotation;"); - - return reinterpret_cast( - t->m->processor->invoke(t, - get, - 0, - method->class_()->loader(), - objectArrayBody(t, table, i))); - } - } - } - } - - return false; -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Method_getDeclaredAnnotations(Thread* t, - object, - uintptr_t* arguments) -{ - GcMethod* method = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->methodTable())->body()[arguments[1]]); - - GcMethodAddendum* addendum = method->addendum(); - if (addendum) { - object table = addendum->annotationTable(); - if (table) { - PROTECT(t, method); - PROTECT(t, table); - - object array = makeObjectArray( - t, - resolveClass( - t, roots(t)->bootLoader(), "java/lang/annotation/Annotation"), - objectArrayLength(t, table)); - PROTECT(t, array); - - GcMethod* get - = resolveMethod(t, - roots(t)->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, - method->class_()->loader(), - objectArrayBody(t, table, i)); - - setField(t, array, ArrayBody + (i * BytesPerWord), a); - } - - return reinterpret_cast(array); - } - } - - return reinterpret_cast(makeObjectArray( - t, - resolveClass( - t, roots(t)->bootLoader(), "java/lang/annotation/Annotation"), - 0)); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Field_getDeclaredAnnotations(Thread* t, - object, - uintptr_t* arguments) -{ - GcField* field = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->fieldTable())->body()[arguments[1]]); - - GcFieldAddendum* addendum = field->addendum(); - if (addendum) { - object table = addendum->annotationTable(); - if (table) { - PROTECT(t, field); - PROTECT(t, table); - - object array = makeObjectArray( - t, - resolveClass( - t, roots(t)->bootLoader(), "java/lang/annotation/Annotation"), - objectArrayLength(t, table)); - PROTECT(t, array); - - GcMethod* get - = resolveMethod(t, - roots(t)->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, - cast(t, reinterpret_cast(arguments[0]))->loader(), - objectArrayBody(t, table, i)); - - setField(t, array, ArrayBody + (i * BytesPerWord), a); - } - - return reinterpret_cast(array); - } - } - - return reinterpret_cast(makeObjectArray( - t, - resolveClass( - t, roots(t)->bootLoader(), "java/lang/annotation/Annotation"), - 0)); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Method_getDefaultValue(Thread* t, - object, - uintptr_t* arguments) -{ - GcMethod* method = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[1])) - ->vmClass() - ->methodTable())->body()[arguments[2]]); - - GcMethodAddendum* addendum = method->addendum(); - if (addendum) { - GcMethod* get - = resolveMethod(t, - roots(t)->bootLoader(), - "avian/Classes", - "getAnnotationDefaultValue", - "(Ljava/lang/ClassLoader;Lavian/MethodAddendum;)" - "Ljava/lang/Object;"); - - return reinterpret_cast(t->m->processor->invoke( - t, get, 0, method->class_()->loader(), addendum)); - } - - return 0; -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Constructor_constructNative(Thread* t, - object, - uintptr_t* arguments) -{ - object args = reinterpret_cast(arguments[1]); - PROTECT(t, args); - - GcClass* c - = cast(t, reinterpret_cast(arguments[2]))->vmClass(); - PROTECT(t, c); - - initClass(t, c); - - GcMethod* method = cast( - t, cast(t, c->methodTable())->body()[arguments[4]]); - PROTECT(t, method); - - object instance = makeNew(t, c); - PROTECT(t, instance); - - t->m->processor->invokeArray(t, method, instance, args); - - return reinterpret_cast(instance); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Field_getField(Thread* t, - object, - uintptr_t* arguments) -{ - GcField* field = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[2])) - ->vmClass() - ->fieldTable())->body()[arguments[4]]); - - PROTECT(t, field); - - object instance = reinterpret_cast(arguments[1]); - PROTECT(t, instance); - - return reinterpret_cast(local::getField(t, field, instance)); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Field_getIField(Thread* t, - object, - uintptr_t* arguments) -{ - GcField* field = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[2])) - ->vmClass() - ->fieldTable())->body()[arguments[4]]); - - PROTECT(t, field); - - object instance = reinterpret_cast(arguments[1]); - PROTECT(t, instance); - - return cast(t, local::getField(t, field, instance))->value(); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Field_getJField(Thread* t, - object, - uintptr_t* arguments) -{ - GcField* field = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[2])) - ->vmClass() - ->fieldTable())->body()[arguments[4]]); - - PROTECT(t, field); - - object instance = reinterpret_cast(arguments[1]); - PROTECT(t, instance); - - return cast(t, local::getField(t, field, instance))->value(); -} - -extern "C" AVIAN_EXPORT void JNICALL - Avian_java_lang_reflect_Field_setField(Thread* t, - object, - uintptr_t* arguments) -{ - GcField* field = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[2])) - ->vmClass() - ->fieldTable())->body()[arguments[4]]); - - PROTECT(t, field); - - object instance = reinterpret_cast(arguments[1]); - PROTECT(t, instance); - - object value = reinterpret_cast(arguments[6]); - PROTECT(t, value); - - local::setField(t, field, instance, value); -} - -extern "C" AVIAN_EXPORT void JNICALL - Avian_java_lang_reflect_Field_setIField(Thread* t, - object, - uintptr_t* arguments) -{ - GcField* field = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[2])) - ->vmClass() - ->fieldTable())->body()[arguments[4]]); - - object instance = reinterpret_cast(arguments[1]); - PROTECT(t, instance); - - object value = reinterpret_cast(makeInt(t, arguments[7])); - - local::setField(t, field, instance, value); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Field_getFieldModifiers(Thread* t, - object, - uintptr_t* arguments) -{ - return cast( - t, - cast( - t, - cast(t, reinterpret_cast(arguments[1])) - ->vmClass() - ->fieldTable())->body()[arguments[2]])->flags(); -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Field_getAnnotation(Thread* t, - object, - uintptr_t* arguments) -{ - GcField* field = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->fieldTable())->body()[arguments[1]]); - - GcFieldAddendum* addendum = field->addendum(); - if (addendum) { - object table = addendum->annotationTable(); - if (table) { - for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { - if (objectArrayBody(t, objectArrayBody(t, table, i), 1) - == reinterpret_cast(arguments[2])) { - PROTECT(t, field); - PROTECT(t, table); - - GcMethod* get - = resolveMethod(t, - roots(t)->bootLoader(), - "avian/Classes", - "getAnnotation", - "(Ljava/lang/ClassLoader;[Ljava/lang/Object;)" - "Ljava/lang/annotation/Annotation;"); - - return reinterpret_cast( - t->m->processor->invoke(t, - get, - 0, - field->class_()->loader(), - objectArrayBody(t, table, i))); - } - } - } - } - - return false; -} - -extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_java_lang_reflect_Field_getSignatureAnnotation(Thread* t, - object, - uintptr_t* arguments) -{ - GcField* field = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[1])) - ->vmClass() - ->fieldTable())->body()[arguments[2]]); - - GcFieldAddendum* addendum = field->addendum(); - if (addendum) { - GcByteArray* signature = cast(t, addendum->signature()); - if (signature) { - object array = makeObjectArray(t, 1); - PROTECT(t, array); - - GcString* string = t->m->classpath->makeString( - t, signature, 0, signature->length() - 1); - - setField(t, array, ArrayBody, string); - - return reinterpret_cast(array); - } - } - - return reinterpret_cast(makeObjectArray(t, 0)); + cast(t, reinterpret_cast(arguments[0]))->target()); } extern "C" AVIAN_EXPORT int64_t JNICALL @@ -2376,21 +1387,34 @@ extern "C" AVIAN_EXPORT int64_t JNICALL } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_avian_Classes_makeMethod(Thread* t, object, uintptr_t* arguments) + Avian_avian_Classes_getVMClass(Thread* t, object, uintptr_t* arguments) { - return reinterpret_cast(local::makeMethodOrConstructor( - t, - cast(t, reinterpret_cast(arguments[0])), - arguments[1])); + return reinterpret_cast( + objectClass(t, reinterpret_cast(arguments[0]))); } extern "C" AVIAN_EXPORT int64_t JNICALL - Avian_avian_Classes_makeField(Thread* t, object, uintptr_t* arguments) + Avian_avian_Classes_makeMethod(Thread* t, object, uintptr_t* arguments) { - return reinterpret_cast(local::makeField( - t, - cast(t, reinterpret_cast(arguments[0])), - arguments[1])); + return reinterpret_cast( + makeMethod(t, + cast(t, reinterpret_cast(arguments[0])), + arguments[1])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_isAssignableFrom(Thread* t, + object, + uintptr_t* arguments) +{ + GcClass* this_ = cast(t, reinterpret_cast(arguments[0])); + GcClass* that = cast(t, reinterpret_cast(arguments[1])); + + if (LIKELY(that)) { + return vm::isAssignableFrom(t, this_, that); + } else { + throwNew(t, GcNullPointerException::Type); + } } extern "C" AVIAN_EXPORT int64_t JNICALL diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 85821a7025..4f8740cc90 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -343,30 +343,8 @@ extern "C" AVIAN_EXPORT int64_t JNICALL object, uintptr_t* arguments) { - object instance = reinterpret_cast(arguments[0]); - int code = arguments[1]; - int offset = arguments[2]; - - switch (code) { - case ByteField: - return fieldAtOffset(instance, offset); - case BooleanField: - return fieldAtOffset(instance, offset); - case CharField: - return fieldAtOffset(instance, offset); - case ShortField: - return fieldAtOffset(instance, offset); - case IntField: - return fieldAtOffset(instance, offset); - case LongField: - return fieldAtOffset(instance, offset); - case FloatField: - return fieldAtOffset(instance, offset); - case DoubleField: - return fieldAtOffset(instance, offset); - default: - abort(t); - } + return getPrimitive( + t, reinterpret_cast(arguments[0]), arguments[1], arguments[2]); } extern "C" AVIAN_EXPORT int64_t JNICALL @@ -374,10 +352,8 @@ extern "C" AVIAN_EXPORT int64_t JNICALL object, uintptr_t* arguments) { - object instance = reinterpret_cast(arguments[0]); - int offset = arguments[1]; - - return reinterpret_cast(fieldAtOffset(instance, offset)); + return reinterpret_cast(fieldAtOffset( + reinterpret_cast(arguments[0]), arguments[1])); } extern "C" AVIAN_EXPORT void JNICALL @@ -385,40 +361,14 @@ extern "C" AVIAN_EXPORT void JNICALL object, uintptr_t* arguments) { - object instance = reinterpret_cast(arguments[0]); - int code = arguments[1]; - int offset = arguments[2]; int64_t value; memcpy(&value, arguments + 3, 8); - switch (code) { - case ByteField: - fieldAtOffset(instance, offset) = static_cast(value); - break; - case BooleanField: - fieldAtOffset(instance, offset) = static_cast(value); - break; - case CharField: - fieldAtOffset(instance, offset) = static_cast(value); - break; - case ShortField: - fieldAtOffset(instance, offset) = static_cast(value); - break; - case IntField: - fieldAtOffset(instance, offset) = static_cast(value); - break; - case LongField: - fieldAtOffset(instance, offset) = static_cast(value); - break; - case FloatField: - fieldAtOffset(instance, offset) = static_cast(value); - break; - case DoubleField: - fieldAtOffset(instance, offset) = static_cast(value); - break; - default: - abort(t); - } + setPrimitive(t, + reinterpret_cast(arguments[0]), + arguments[1], + arguments[2], + value); } extern "C" AVIAN_EXPORT void JNICALL @@ -426,11 +376,10 @@ extern "C" AVIAN_EXPORT void JNICALL object, uintptr_t* arguments) { - object instance = reinterpret_cast(arguments[0]); - int offset = arguments[1]; - object value = reinterpret_cast(arguments[2]); - - setField(t, instance, offset, value); + setField(t, + reinterpret_cast(arguments[0]), + arguments[1], + reinterpret_cast(arguments[2])); } extern "C" AVIAN_EXPORT int64_t JNICALL @@ -438,9 +387,8 @@ extern "C" AVIAN_EXPORT int64_t JNICALL object, uintptr_t* arguments) { - GcClass* c = cast(t, reinterpret_cast(arguments[0])); - - return reinterpret_cast(make(t, c)); + return reinterpret_cast( + make(t, cast(t, reinterpret_cast(arguments[0])))); } extern "C" AVIAN_EXPORT int64_t JNICALL @@ -454,22 +402,10 @@ extern "C" AVIAN_EXPORT int64_t JNICALL object, uintptr_t* arguments) { - GcMethod* method = cast(t, reinterpret_cast(arguments[0])); - object instance = reinterpret_cast(arguments[1]); - object args = reinterpret_cast(arguments[2]); - - THREAD_RESOURCE0(t, { - if (t->exception) { - GcThrowable* exception = t->exception; - t->exception = makeThrowable( - t, GcInvocationTargetException::Type, 0, 0, exception); - } - }); - - unsigned returnCode = method->returnCode(); - - return reinterpret_cast(translateInvokeResult( - t, returnCode, t->m->processor->invokeArray(t, method, instance, args))); + return invokeMethod(t, + cast(t, reinterpret_cast(arguments[0])), + reinterpret_cast(arguments[1]), + reinterpret_cast(arguments[2])); } extern "C" AVIAN_EXPORT int64_t JNICALL @@ -809,38 +745,8 @@ extern "C" AVIAN_EXPORT int64_t JNICALL extern "C" AVIAN_EXPORT int64_t JNICALL Avian_avian_Classes_makeMethod(Thread* t, object, uintptr_t* arguments) { - GcMethod* method = cast( - t, - cast(t, - cast(t, reinterpret_cast(arguments[0])) - ->vmClass() - ->methodTable())->body()[arguments[1]]); - PROTECT(t, method); - - GcClass* c - = resolveClass(t, roots(t)->bootLoader(), "java/lang/reflect/Method"); - PROTECT(t, c); - - object instance = makeNew(t, c); - PROTECT(t, instance); - - GcMethod* constructor = resolveMethod(t, c, "", "(Lavian/VMMethod;)V"); - - t->m->processor->invoke(t, constructor, instance, method); - - if (method->name()->body()[0] == '<') { - object oldInstance = instance; - - c = resolveClass( - t, roots(t)->bootLoader(), "java/lang/reflect/Constructor"); - - object instance = makeNew(t, c); - - GcMethod* constructor - = resolveMethod(t, c, "", "(Ljava/lang/Method;)V"); - - t->m->processor->invoke(t, constructor, instance, oldInstance); - } - - return reinterpret_cast(instance); + return reinterpret_cast( + makeMethod(t, + cast(t, reinterpret_cast(arguments[0])), + arguments[1])); } diff --git a/src/types.def b/src/types.def index 6623ac44ea..a140503eba 100644 --- a/src/types.def +++ b/src/types.def @@ -179,6 +179,7 @@ (require uint8_t interrupted) (require uint8_t unparked) (alias peer uint64_t eetop) + (alias peer uint64_t nativePeer) (require uint64_t peer)) (type threadGroup java/lang/ThreadGroup) diff --git a/test/Misc.java b/test/Misc.java index ef78345a56..ec3bd0bd25 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -316,21 +316,21 @@ public class Misc { expect(staticRan); expect(System.getProperty("java.class.path").equals - (System.getProperties().get("java.class.path"))); + (System.getProperties().getProperty("java.class.path"))); expect(System.getProperty("path.separator").equals - (System.getProperties().get("path.separator"))); + (System.getProperties().getProperty("path.separator"))); expect(System.getProperty("user.dir").equals - (System.getProperties().get("user.dir"))); + (System.getProperties().getProperty("user.dir"))); expect(System.getProperty("java.io.tmpdir").equals - (System.getProperties().get("java.io.tmpdir"))); + (System.getProperties().getProperty("java.io.tmpdir"))); System.setProperty("buzzy.buzzy.bim.bam", "dippy dopey flim flam"); expect(System.getProperty("buzzy.buzzy.bim.bam").equals - (System.getProperties().get("buzzy.buzzy.bim.bam"))); + (System.getProperties().getProperty("buzzy.buzzy.bim.bam"))); expect(System.getProperty("buzzy.buzzy.bim.bam").equals ("dippy dopey flim flam")); @@ -338,7 +338,7 @@ public class Misc { System.getProperties().put("buzzy.buzzy.bim.bam", "yippy yappy yin yang"); expect(System.getProperty("buzzy.buzzy.bim.bam").equals - (System.getProperties().get("buzzy.buzzy.bim.bam"))); + (System.getProperties().getProperty("buzzy.buzzy.bim.bam"))); expect(System.getProperty("buzzy.buzzy.bim.bam").equals ("yippy yappy yin yang")); diff --git a/test/ci.sh b/test/ci.sh index b48f0355c1..7040c7b921 100755 --- a/test/ci.sh +++ b/test/ci.sh @@ -49,7 +49,7 @@ run make ${flags} process=interpret ${make_target} run make ${flags} mode=debug bootimage=true ${make_target} && \ run make ${flags} bootimage=true ${make_target} -! has_flag openjdk && \ +(! has_flag openjdk && ! has_flag android) && \ run make ${flags} openjdk=$JAVA_HOME ${make_target} run make ${flags} tails=true continuations=true heapdump=true ${make_target}