diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 23fdf52196..10485c25cd 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -596,7 +596,9 @@ public final class String } public static String valueOf(int v) { - return Integer.toString(v); + // use Integer.toString(int, int), because GNU Classpath's + // Integer.toString(int) just calls String.valueOf(int): + return Integer.toString(v, 10); } public static String valueOf(long v) { @@ -615,6 +617,10 @@ public final class String return new String(data, offset, length); } + public static String valueOf(char[] data) { + return valueOf(data, 0, data.length); + } + public int lastIndexOf(int ch, int lastIndex) { for (int i = lastIndex ; i >= 0; --i) { if (charAt(i) == ch) { diff --git a/makefile b/makefile index 2d00f61417..d0041344e9 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -#MAKEFLAGS = -s +MAKEFLAGS = -s name = avian version = 0.2 @@ -326,12 +326,13 @@ gnu-blacklist = \ java/lang/reflect/Proxy.class gnu-overrides = \ + avian/*.class \ java/lang/Class.class \ java/lang/Enum.class \ java/lang/InheritableThreadLocal.class \ java/lang/Object.class \ java/lang/StackTraceElement.class \ - java/lang/String.class \ + java/lang/String*.class \ java/lang/StringBuffer.class \ java/lang/StringBuilder.class \ java/lang/Thread.class \ @@ -432,7 +433,7 @@ ifdef gnu (wd=$$(pwd); \ cd $(classpath-build); \ $(jar) c0f "$$($(native-path) "$${wd}/$(build)/overrides.jar")" \ - $(gnu-overrides) $$(find avian -name '*.class'); \ + $(gnu-overrides); \ rm -r *; \ $(jar) xf $(gnu)/share/classpath/glibj.zip; \ rm $(gnu-blacklist); \ diff --git a/src/gnu.cpp b/src/gnu.cpp index 3e443a275f..36d666de23 100644 --- a/src/gnu.cpp +++ b/src/gnu.cpp @@ -60,21 +60,30 @@ Avian_gnu_classpath_VMSystemProperties_preInit #ifdef WIN32 setProperty(t, method, properties, "line.separator", "\r\n"); setProperty(t, method, properties, "file.separator", "\\"); + setProperty(t, method, properties, "path.separator", ";"); setProperty(t, method, properties, "os.name", "Windows"); TCHAR buffer[MAX_PATH]; GetTempPath(MAX_PATH, buffer); setProperty(t, method, properties, "java.io.tmpdir", buffer); - LPWSTR home = _wgetenv(L"USERPROFILE"); - setProperty(t, method, properties, "user.home", home, "%ls"); + setProperty(t, method, properties, "user.home", + _wgetenv(L"USERPROFILE"), "%ls"); + + setProperty(t, method, properties, "java.library.path", + _wgetenv(L"PATH"), "%ls"); #else setProperty(t, method, properties, "line.separator", "\n"); setProperty(t, method, properties, "file.separator", "/"); + setProperty(t, method, properties, "path.separator", ":"); # ifdef __APPLE__ setProperty(t, method, properties, "os.name", "Mac OS X"); + setProperty(t, method, properties, "java.library.path", + getenv("DYLD_LIBRARY_PATH")); # else setProperty(t, method, properties, "os.name", "Linux"); + setProperty(t, method, properties, "java.library.path", + getenv("LD_LIBRARY_PATH")); # endif setProperty(t, method, properties, "java.io.tmpdir", "/tmp"); setProperty(t, method, properties, "user.home", getenv("HOME")); @@ -136,3 +145,103 @@ Avian_gnu_classpath_VMStackWalker_getClassLoader return reinterpret_cast (classLoader(t, reinterpret_cast(arguments[0]))); } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMRuntime_mapLibraryName +(Thread* t, object, uintptr_t* arguments) +{ + object name = reinterpret_cast(arguments[0]); + PROTECT(t, name); + + const unsigned prefixLength = sizeof(SO_PREFIX) - 1; + const unsigned nameLength = stringLength(t, name); + const unsigned suffixLength = sizeof(SO_SUFFIX) - 1; + const unsigned total = prefixLength + nameLength + suffixLength; + + object s = makeByteArray(t, total + 1); + char* p = reinterpret_cast(&byteArrayBody(t, s, 0)); + + memcpy(p, SO_PREFIX, prefixLength); + stringChars(t, name, p + prefixLength); + memcpy(p + prefixLength + nameLength, SO_SUFFIX, suffixLength); + p[total] = 0; + + return reinterpret_cast(makeString(t, s, 0, total, 0)); +} + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_System_arraycopy +(Thread*, object, uintptr_t*); + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_VMSystem_arraycopy +(Thread* t, object, uintptr_t* arguments) +{ + Avian_java_lang_System_arraycopy(t, 0, arguments); +} + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_Runtime_load +(Thread* t, object, uintptr_t*); + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMRuntime_nativeLoad +(Thread* t, object, uintptr_t* arguments) +{ + uintptr_t args[] = { arguments[0], 0 }; + + Avian_java_lang_Runtime_load(t, 0, args); + + if (t->exception) { + t->exception = 0; + return 0; + } else { + return 1; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_primitiveClass +(Thread* t, object, uintptr_t*); + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMClassLoader_getPrimitiveClass +(Thread* t, object, uintptr_t* arguments) +{ + return Avian_java_lang_Class_primitiveClass(t, 0, arguments); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_System_identityHashCode +(Thread*, object, uintptr_t*); + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMSystem_identityHashCode +(Thread* t, object, uintptr_t* arguments) +{ + return Avian_java_lang_System_identityHashCode(t, 0, arguments); +} + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_Runtime_gc +(Thread*, object, uintptr_t*); + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_VMRuntime_gc +(Thread* t, object, uintptr_t*) +{ + Avian_java_lang_Runtime_gc(t, 0, 0); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_SystemClassLoader_findClass +(Thread*, object, uintptr_t*); + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMClassLoader_loadClass +(Thread* t, object, uintptr_t* arguments) +{ + uintptr_t args[] = { 0, arguments[0] }; + + return Avian_avian_SystemClassLoader_findClass(t, 0, args); +} diff --git a/src/jnienv.cpp b/src/jnienv.cpp index d7e5ea0fdc..199145ba6c 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -256,6 +256,24 @@ ExceptionCheck(Thread* t) return t->exception != 0; } +jobject JNICALL +NewDirectByteBuffer(Thread*, void*, jlong) +{ + return 0; +} + +void* JNICALL +GetDirectBufferAddress(Thread*, jobject) +{ + return 0; +} + +jlong JNICALL +GetDirectBufferCapacity(JNIEnv*, jobject) +{ + return -1; +} + jclass JNICALL GetObjectClass(Thread* t, jobject o) { @@ -1905,6 +1923,9 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) envTable->FindClass = ::FindClass; envTable->ThrowNew = ::ThrowNew; envTable->ExceptionCheck = ::ExceptionCheck; + envTable->NewDirectByteBuffer = ::NewDirectByteBuffer; + envTable->GetDirectBufferAddress = ::GetDirectBufferAddress; + envTable->GetDirectBufferCapacity = ::GetDirectBufferCapacity; envTable->DeleteLocalRef = ::DeleteLocalRef; envTable->GetObjectClass = ::GetObjectClass; envTable->IsInstanceOf = ::IsInstanceOf; diff --git a/src/machine.cpp b/src/machine.cpp index 853cd29519..760a54969c 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -496,6 +496,68 @@ makeByteArray(Thread* t, const char* format, va_list a) return s; } +object +parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount, + unsigned sourceIndex, unsigned lastByteRead) +{ + PROTECT(t, bytesSoFar); + + unsigned length = byteArrayLength(t, bytesSoFar) - 1; + object value = makeCharArray(t, length + 1); + + unsigned vi = 0; + for (; vi < byteCount; ++vi) { + charArrayBody(t, value, vi) = byteArrayBody(t, bytesSoFar, vi); + } + + unsigned a = lastByteRead; + unsigned si = sourceIndex; + while (true) { + if (a & 0x80) { + // todo: handle non-ASCII characters properly + if (a & 0x20) { + // 3 bytes + si += 2; + assert(t, si < length); + unsigned b = s.read1(); + unsigned c = s.read1(); + charArrayBody(t, value, vi++) + = ((a & 0xf) << 12) | ((b & 0x3f) << 6) | (c & 0x3f); + } else { + // 2 bytes + ++ si; + assert(t, si < length); + unsigned b = s.read1(); + + if (a == 0xC0 and b == 0x80) { + charArrayBody(t, value, vi++) = 0; + } else { + charArrayBody(t, value, vi++) = ((a & 0x1f) << 6) | (b & 0x3f); + } + } + } else { + charArrayBody(t, value, vi++) = a; + } + + if (++si < length) { + a = s.read1(); + } else { + break; + } + } + + if (vi < length) { + PROTECT(t, value); + + object v = makeCharArray(t, vi + 1); + memcpy(&charArrayBody(t, v, 0), &charArrayBody(t, value, 0), vi * 2); + value = v; + } + + charArrayBody(t, value, vi) = 0; + return value; +} + object parseUtf8(Thread* t, Stream& s, unsigned length) { @@ -507,21 +569,17 @@ parseUtf8(Thread* t, Stream& s, unsigned length) // todo: handle non-ASCII characters properly if (a & 0x20) { // 3 bytes - si += 2; - assert(t, si < length); - /*unsigned b = */s.read1(); - /*unsigned c = */s.read1(); - byteArrayBody(t, value, vi++) = '_'; + return parseUtf8NonAscii(t, s, value, vi, si, a); } else { // 2 bytes - ++ si; - assert(t, si < length); unsigned b = s.read1(); if (a == 0xC0 and b == 0x80) { + ++ si; + assert(t, si < length); byteArrayBody(t, value, vi++) = 0; } else { - byteArrayBody(t, value, vi++) = '_'; + return parseUtf8NonAscii(t, s, value, vi, si, a); } } } else { @@ -583,7 +641,8 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) parsePoolEntry(t, s, index, pool, si); object value = singletonObject(t, pool, si); - value = makeString(t, value, 0, byteArrayLength(t, value) - 1, 0); + value = makeString + (t, value, 0, cast(value, BytesPerWord) - 1, 0); value = intern(t, value); set(t, pool, SingletonBody + (i * BytesPerWord), value); } @@ -1513,7 +1572,7 @@ boot(Thread* t) m->unsafe = true; - m->loader = allocate(t, sizeof(void*) * 3, true); + m->loader = allocate(t, FixedSizeOfSystemClassLoader, true); m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true); arrayLength(t, m->types) = TypeCount; @@ -2434,6 +2493,8 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) classLoader(t, class_), vtableLength); + PROTECT(t, real); + t->m->processor->initVtable(t, real); updateClassTables(t, real, class_); @@ -2977,7 +3038,7 @@ runJavaThread(Thread* t) (t, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V"); if (t->exception == 0) { - t->m->processor->invoke (t, method, t->javaThread); + t->m->processor->invoke(t, method, 0, t->javaThread); } }