diff --git a/makefile b/makefile index a7e4389511..2578ac6107 100755 --- a/makefile +++ b/makefile @@ -120,16 +120,24 @@ ifneq ($(openjdk),) openjdk-jar-dep = $(build)/openjdk-jar.dep classpath-jar-dep = $(openjdk-jar-dep) javahome = $(embed-prefix)/javahomeJar - javahome-files = lib/zi lib/currency.data lib/security/java.security \ + javahome-files = lib/currency.data lib/security/java.security \ lib/security/java.policy lib/security/cacerts + ifneq (,$(wildcard $(openjdk)/jre/lib/zi)) + javahome-files += lib/zi + endif + + ifneq (,$(wildcard $(openjdk)/jre/lib/tzdb.dat)) + javahome-files += lib/tzdb.dat + endif + local-policy = lib/security/local_policy.jar - ifeq ($(shell test -e "$(openjdk)/jre/$(local-policy)" && echo found),found) + ifneq (,$(wildcard $(openjdk)/jre/$(local-policy))) javahome-files += $(local-policy) endif export-policy = lib/security/US_export_policy.jar - ifeq ($(shell test -e "$(openjdk)/jre/$(export-policy)" && echo found),found) + ifneq (,$(wildcard $(openjdk)/jre/$(export-policy))) javahome-files += $(export-policy) endif diff --git a/openjdk-src.mk b/openjdk-src.mk index 0f59e03bcb..ea4acd9c03 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -19,10 +19,10 @@ openjdk-sources = \ $(openjdk-src)/share/native/java/lang/Float.c \ $(openjdk-src)/share/native/java/lang/Object.c \ $(openjdk-src)/share/native/java/lang/Package.c \ - $(openjdk-src)/share/native/java/lang/ref/Finalizer.c \ + $(wildcard $(openjdk-src)/share/native/java/lang/ref/Finalizer.c) \ $(openjdk-src)/share/native/java/lang/reflect/Array.c \ $(openjdk-src)/share/native/java/lang/reflect/Proxy.c \ - $(openjdk-src)/share/native/java/lang/ResourceBundle.c \ + $(wildcard $(openjdk-src)/share/native/java/lang/ResourceBundle.c) \ $(openjdk-src)/share/native/java/lang/Runtime.c \ $(openjdk-src)/share/native/java/lang/SecurityManager.c \ $(openjdk-src)/share/native/java/lang/Shutdown.c \ @@ -38,7 +38,7 @@ openjdk-sources = \ $(openjdk-src)/share/native/java/net/Inet6Address.c \ $(openjdk-src)/share/native/java/nio/Bits.c \ $(openjdk-src)/share/native/java/security/AccessController.c \ - $(openjdk-src)/share/native/java/sql/DriverManager.c \ + $(wildcard $(openjdk-src)/share/native/java/sql/DriverManager.c) \ $(openjdk-src)/share/native/java/util/concurrent/atomic/AtomicLong.c \ $(openjdk-src)/share/native/java/util/TimeZone.c \ $(openjdk-src)/share/native/java/util/zip/Adler32.c \ @@ -250,11 +250,12 @@ else $(openjdk-src)/solaris/native/java/io/FileDescriptor_md.c \ $(openjdk-src)/solaris/native/java/io/FileInputStream_md.c \ $(openjdk-src)/solaris/native/java/io/FileOutputStream_md.c \ - $(openjdk-src)/solaris/native/java/io/FileSystem_md.c \ + $(wildcard $(openjdk-src)/solaris/native/java/io/FileSystem_md.c) \ $(openjdk-src)/solaris/native/java/io/io_util_md.c \ $(openjdk-src)/solaris/native/java/io/RandomAccessFile_md.c \ $(openjdk-src)/solaris/native/java/io/UnixFileSystem_md.c \ $(openjdk-src)/solaris/native/java/lang/java_props_md.c \ + $(wildcard $(openjdk-src)/solaris/native/java/lang/childproc.c) \ $(openjdk-src)/solaris/native/java/lang/ProcessEnvironment_md.c \ $(openjdk-src)/solaris/native/java/lang/UNIXProcess_md.c \ $(openjdk-src)/solaris/native/java/net/net_util_md.c \ diff --git a/openjdk.ld b/openjdk.ld index fdad025d57..ac767806e5 100644 --- a/openjdk.ld +++ b/openjdk.ld @@ -74,6 +74,7 @@ SUNWprivate_1.1 { JVM_CurrentTimeMillis; JVM_DefineClass; JVM_DefineClassWithSource; + JVM_DefineClassWithSourceCond; JVM_DesiredAssertionStatus; JVM_DisableCompiler; JVM_DoPrivileged; @@ -127,12 +128,14 @@ SUNWprivate_1.1 { JVM_GetClassNameUTF; JVM_GetClassSignature; JVM_GetClassSigners; + JVM_GetClassTypeAnnotations; JVM_GetComponentType; JVM_GetDeclaredClasses; JVM_GetDeclaringClass; JVM_GetEnclosingMethodInfo; JVM_GetFieldAnnotations; JVM_GetFieldIxModifiers; + JVM_GetFieldTypeAnnotations; JVM_GetHostName; JVM_GetInheritedAccessControlContext; JVM_GetInterfaceVersion; @@ -185,6 +188,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; @@ -220,6 +224,7 @@ SUNWprivate_1.1 { JVM_SetArrayElement; JVM_SetClassSigners; JVM_SetLength; + JVM_SetNativeThreadName; JVM_SetPrimitiveArrayElement; JVM_SetProtectionDomain; JVM_SetSockOpt; diff --git a/src/avian/classpath-common.h b/src/avian/classpath-common.h index 6d95ca1406..de91a82564 100644 --- a/src/avian/classpath-common.h +++ b/src/avian/classpath-common.h @@ -239,8 +239,8 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName, runOnLoadIfFound(t, lib); } } else if (throw_) { - throwNew(t, Machine::UnsatisfiedLinkErrorType, "library not found: %s", - name); + throwNew(t, Machine::UnsatisfiedLinkErrorType, + "library not found in %s: %s", path, name); } return lib; diff --git a/src/avian/constants.h b/src/avian/constants.h index 2852afc18f..5fa836c875 100644 --- a/src/avian/constants.h +++ b/src/avian/constants.h @@ -233,15 +233,18 @@ enum TypeCode { enum Constant { CONSTANT_Class = 7, - CONSTANT_Fieldref = 9, - CONSTANT_Methodref = 10, - CONSTANT_InterfaceMethodref = 11, - CONSTANT_String = 8, - CONSTANT_Integer = 3, - CONSTANT_Float = 4, - CONSTANT_Long = 5, CONSTANT_Double = 6, + CONSTANT_Fieldref = 9, + CONSTANT_Float = 4, + CONSTANT_Integer = 3, + CONSTANT_InterfaceMethodref = 11, + CONSTANT_InvokeDynamic = 18, + CONSTANT_Long = 5, + CONSTANT_MethodHandle = 15, + CONSTANT_MethodType = 16, + CONSTANT_Methodref = 10, CONSTANT_NameAndType = 12, + CONSTANT_String = 8, CONSTANT_Utf8 = 1 }; diff --git a/src/avian/machine.h b/src/avian/machine.h index d25097c744..21ca414af6 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -2197,6 +2197,16 @@ stringOffset(Thread*, object) return 0; } +# ifndef HAVE_StringHash32 + +inline object +makeString(Thread* t, object data, int32_t hash, int32_t) +{ + return makeString(t, data, hash); +} + +# endif // not HAVE_StringHash32 + inline object makeString(Thread* t, object data, unsigned offset, unsigned length, unsigned) { @@ -2476,16 +2486,33 @@ fieldSize(Thread* t, object field) } inline void -scanMethodSpec(Thread* t, const char* s, unsigned* parameterCount, +scanMethodSpec(Thread* t, const char* s, bool static_, + unsigned* parameterCount, unsigned* parameterFootprint, unsigned* returnCode) { unsigned count = 0; + unsigned footprint = 0; MethodSpecIterator it(t, s); - for (; it.hasNext(); it.next()) { + while (it.hasNext()) { ++ count; + switch (*it.next()) { + case 'J': + case 'D': + footprint += 2; + break; + + default: + ++ footprint; + break; + } + } + + if (not static_) { + ++ footprint; } *parameterCount = count; + *parameterFootprint = footprint; *returnCode = fieldCode(t, *it.returnSpec()); } diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index a6c6970b22..b53a646aa1 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2136,6 +2136,58 @@ countConstructors(Thread* t, object c, bool publicOnly) return count; } +#ifdef HAVE_JexecutableHasRealParameterData +object +makeJmethod(Thread* t, + uint8_t override, + object securityCheckCache, + object clazz, + uint32_t slot, + object name, + object returnType, + object parameterTypes, + object exceptionTypes, + uint32_t modifiers, + object signature, + object genericInfo, + object annotations, + object parameterAnnotations, + object annotationDefault, + object methodAccessor, + object root, + object declaredAnnotations) +{ + return makeJmethod + (t, override, securityCheckCache, 0, 0, declaredAnnotations, clazz, slot, + name, returnType, parameterTypes, exceptionTypes, modifiers, signature, + genericInfo, annotations, parameterAnnotations, annotationDefault, + methodAccessor, root); +} + +object +makeJconstructor(Thread* t, + uint8_t override, + object securityCheckCache, + object clazz, + uint32_t slot, + object parameterTypes, + object exceptionTypes, + uint32_t modifiers, + object signature, + object genericInfo, + object annotations, + object parameterAnnotations, + object constructorAccessor, + object root, + object declaredAnnotations) +{ + return makeJconstructor + (t, override, securityCheckCache, 0, 0, declaredAnnotations, clazz, slot, + parameterTypes, exceptionTypes, modifiers, signature, genericInfo, + annotations, parameterAnnotations, constructorAccessor, root); +} +#endif // HAVE_JexecutableHasRealParameterData + object makeJmethod(Thread* t, object vmMethod, int index) { @@ -3081,7 +3133,13 @@ EXPORT(JVM_FindLibraryEntry)(void* library, const char* name) library = t->m->libraries; } - return static_cast(library)->resolve(name); + for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) { + if (library == lib) { + return lib->resolve(name); + } + } + + return 0; } extern "C" AVIAN_EXPORT jboolean JNICALL @@ -3882,6 +3940,14 @@ EXPORT(JVM_DefineClassWithSource)(Thread* t, const char*, jobject loader, return EXPORT(JVM_DefineClass)(t, 0, loader, data, length, 0); } +extern "C" AVIAN_EXPORT jclass JNICALL +EXPORT(JVM_DefineClassWithSourceCond)(Thread* t, const char*, jobject loader, + const uint8_t* data, jsize length, + jobject, const char*, jboolean) +{ + return EXPORT(JVM_DefineClass)(t, 0, loader, data, length, 0); +} + extern "C" AVIAN_EXPORT jstring JNICALL EXPORT(JVM_GetClassName)(Thread* t, jclass c) { @@ -3972,6 +4038,24 @@ EXPORT(JVM_GetClassSigners)(Thread* t, jclass c) (t, classRuntimeDataSigners(t, runtimeData)) : 0; } +extern "C" AVIAN_EXPORT jbyteArray JNICALL +EXPORT(JVM_GetClassTypeAnnotations)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jbyteArray JNICALL +EXPORT(JVM_GetFieldTypeAnnotations)(Thread*, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jbyteArray JNICALL +EXPORT(JVM_GetMethodTypeAnnotations)(Thread*, jobject) +{ + abort(); +} + extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_SetClassSigners)(Thread* t, jclass c, jobjectArray signers) { @@ -4653,6 +4737,9 @@ EXPORT(JVM_GetMethodIxMaxStack)(Thread*, jclass, int) { abort(); } extern "C" AVIAN_EXPORT jboolean JNICALL EXPORT(JVM_IsConstructorIx)(Thread*, jclass, int) { abort(); } +extern "C" AVIAN_EXPORT jboolean JNICALL +EXPORT(JVM_IsVMGeneratedMethodIx)(Thread*, jclass, int) { abort(); } + extern "C" AVIAN_EXPORT const char* JNICALL EXPORT(JVM_GetMethodIxNameUTF)(Thread*, jclass, jint) { abort(); } diff --git a/src/compile.cpp b/src/compile.cpp index d2146f61bb..4703db05e7 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3296,11 +3296,12 @@ int methodReferenceReturnCode(Thread* t, object reference) { unsigned parameterCount; + unsigned parameterFootprint; unsigned returnCode; scanMethodSpec (t, reinterpret_cast - (&byteArrayBody(t, referenceSpec(t, reference), 0)), ¶meterCount, - &returnCode); + (&byteArrayBody(t, referenceSpec(t, reference), 0)), true, + ¶meterCount, ¶meterFootprint, &returnCode); return returnCode; } diff --git a/src/machine.cpp b/src/machine.cpp index f2357e2c90..93ddf5d5bc 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -945,7 +945,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) unsigned si = s.read2() - 1; parsePoolEntry(t, s, index, pool, si); - object value = makeReference(t, 0, singletonObject(t, pool, si), 0); + object value = makeReference(t, 0, 0, singletonObject(t, pool, si), 0); set(t, pool, SingletonBody + (i * BytesPerWord), value); if(DebugClassReader) { @@ -1004,7 +1004,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) object nameAndType = singletonObject(t, pool, nti); object value = makeReference - (t, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType)); + (t, 0, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType)); set(t, pool, SingletonBody + (i * BytesPerWord), value); if(DebugClassReader) { @@ -1013,6 +1013,68 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) } } return 1; + case CONSTANT_MethodHandle: + if (singletonObject(t, pool, i) == 0) { + unsigned kind = s.read1(); + unsigned ri = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, ri); + + object value = singletonObject(t, pool, ri); + + if (DebugClassReader) { + fprintf(stderr, " consts[%d] = method handle %d %s.%s%s\n", i, kind, + &byteArrayBody(t, referenceClass(t, value), 0), + &byteArrayBody(t, referenceName(t, value), 0), + &byteArrayBody(t, referenceSpec(t, value), 0)); + } + + value = makeReference + (t, kind, referenceClass(t, value), referenceName(t, value), + referenceSpec(t, value)); + + set(t, pool, SingletonBody + (i * BytesPerWord), value); + } return 1; + + case CONSTANT_MethodType: + if (singletonObject(t, pool, i) == 0) { + unsigned ni = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, ni); + + set(t, pool, SingletonBody + (i * BytesPerWord), + singletonObject(t, pool, ni)); + } return 1; + + case CONSTANT_InvokeDynamic: + if (singletonObject(t, pool, i) == 0) { + unsigned bootstrap = s.read2(); + unsigned nti = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, nti); + + object nameAndType = singletonObject(t, pool, nti); + + const char* specString = reinterpret_cast + (&byteArrayBody(t, pairSecond(t, nameAndType), 0)); + + unsigned parameterCount; + unsigned parameterFootprint; + unsigned returnCode; + scanMethodSpec + (t, specString, true, ¶meterCount, ¶meterFootprint, + &returnCode); + + object template_ = makeMethod + (t, 0, returnCode, parameterCount, parameterFootprint, 0, 0, 0, 0, + pairFirst(t, nameAndType), pairSecond(t, nameAndType), 0, 0, 0); + + object value = makeInvocation + (t, bootstrap, -1, 0, pool, template_, 0); + + set(t, pool, SingletonBody + (i * BytesPerWord), value); + } return 1; + default: abort(t); } } @@ -1078,6 +1140,21 @@ parsePool(Thread* t, Stream& s) s.skip(s.read2()); break; + case CONSTANT_MethodHandle: + singletonMarkObject(t, pool, i); + s.skip(3); + break; + + case CONSTANT_MethodType: + singletonMarkObject(t, pool, i); + s.skip(2); + break; + + case CONSTANT_InvokeDynamic: + singletonMarkObject(t, pool, i); + s.skip(4); + break; + default: abort(t); } } @@ -2066,15 +2143,17 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) (&byteArrayBody(t, singletonObject(t, pool, spec - 1), 0)); unsigned parameterCount; + unsigned parameterFootprint; unsigned returnCode; - scanMethodSpec(t, specString, ¶meterCount, &returnCode); + scanMethodSpec(t, specString, flags & ACC_STATIC, ¶meterCount, + ¶meterFootprint, &returnCode); object method = t->m->processor->makeMethod (t, 0, // vm flags returnCode, parameterCount, - parameterFootprint(t, specString, flags & ACC_STATIC), + parameterFootprint, flags, 0, // offset singletonObject(t, pool, name - 1), @@ -5158,6 +5237,10 @@ parseUtf8(Thread* t, object array) object getCaller(Thread* t, unsigned target, bool skipMethodInvoke) { + if (static_cast(target) == -1) { + target = 2; + } + class Visitor: public Processor::StackVisitor { public: Visitor(Thread* t, unsigned target, bool skipMethodInvoke): diff --git a/src/tools/type-generator/main.cpp b/src/tools/type-generator/main.cpp index 258f0951b6..90affb4e3c 100644 --- a/src/tools/type-generator/main.cpp +++ b/src/tools/type-generator/main.cpp @@ -1061,6 +1061,7 @@ parseType(Finder* finder, Object::ObjectType type, Object* p, } } client; System::Region* region = finder->find(append(javaName, ".class")); + if (region == 0) return 0; Stream s(&client, region->start(), region->length()); parseJavaClass(t, &s, declarations); region->dispose(); @@ -1109,8 +1110,10 @@ parse(Finder* finder, Input* in) Object* o; while ((o = read(in, eos, 0)) != eos) { - declarations.append - (parseDeclaration(finder, o, declarations.first)); + Object* declaration = parseDeclaration(finder, o, declarations.first); + if (declaration) { + declarations.append(declaration); + } } return declarations.first; diff --git a/src/types.def b/src/types.def index 82b0e5a5aa..0b6b63f5ab 100644 --- a/src/types.def +++ b/src/types.def @@ -8,6 +8,8 @@ (type jaccessibleObject java/lang/reflect/AccessibleObject) +(type jexecutable java/lang/reflect/Executable) + (type jfield java/lang/reflect/Field) (type jmethod java/lang/reflect/Method) @@ -87,10 +89,19 @@ (array uint8_t body)) (type reference + (uint8_t kind) (object class) (object name) (object spec)) +(type invocation + (uint16_t bootstrap) + (int32_t index) + (object class) + (object pool) + (object template) + (object site)) + (type triple (object first) (object second) diff --git a/test/Regex.java b/test/Regex.java index f67413978c..1409c67e3e 100644 --- a/test/Regex.java +++ b/test/Regex.java @@ -85,7 +85,13 @@ public class Regex { expectNoMatch("[a-z&&[^d-f]]", "f"); expectSplit("^H", "Hello\nHobbes!", "", "ello\nHobbes!"); expectSplit("o.*?$", "Hello\r\nHobbes!", "Hello\r\nH"); - expectSplit("\\b", "a+ b + c\nd", "", "a", "+ ", "b", " + ", "c", "\n", "d"); + try { + expectSplit("\\b", "a+ b + c\nd", "", "a", "+ ", "b", " + ", "c", "\n", "d"); + } catch (RuntimeException e) { + // Java 8 changed the semantics of split, so if we're on 8, the + // above will fail and this will succeed: + expectSplit("\\b", "a+ b + c\nd", "a", "+ ", "b", " + ", "c", "\n", "d"); + } expectSplit("\\B", "Hi Cal!", "H", "i C", "a", "l!"); expectMatch("a{2,5}", "aaaa"); expectGroups("a??(a{2,5}?)", "aaaa", "aaaa"); diff --git a/test/Strings.java b/test/Strings.java index f37c99efaa..823b024c02 100644 --- a/test/Strings.java +++ b/test/Strings.java @@ -124,22 +124,39 @@ public class Strings { expect(months.split("\u00ae").length == 3); expect(months.replaceAll("\u00ae", ".").equals("Jan.Feb.Mar.")); + // Java 8 changed the semantics of String.split relative to + // previous versions, therefore we accept multiple possible + // results: expect(arraysEqual - ("xyz".split("", 0), new String[] { "", "x", "y", "z" })); + ("xyz".split("", 0), new String[] { "", "x", "y", "z" }) + || arraysEqual + ("xyz".split("", 0), new String[] { "x", "y", "z" })); expect(arraysEqual ("xyz".split("", 1), new String[] { "xyz" })); expect(arraysEqual - ("xyz".split("", 2), new String[] { "", "xyz" })); + ("xyz".split("", 2), new String[] { "", "xyz" }) + || arraysEqual + ("xyz".split("", 2), new String[] { "x", "yz" })); expect(arraysEqual - ("xyz".split("", 3), new String[] { "", "x", "yz" })); + ("xyz".split("", 3), new String[] { "", "x", "yz" }) + || arraysEqual + ("xyz".split("", 3), new String[] { "x", "y", "z" })); expect(arraysEqual - ("xyz".split("", 4), new String[] { "", "x", "y", "z" })); + ("xyz".split("", 4), new String[] { "", "x", "y", "z" }) + || arraysEqual + ("xyz".split("", 4), new String[] { "x", "y", "z", "" })); expect(arraysEqual - ("xyz".split("", 5), new String[] { "", "x", "y", "z", "" })); + ("xyz".split("", 5), new String[] { "", "x", "y", "z", "" }) + || arraysEqual + ("xyz".split("", 5), new String[] { "x", "y", "z", "" })); expect(arraysEqual - ("xyz".split("", 6), new String[] { "", "x", "y", "z", "" })); + ("xyz".split("", 6), new String[] { "", "x", "y", "z", "" }) + || arraysEqual + ("xyz".split("", 6), new String[] { "x", "y", "z", "" })); expect(arraysEqual - ("xyz".split("", -1), new String[] { "", "x", "y", "z", "" })); + ("xyz".split("", -1), new String[] { "", "x", "y", "z", "" }) + || arraysEqual + ("xyz".split("", -1), new String[] { "x", "y", "z", "" })); expect(arraysEqual("".split("xyz", 0), new String[] { "" })); expect(arraysEqual("".split("xyz", 1), new String[] { "" }));