From d414fd4c7bf0eff4f6508c2f74078d12caed8732 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 20 Feb 2013 10:22:40 -0700 Subject: [PATCH] more progress on Android class library port Hello.java works. Yay. --- classpath/avian/Android.java | 30 ++++++ classpath/sun/misc/Unsafe.java | 7 ++ makefile | 14 ++- src/builtin.cpp | 13 +++ src/classpath-android.cpp | 170 ++++++++++++++++++++++++++++++++- src/classpath-common.h | 24 +++++ src/classpath-openjdk.cpp | 39 +------- 7 files changed, 255 insertions(+), 42 deletions(-) create mode 100644 classpath/avian/Android.java diff --git a/classpath/avian/Android.java b/classpath/avian/Android.java new file mode 100644 index 0000000000..720f82341c --- /dev/null +++ b/classpath/avian/Android.java @@ -0,0 +1,30 @@ +/* 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); + } +} diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java index 4f395718c9..5fea56c54a 100644 --- a/classpath/sun/misc/Unsafe.java +++ b/classpath/sun/misc/Unsafe.java @@ -1,5 +1,7 @@ package sun.misc; +import java.lang.reflect.Field; + public final class Unsafe { private void Unsafe() { } @@ -50,10 +52,15 @@ public final class Unsafe { public native int arrayBaseOffset(Class arrayClass); + public native long objectFieldOffset(Field field); + public native void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long count); + public native boolean compareAndSwapInt(Object o, long offset, int old, + int new_); + public void copyMemory(long src, long dst, long count) { copyMemory(null, src, null, dst, count); } diff --git a/makefile b/makefile index a50fc6cb53..a023f4b6f2 100755 --- a/makefile +++ b/makefile @@ -1229,7 +1229,8 @@ ifneq ($(classpath),avian) $(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)/sun/misc/Unsafe.java \ + $(classpath-src)/avian/Android.java endif else classpath-sources := $(shell find $(classpath-src) -name '*.java') @@ -1406,7 +1407,13 @@ $(classpath-dep): $(classpath-sources) $(classpath-jar-dep) $(classpath-classes)) @touch $(@) -$(build)/%.o: $(luni-native)/%.cpp $(build)/android.dep +$(build)/android-src/%.cpp: $(luni-native)/%.cpp + if [ "$(luni-native)/libcore_icu_ICU.cpp" = "$(<)" ]; then \ + sed 's/register_libcore_icu_ICU/hide_register_libcore_icu_ICU/' \ + < $(<) > $(@).tmp && cat $(@).tmp $(src)/android/icu.cpp > $(@); else \ + cp $(<) $(@); fi + +$(build)/%.o: $(build)/android-src/%.cpp $(build)/android.dep @echo "compiling $(@)" @mkdir -p $(dir $(@)) $(cxx) $(android-cflags) -c $$($(windows-path) $(<)) $(call output,$(@)) @@ -1653,7 +1660,8 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) -unittest-executable-objects = $(unittest-objects) $(vm-objects) +unittest-executable-objects = $(unittest-objects) $(vm-objects) \ + $(classpath-objects) ifeq ($(process),interpret) unittest-executable-objects += $(all-codegen-target-objects) diff --git a/src/builtin.cpp b/src/builtin.cpp index eaa66ed101..b9cfde971d 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -565,3 +565,16 @@ Avian_java_nio_FixedArrayByteBuffer_allocateFixed return reinterpret_cast(array); } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_compareAndSwapInt +(Thread*, object, uintptr_t* arguments) +{ + object target = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + uint32_t expect = arguments[4]; + uint32_t update = arguments[5]; + + return atomicCompareAndSwap32 + (&fieldAtOffset(target, offset), expect, update); +} diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index d50be47057..ef26c514ca 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -291,7 +291,7 @@ jniCreateFileDescriptor(JNIEnv* e, int fd) return descriptor; } -extern "C" struct _JNIEnv; +struct _JNIEnv; int register_org_apache_harmony_dalvik_NativeTestTarget(_JNIEnv*) @@ -299,3 +299,171 @@ register_org_apache_harmony_dalvik_NativeTestTarget(_JNIEnv*) // ignore return 0; } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_isEmpty +(Thread* t, object, uintptr_t* arguments) +{ + return stringLength(t, reinterpret_cast(arguments[0])) == 0; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_length +(Thread* t, object, uintptr_t* arguments) +{ + return stringLength(t, reinterpret_cast(arguments[0])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_charAt +(Thread* t, object, uintptr_t* arguments) +{ + return stringCharAt(t, reinterpret_cast(arguments[0]), arguments[1]); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_equals +(Thread* t, object, uintptr_t* arguments) +{ + return stringEqual(t, reinterpret_cast(arguments[0]), + reinterpret_cast(arguments[1])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_fastIndexOf +(Thread* t, object, uintptr_t* arguments) +{ + object s = reinterpret_cast(arguments[0]); + unsigned c = arguments[1]; + unsigned start = arguments[2]; + + for (unsigned i = start; i < stringLength(t, s); ++i) { + if (stringCharAt(t, s, i) == c) { + return i; + } + } + + return -1; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getComponentType +(Thread* t, object, uintptr_t* arguments) +{ + object c = reinterpret_cast(arguments[0]); + + if (classArrayDimensions(t, jclassVmClass(t, c))) { + uint8_t n = byteArrayBody(t, className(t, jclassVmClass(t, c)), 1); + if (n != 'L' and n != '[') { + return reinterpret_cast + (getJClass(t, primitiveClass(t, n))); + } else { + return reinterpret_cast + (getJClass(t, classStaticTable(t, jclassVmClass(t, c)))); + } + } else { + return 0; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getDeclaredField +(Thread* t, object, uintptr_t* arguments) +{ + object c = reinterpret_cast(arguments[0]); + PROTECT(t, c); + + object name = reinterpret_cast(arguments[1]); + PROTECT(t, name); + + object method = resolveMethod + (t, root(t, Machine::BootLoader), "avian/Android", "findField", + "(Lavian/VMClass;Ljava/lang/String;)Lavian/VMField;"); + + object field = t->m->processor->invoke + (t, method, 0, jclassVmClass(t, c), name); + + if (field) { + PROTECT(t, field); + + object type = resolveClassBySpec + (t, classLoader(t, fieldClass(t, field)), + reinterpret_cast + (&byteArrayBody(t, fieldSpec(t, field), 0)), + byteArrayLength(t, fieldSpec(t, field)) - 1); + PROTECT(t, type); + + unsigned index = 0xFFFFFFFF; + object table = classFieldTable(t, fieldClass(t, field)); + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + if (field == arrayBody(t, table, i)) { + index = i; + break; + } + } + + return reinterpret_cast + (makeJfield(t, 0, c, type, 0, 0, name, index)); + } else { + return 0; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_bootClassPath +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(root(t, Machine::BootLoader)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_classPath +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(root(t, Machine::AppLoader)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_vmVersion +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(makeString(t, "%s", AVIAN_VERSION)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_properties +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast + (makeObjectArray(t, type(t, Machine::StringType), 0)); +} + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_System_arraycopy +(Thread* t, object, uintptr_t* arguments) +{ + arrayCopy(t, reinterpret_cast(arguments[0]), + arguments[1], + reinterpret_cast(arguments[2]), + arguments[3], + arguments[4]); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_objectFieldOffset +(Thread* t, object, uintptr_t* arguments) +{ + object jfield = reinterpret_cast(arguments[1]); + return fieldOffset + (t, arrayBody + (t, classFieldTable + (t, jclassVmClass(t, jfieldDeclaringClass(t, jfield))), + jfieldSlot(t, jfield))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMThread_currentThread +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(t->javaThread); +} diff --git a/src/classpath-common.h b/src/classpath-common.h index 11c22b913f..ca6649a01e 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -331,6 +331,30 @@ translateInvokeResult(Thread* t, unsigned returnCode, object o) } } +object +resolveClassBySpec(Thread* t, object loader, const char* spec, + unsigned specLength) +{ + switch (*spec) { + case 'L': { + THREAD_RUNTIME_ARRAY(t, char, s, specLength - 1); + memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2); + RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0; + return resolveClass(t, loader, s); + } + + case '[': { + THREAD_RUNTIME_ARRAY(t, char, s, specLength + 1); + memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength); + RUNTIME_ARRAY_BODY(s)[specLength] = 0; + return resolveClass(t, loader, s); + } + + default: + return primitiveClass(t, *spec); + } +} + } // namespace vm #endif//CLASSPATH_COMMON_H diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 074f3cf5f3..df37efceaf 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2185,30 +2185,6 @@ countConstructors(Thread* t, object c, bool publicOnly) return count; } -object -resolveClassBySpec(Thread* t, object loader, const char* spec, - unsigned specLength) -{ - switch (*spec) { - case 'L': { - THREAD_RUNTIME_ARRAY(t, char, s, specLength - 1); - memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2); - RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0; - return resolveClass(t, loader, s); - } - - case '[': { - THREAD_RUNTIME_ARRAY(t, char, s, specLength + 1); - memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength); - RUNTIME_ARRAY_BODY(s)[specLength] = 0; - return resolveClass(t, loader, s); - } - - default: - return primitiveClass(t, *spec); - } -} - object resolveJType(Thread* t, object loader, const char* spec, unsigned specLength) { @@ -2498,7 +2474,7 @@ makeJfield(Thread* t, object vmField, int index) (t, fieldName(t, vmField)) - 1)); PROTECT(t, name); - object type = local::resolveClassBySpec + object type = resolveClassBySpec (t, classLoader(t, fieldClass(t, vmField)), reinterpret_cast (&byteArrayBody(t, fieldSpec(t, vmField), 0)), @@ -3055,19 +3031,6 @@ Avian_sun_misc_Unsafe_putOrderedObject Avian_sun_misc_Unsafe_putObjectVolatile(t, method, arguments); } -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_compareAndSwapInt -(Thread*, object, uintptr_t* arguments) -{ - object target = reinterpret_cast(arguments[1]); - int64_t offset; memcpy(&offset, arguments + 2, 8); - uint32_t expect = arguments[4]; - uint32_t update = arguments[5]; - - return atomicCompareAndSwap32 - (&fieldAtOffset(target, offset), expect, update); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_compareAndSwapObject (Thread* t, object, uintptr_t* arguments)