diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 9b7f83286f..d08601a465 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -408,7 +408,6 @@ Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path) if (not exists(chars)) { int fd = OPEN(chars, O_CREAT | O_WRONLY | O_EXCL, 0600); if (fd == -1) { - fprintf(stderr, "errno %d\n", errno); if (errno != EEXIST) { throwNewErrno(e, "java/io/IOException"); } diff --git a/classpath/java/lang/ReflectiveOperationException.java b/classpath/java/lang/ReflectiveOperationException.java new file mode 100644 index 0000000000..e3c8c0872f --- /dev/null +++ b/classpath/java/lang/ReflectiveOperationException.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2012, 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 java.lang; + +public class ReflectiveOperationException extends Exception { } diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java index 84f22b88db..b7613d2559 100644 --- a/classpath/sun/misc/Unsafe.java +++ b/classpath/sun/misc/Unsafe.java @@ -11,7 +11,8 @@ public final class Unsafe { public native long allocateMemory(long bytes); - public native void setMemory(long address, long count, byte value); + public native void setMemory + (Object base, long offset, long count, byte value); public native void freeMemory(long address); diff --git a/makefile b/makefile index 85375afbd0..86bc33e9b1 100755 --- a/makefile +++ b/makefile @@ -115,8 +115,13 @@ ifneq ($(openjdk),) else options := $(options)-openjdk test-executable = $(shell pwd)/$(executable-dynamic) - library-path = \ - $(library-path-variable)=$(build):$(openjdk)/jre/lib/$(openjdk-arch) + ifeq ($(build-platform),darwin) + library-path = \ + $(library-path-variable)=$(build):$(openjdk)/jre/lib + else + library-path = \ + $(library-path-variable)=$(build):$(openjdk)/jre/lib/$(openjdk-arch) + endif javahome = "$$($(native-path) "$(openjdk)/jre")" endif @@ -308,9 +313,11 @@ ifeq ($(platform),darwin) endif version-script-flag = - lflags = $(common-lflags) -ldl -framework CoreFoundation + lflags = $(common-lflags) -ldl -framework CoreFoundation \ + -Wl,-compatibility_version,1.0.0 ifneq ($(arch),arm) - lflags += -framework CoreServices + lflags += -framework CoreServices -framework SystemConfiguration \ + -framework Security endif ifeq ($(bootimage),true) bootimage-lflags = -Wl,-segprot,__RWX,rwx,rwx @@ -376,10 +383,9 @@ ifeq ($(platform),windows) so-suffix = .dll exe-suffix = .exe - lflags = -L$(lib) $(common-lflags) -lws2_32 -mwindows -mconsole + lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mwindows -mconsole cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 - ifeq (,$(filter mingw32 cygwin,$(build-platform))) openjdk-extra-cflags += -I$(src)/openjdk/caseSensitive cxx = x86_64-w64-mingw32-g++ -m32 @@ -417,6 +423,8 @@ ifeq ($(platform),windows) strip = x86_64-w64-mingw32-strip inc = "$(win64)/include" lib = "$(win64)/lib" + else + shared += -Wl,--add-stdcall-alias endif endif @@ -1003,6 +1011,18 @@ $(openjdk-objects): $(build)/openjdk/%-openjdk.o: $(openjdk-src)/%.c \ @echo "compiling $(@)" @mkdir -p $(dir $(@)) sed 's/^static jclass ia_class;//' < $(<) > $(build)/openjdk/$(notdir $(<)) +ifeq ($(ios),true) + sed \ + -e 's/^#ifndef __APPLE__/#if 1/' \ + -e 's/^#ifdef __APPLE__/#if 0/' \ + < "$(openjdk-src)/solaris/native/java/lang/ProcessEnvironment_md.c" \ + > $(build)/openjdk/ProcessEnvironment_md.c + sed \ + -e 's/^#ifndef __APPLE__/#if 1/' \ + -e 's/^#ifdef __APPLE__/#if 0/' \ + < "$(openjdk-src)/solaris/native/java/lang/UNIXProcess_md.c" \ + > $(build)/openjdk/UNIXProcess_md.c +endif $(cc) -fPIC $(openjdk-extra-cflags) $(openjdk-cflags) \ $(optimization-cflags) -w -c $(build)/openjdk/$(notdir $(<)) \ $(call output,$(@)) @@ -1033,6 +1053,42 @@ ifeq ($(platform),windows) < "$(openjdk-src)/windows/native/java/net/NetworkInterface.h" \ > $(build)/openjdk/NetworkInterface.h echo 'static int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);' >> $(build)/openjdk/NetworkInterface.h +endif +ifeq ($(platform),darwin) + mkdir -p $(build)/openjdk/netinet + for file in \ + /usr/include/netinet/ip.h \ + /usr/include/netinet/in_systm.h \ + /usr/include/netinet/ip_icmp.h \ + /usr/include/netinet/in_var.h \ + /usr/include/netinet/icmp6.h \ + /usr/include/netinet/ip_var.h; do \ + if [ ! -f "$(build)/openjdk/netinet/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/netinet/$$(basename $${file})"; \ + fi; \ + done + mkdir -p $(build)/openjdk/netinet6 + for file in \ + /usr/include/netinet6/in6_var.h; do \ + if [ ! -f "$(build)/openjdk/netinet6/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/netinet6/$$(basename $${file})"; \ + fi; \ + done + mkdir -p $(build)/openjdk/net + for file in \ + /usr/include/net/if_arp.h; do \ + if [ ! -f "$(build)/openjdk/net/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/net/$$(basename $${file})"; \ + fi; \ + done + mkdir -p $(build)/openjdk/sys + for file in \ + /usr/include/sys/kern_event.h \ + /usr/include/sys/sys_domain.h; do \ + if [ ! -f "$(build)/openjdk/sys/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/sys/$$(basename $${file})"; \ + fi; \ + done endif @touch $(@) @@ -1044,6 +1100,7 @@ $(openjdk-jar-dep): $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/rt.jar")" && \ $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jsse.jar")" && \ $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jce.jar")" && \ + $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/charsets.jar")" && \ $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/ext/sunjce_provider.jar")" && \ $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/resources.jar")") @touch $(@) diff --git a/openjdk-src.mk b/openjdk-src.mk index 28166a9542..027b6a79b5 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -45,7 +45,6 @@ openjdk-sources = \ $(openjdk-src)/share/native/java/util/zip/CRC32.c \ $(openjdk-src)/share/native/java/util/zip/Deflater.c \ $(openjdk-src)/share/native/java/util/zip/Inflater.c \ - $(openjdk-src)/share/native/java/util/zip/ZipEntry.c \ $(openjdk-src)/share/native/java/util/zip/ZipFile.c \ $(openjdk-src)/share/native/java/util/zip/zip_util.c \ $(openjdk-src)/share/native/sun/management/VMManagementImpl.c \ @@ -76,6 +75,7 @@ openjdk-headers-classes = \ java.lang.Double \ java.lang.Float \ java.lang.Integer \ + java.lang.Long \ java.lang.Object \ java.lang.Package \ java.lang.Runtime \ @@ -124,7 +124,7 @@ openjdk-headers-classes = \ sun.net.spi.DefaultProxySelector \ sun.nio.ch.FileKey \ sun.nio.ch.FileChannelImpl \ - sun.nio.ch.FileDispatcher \ + sun.nio.ch.FileDispatcherImpl \ sun.nio.ch.DatagramChannelImpl \ sun.nio.ch.DatagramDispatcher \ sun.nio.ch.IOStatus \ @@ -173,6 +173,7 @@ endif ifeq ($(platform),windows) openjdk-sources += \ + $(openjdk-src)/windows/native/common/jni_util_md.c \ $(openjdk-src)/windows/native/java/io/canonicalize_md.c \ $(openjdk-src)/windows/native/java/io/Console_md.c \ $(openjdk-src)/windows/native/java/io/FileDescriptor_md.c \ @@ -193,7 +194,6 @@ ifeq ($(platform),windows) $(openjdk-src)/windows/native/java/net/Inet6AddressImpl.c \ $(openjdk-src)/windows/native/java/net/NetworkInterface.c \ $(openjdk-src)/windows/native/java/net/NetworkInterface_winXP.c \ - $(openjdk-src)/windows/native/java/net/NetworkInterface_win9x.c \ $(openjdk-src)/windows/native/java/net/SocketInputStream.c \ $(openjdk-src)/windows/native/java/net/SocketOutputStream.c \ $(openjdk-src)/windows/native/java/util/WindowsPreferences.c \ @@ -203,7 +203,7 @@ ifeq ($(platform),windows) $(openjdk-src)/windows/native/sun/nio/ch/DatagramChannelImpl.c \ $(openjdk-src)/windows/native/sun/nio/ch/DatagramDispatcher.c \ $(openjdk-src)/windows/native/sun/nio/ch/FileChannelImpl.c \ - $(openjdk-src)/windows/native/sun/nio/ch/FileDispatcher.c \ + $(openjdk-src)/windows/native/sun/nio/ch/FileDispatcherImpl.c \ $(openjdk-src)/windows/native/sun/nio/ch/FileKey.c \ $(openjdk-src)/windows/native/sun/nio/ch/IOUtil.c \ $(openjdk-src)/windows/native/sun/nio/ch/Net.c \ @@ -211,6 +211,7 @@ ifeq ($(platform),windows) $(openjdk-src)/windows/native/sun/nio/ch/SocketChannelImpl.c \ $(openjdk-src)/windows/native/sun/nio/ch/SocketDispatcher.c \ $(openjdk-src)/windows/native/sun/nio/ch/WindowsSelectorImpl.c \ + $(openjdk-src)/windows/native/sun/nio/fs/WindowsNativeDispatcher.c \ $(openjdk-src)/windows/native/sun/security/provider/WinCAPISeedGenerator.c openjdk-headers-classes += \ @@ -218,6 +219,7 @@ ifeq ($(platform),windows) java.lang.ProcessImpl \ sun.io.Win32ErrorMode \ sun.nio.ch.WindowsSelectorImpl \ + sun.nio.fs.WindowsNativeDispatcher \ openjdk-cflags += \ "-I$(openjdk-src)/windows/javavm/export" \ @@ -228,6 +230,9 @@ ifeq ($(platform),windows) "-I$(openjdk-src)/windows/native/sun/nio/ch" \ "-I$(openjdk-src)/windows/javavm/include" \ "-I$(root)/win32/include" \ + -DLOCALE_SNAME=0x0000005c \ + -DLOCALE_SISO3166CTRYNAME2=0x00000068 \ + -DLOCALE_SISO639LANGNAME2=0x00000067 \ -D_JNI_IMPLEMENTATION_ \ -D_JAVASOFT_WIN32_TYPEDEF_MD_H_ \ -Ds6_words=_s6_words \ @@ -235,6 +240,7 @@ ifeq ($(platform),windows) else openjdk-sources += \ $(openjdk-src)/solaris/native/common/jdk_util_md.c \ + $(openjdk-src)/solaris/native/common/jni_util_md.c \ $(openjdk-src)/solaris/native/java/io/canonicalize_md.c \ $(openjdk-src)/solaris/native/java/io/Console_md.c \ $(openjdk-src)/solaris/native/java/io/FileDescriptor_md.c \ @@ -265,30 +271,26 @@ else $(openjdk-src)/solaris/native/sun/nio/ch/DatagramChannelImpl.c \ $(openjdk-src)/solaris/native/sun/nio/ch/DatagramDispatcher.c \ $(openjdk-src)/solaris/native/sun/nio/ch/FileChannelImpl.c \ - $(openjdk-src)/solaris/native/sun/nio/ch/FileDispatcher.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/FileDispatcherImpl.c \ $(openjdk-src)/solaris/native/sun/nio/ch/FileKey.c \ $(openjdk-src)/solaris/native/sun/nio/ch/IOUtil.c \ $(openjdk-src)/solaris/native/sun/nio/ch/Net.c \ $(openjdk-src)/solaris/native/sun/nio/ch/ServerSocketChannelImpl.c \ $(openjdk-src)/solaris/native/sun/nio/ch/SocketChannelImpl.c \ $(openjdk-src)/solaris/native/sun/nio/ch/SocketDispatcher.c \ - $(openjdk-src)/solaris/native/sun/nio/ch/EPollArrayWrapper.c \ $(openjdk-src)/solaris/native/sun/nio/ch/PollArrayWrapper.c \ $(openjdk-src)/solaris/native/sun/nio/ch/InheritedChannel.c \ $(openjdk-src)/solaris/native/sun/nio/ch/NativeThread.c \ - - ifeq ($(platform),linux) - openjdk-sources += \ - $(openjdk-src)/solaris/native/java/net/linux_close.c - endif + $(openjdk-src)/solaris/native/sun/nio/fs/UnixNativeDispatcher.c \ openjdk-headers-classes += \ java.net.PlainDatagramSocketImpl \ java.io.UnixFileSystem \ sun.nio.ch.InheritedChannel \ - sun.nio.ch.EPollArrayWrapper \ + sun.nio.fs.UnixNativeDispatcher \ - openjdk-cflags += "-I$(openjdk-src)/solaris/javavm/export" \ + openjdk-cflags += \ + "-I$(openjdk-src)/solaris/javavm/export" \ "-I$(openjdk-src)/solaris/native/common" \ "-I$(openjdk-src)/solaris/native/java/io" \ "-I$(openjdk-src)/solaris/native/java/lang" \ @@ -297,10 +299,45 @@ else "-I$(openjdk-src)/solaris/native/sun/management" \ "-I$(openjdk-src)/solaris/native/sun/nio/ch" \ "-I$(openjdk-src)/solaris/javavm/include" \ - "-I$(openjdk-src)/solaris/hpi/include" + "-I$(openjdk-src)/solaris/hpi/include" \ + "-I$(openjdk-src)/solaris/native/common/deps" + + ifeq ($(platform),linux) + openjdk-sources += \ + $(openjdk-src)/solaris/native/java/net/linux_close.c \ + $(openjdk-src)/solaris/native/common/deps/syscalls_fp.c \ + $(openjdk-src)/solaris/native/common/deps/gconf2/gconf_fp.c \ + $(openjdk-src)/solaris/native/common/deps/glib2/gio_fp.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/EPollArrayWrapper.c + + openjdk-headers-classes += \ + sun.nio.ch.EPollArrayWrapper + + openjdk-cflags += \ + "-I$(openjdk-src)/solaris/native/common/deps/glib2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gconf2" \ + $(shell pkg-config --cflags glib-2.0) \ + $(shell pkg-config --cflags gconf-2.0) + endif + + ifeq ($(platform),darwin) + openjdk-sources += \ + $(openjdk-src)/solaris/native/java/net/bsd_close.c + + ifeq ($(ios),true) + openjdk-local-sources += \ + $(src)/openjdk/my_java_props_macosx.c + else + openjdk-sources += \ + $(openjdk-src)/solaris/native/java/lang/java_props_macosx.c + endif + + openjdk-cflags += \ + -DMACOSX + endif endif -openjdk-local-sources = \ +openjdk-local-sources += \ $(src)/openjdk/my_net_util.c \ $(src)/openjdk/my_management.c diff --git a/openjdk.pro b/openjdk.pro index dd9e07a910..953b5e205b 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -11,6 +11,7 @@ -keep class java.lang.System { private static void initializeSystemClass(); + public static void setProperties(java.util.Properties); } -keep class java.lang.ClassLoader { @@ -33,6 +34,11 @@ -keep class java.util.Properties { public java.lang.Object setProperty(java.lang.String, java.lang.String); + public java.lang.String getProperty(java.lang.String); + } + +-keep class java.util.Hashtable { + public java.lang.Object remove(java.lang.Object); } -keep class avian.OpenJDK { diff --git a/readme.txt b/readme.txt index 7ae4a46e62..7a5591715f 100644 --- a/readme.txt +++ b/readme.txt @@ -220,11 +220,11 @@ features beyond that subset, you may want to tell Avian to use OpenJDK's class library instead. To do so, specify the directory where OpenJDK is installed, e.g.: - $ make openjdk=/usr/lib/jvm/java-6-openjdk + $ make openjdk=/usr/lib/jvm/java-7-openjdk This will build Avian as a conventional JVM (e.g. libjvm.so) which loads its boot class library and native libraries (e.g. libjava.so) -from /usr/lib/jvm/java-6-openjdk/jre at runtime. To run an +from /usr/lib/jvm/java-7-openjdk/jre at runtime. To run an application in this configuration, you'll need to make sure the VM is in your library search path. For example: @@ -235,8 +235,8 @@ in your library search path. For example: Alternatively, you can enable a stand-alone build using OpenJDK by specifying the location of the OpenJDK source code, e.g.: - $ make openjdk=$(pwd)/../jdk6/build/linux-amd64/j2sdk-image \ - openjdk-src=$(pwd)/../jdk6/jdk/src + $ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../jdk7/jdk/src You must ensure that the path specified for openjdk-src does not have any spaces in it; make gets confused when dependency paths include @@ -260,7 +260,9 @@ an LZMA-enabled version: You can reduce the size futher for embedded builds by using ProGuard and the supplied openjdk.pro configuration file (see "Embedding with -ProGuard and a Boot Image" below). Also see app.mk in +ProGuard and a Boot Image" below). Note that you'll still need to use +vm.pro in that case -- openjdk.pro just adds additional constraints +specific to the OpenJDK port. Also see app.mk in git://oss.readytalk.com/avian-swt-examples.git for an example of using Avian, OpenJDK, ProGuard, and UPX in concert. @@ -269,49 +271,42 @@ it on various OSes: Debian-based Linux: # conventional build: - apt-get install openjdk-6-jdk - make openjdk=/usr/lib/jvm/java-6-openjdk test + apt-get install openjdk-7-jdk + make openjdk=/usr/lib/jvm/java-7-openjdk test # stand-alone build: - apt-get install openjdk-6-jdk - apt-get source openjdk-6-jdk - apt-get build-dep openjdk-6-jdk - (cd openjdk-6-6b18-1.8.3 && ./debian/rules patch) - make openjdk=/usr/lib/jvm/java-6-openjdk \ - openjdk-src=$(pwd)/openjdk-6-6b18-1.8.3/build/openjdk/jdk/src \ + apt-get install openjdk-7-jdk + apt-get source openjdk-7-jdk + apt-get build-dep openjdk-7-jdk + (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage) + make openjdk=/usr/lib/jvm/java-7-openjdk \ + openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \ test Mac OS X: - # Prerequisite: install MacPorts (http://www.macports.org/) - sudo port selfupdate + # Prerequisite: build OpenJDK 7 according to + # https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port # conventional build: - sudo port install openjdk6 - make openjdk=/opt/local/share/java/openjdk6 test + make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test # stand-alone build: - sudo port fetch openjdk6 - sudo port patch openjdk6 - make openjdk=/opt/local/share/java/openjdk6 \ - openjdk-src=/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_java_openjdk6/work/jdk/src \ - test + make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test Windows (Cygwin): + # Prerequisite: build OpenJDK 7 according to + # http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction + # conventional build: - # Prerequisite: download and install the latest Windows OpenJDK - # build from http://www.openscg.com/se/openjdk/ - make openjdk=/cygdrive/c/OpenSCG/openjdk-6.21 test + make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test # stand-alone build: - # Prerequisite: install OpenSCG build as above, plus the - # corresponding source bundle from - # http://download.java.net/openjdk/jdk6/promoted/, e.g.: - wget http://download.java.net/openjdk/jdk6/promoted/b21/openjdk-6-src-b21-20_jan_2011.tar.gz - mkdir openjdk - (cd openjdk && tar xzf ../openjdk-6-src-b21-20_jan_2011.tar.gz) - make openjdk=/cygdrive/c/OpenSCG/openjdk-6.21 \ - openjdk-src=$(pwd)/openjdk/jdk/src \ - test + make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test + +Currently, only OpenJDK 7 is supported. Later versions might work, +but have not yet been tested. Installing @@ -364,7 +359,7 @@ method. Note the bootJar function, which will be called by the VM to get a handle to the embedded jar. We tell the VM about this jar by setting the boot classpath to "[bootJar]". - $ cat >main.cpp <embedded-jar-main.cpp <main.cpp <bootimage-main.cpp <m->system, t->m->heap, 64 * 1024); class MyCompilationHandler : public Processor::CompilationHandler { @@ -1956,14 +1957,18 @@ main(int ac, const char** av) // in a branch instruction for the target architecture (~32MB on // PowerPC and ARM). When that limitation is removed, we'll be able // to specify a capacity as large as we like here: +#if (defined ARCH_x86_64) || (defined ARCH_x86_32) + const unsigned CodeCapacity = 128 * 1024 * 1024; +#else const unsigned CodeCapacity = 30 * 1024 * 1024; +#endif uint8_t* code = static_cast(h->allocate(CodeCapacity)); BootImage image; p->initialize(&image, code, CodeCapacity); Machine* m = new (h->allocate(sizeof(Machine))) Machine - (s, h, f, 0, p, c, 0, 0, 0, 0); + (s, h, f, 0, p, c, 0, 0, 0, 0, 128 * 1024); Thread* t = p->makeThread(m, 0, 0); enter(t, Thread::ActiveState); diff --git a/src/builtin.cpp b/src/builtin.cpp index 7cd41cb3b6..e5cd6bfe07 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -353,13 +353,22 @@ Avian_sun_misc_Unsafe_freeMemory extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_setMemory -(Thread*, object, uintptr_t* arguments) +(Thread* t, object, uintptr_t* arguments) { - int64_t p; memcpy(&p, arguments + 1, 8); - int64_t count; memcpy(&count, arguments + 3, 8); - int8_t v = arguments[5]; + object base = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + int64_t count; memcpy(&count, arguments + 4, 8); + int8_t value = arguments[6]; - memset(reinterpret_cast(p), v, count); + PROTECT(t, base); + + ACQUIRE(t, t->m->referenceLock); + + if (base) { + memset(&cast(base, offset), value, count); + } else { + memset(reinterpret_cast(offset), value, count); + } } // NB: The following primitive get/put methods are only used by the diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 39cde4ff83..5df85fa6b6 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -54,6 +54,12 @@ class MyClasspath : public Classpath { root(t, Machine::BootLoader), 0, 0, group, 0); } + virtual void + clearInterrupted(Thread*) + { + // ignore + } + virtual void runThread(Thread* t) { diff --git a/src/classpath-common.h b/src/classpath-common.h index 99e042162c..5f769ae00f 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -120,6 +120,16 @@ void runOnLoadIfFound(Thread* t, System::Library* library) { void* p = library->resolve("JNI_OnLoad"); + +#ifdef PLATFORM_WINDOWS + if (p == 0) { + p = library->resolve("_JNI_OnLoad@8"); + if (p == 0) { + p = library->resolve("JNI_OnLoad@8"); + } + } +#endif + if (p) { jint (JNICALL * JNI_OnLoad)(Machine*, void*); memcpy(&JNI_OnLoad, &p, sizeof(void*)); diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 72c9750fd5..721889e452 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -344,6 +344,9 @@ makeClassNameString(Thread* t, object name) void interceptFileOperations(Thread*); +void +clearInterrupted(Thread*); + class MyClasspath : public Classpath { public: static const unsigned BufferSize = 1024; @@ -410,6 +413,8 @@ class MyClasspath : public Classpath { sb.append(javaHome); #ifdef PLATFORM_WINDOWS sb.append("/bin"); +#elif defined __APPLE__ + sb.append("/lib"); #elif defined ARCH_x86_64 sb.append("/lib/amd64"); #else @@ -435,9 +440,14 @@ class MyClasspath : public Classpath { PROTECT(t, class_); object name = makeClassNameString(t, getClassName(t, class_)); + PROTECT(t, name); - return vm::makeJclass - (t, 0, 0, name, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, class_); + object c = allocate(t, FixedSizeOfJclass, true); + setObjectClass(t, c, type(t, Machine::JclassType)); + set(t, c, JclassName, name); + set(t, c, JclassVmClass, class_); + + return c; } virtual object @@ -499,6 +509,12 @@ class MyClasspath : public Classpath { return thread; } + virtual void + clearInterrupted(Thread* t) + { + local::clearInterrupted(t); + } + virtual void runThread(Thread* t) { @@ -546,31 +562,61 @@ class MyClasspath : public Classpath { expect(t, loadLibrary(t, libraryPath, "java", true, true)); #endif // not AVIAN_OPENJDK_SRC - object constructor = resolveMethod + { object class_ = resolveClass + (t, root(t, Machine::BootLoader), "java/util/Properties", true, + Machine::NoClassDefFoundErrorType); + + PROTECT(t, class_); + + object instance = makeNew(t, class_); + + PROTECT(t, instance); + + object constructor = resolveMethod(t, class_, "", "()V"); + + t->m->processor->invoke(t, constructor, instance); + + t->m->processor->invoke + (t, root(t, Machine::BootLoader), "java/lang/System", + "setProperties", "(Ljava/util/Properties;)V", 0, instance); + } + + { object constructor = resolveMethod (t, type(t, Machine::ClassLoaderType), "", "(Ljava/lang/ClassLoader;)V"); - PROTECT(t, constructor); + PROTECT(t, constructor); - t->m->processor->invoke(t, constructor, root(t, Machine::BootLoader), 0); + t->m->processor->invoke(t, constructor, root(t, Machine::BootLoader), 0); - t->m->processor->invoke - (t, constructor, root(t, Machine::AppLoader), - root(t, Machine::BootLoader)); + t->m->processor->invoke + (t, constructor, root(t, Machine::AppLoader), + root(t, Machine::BootLoader)); + } - object scl = resolveField - (t, type(t, Machine::ClassLoaderType), "scl", "Ljava/lang/ClassLoader;"); + { object assertionLock = resolveField + (t, type(t, Machine::ClassLoaderType), "assertionLock", + "Ljava/lang/Object;"); - PROTECT(t, scl); + set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock), + root(t, Machine::BootLoader)); + } - object sclSet = resolveField - (t, type(t, Machine::ClassLoaderType), "sclSet", "Z"); + { object scl = resolveField + (t, type(t, Machine::ClassLoaderType), "scl", + "Ljava/lang/ClassLoader;"); - set(t, classStaticTable(t, type(t, Machine::ClassLoaderType)), - fieldOffset(t, scl), root(t, Machine::AppLoader)); + PROTECT(t, scl); - cast(classStaticTable(t, type(t, Machine::ClassLoaderType)), - fieldOffset(t, sclSet)) = true; + object sclSet = resolveField + (t, type(t, Machine::ClassLoaderType), "sclSet", "Z"); + + set(t, classStaticTable(t, type(t, Machine::ClassLoaderType)), + fieldOffset(t, scl), root(t, Machine::AppLoader)); + + cast(classStaticTable(t, type(t, Machine::ClassLoaderType)), + fieldOffset(t, sclSet)) = true; + } t->m->processor->invoke (t, root(t, Machine::BootLoader), "java/lang/System", @@ -1313,15 +1359,17 @@ getZipFileEntry(Thread* t, object method, uintptr_t* arguments) ZipFile* file = reinterpret_cast(peer); if (file->region) { - THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 2); - stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + THREAD_RUNTIME_ARRAY(t, char, p, byteArrayLength(t, path) + 2); + memcpy(RUNTIME_ARRAY_BODY(p), &byteArrayBody(t, path, 0), + byteArrayLength(t, path)); + RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path)] = 0; replace('\\', '/', RUNTIME_ARRAY_BODY(p)); if (addSlash) { - RUNTIME_ARRAY_BODY(p)[stringLength(t, path)] = '/'; - RUNTIME_ARRAY_BODY(p)[stringLength(t, path) + 1] = 0; + RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path)] = '/'; + RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path) + 1] = 0; } - return reinterpret_cast(find(file, p, stringLength(t, path))); + return reinterpret_cast(find(file, p, byteArrayLength(t, path))); } else { int64_t entry = longValue (t, t->m->processor->invoke @@ -1335,6 +1383,43 @@ getZipFileEntry(Thread* t, object method, uintptr_t* arguments) } } +int64_t JNICALL +getZipFileEntryBytes(Thread* t, object method, uintptr_t* arguments) +{ + int64_t peer; memcpy(&peer, arguments, 8); + int type = arguments[2]; + + ZipFile::Entry* entry = reinterpret_cast(peer); + if (entry->start) { + switch (type) { + case 0: { // name + unsigned nameLength = fileNameLength(entry->start); + object array = makeByteArray(t, nameLength + 1); + memcpy(&byteArrayBody(t, array, 0), fileName(entry->start), nameLength); + byteArrayBody(t, array, nameLength) = 0; + return reinterpret_cast(array); + } break; + + case 1: { // extra + return 0; + } break; + + case 2: { // comment + return 0; + } break; + + default: abort(t); + } + return compressedSize(entry->start); + } else { + return reinterpret_cast + (t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + 0, entry->entry, type)); + } +} + int64_t JNICALL getNextZipFileEntry(Thread* t, object method, uintptr_t* arguments) { @@ -1462,6 +1547,8 @@ freeZipFileEntry(Thread* t, object method, uintptr_t* arguments) (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), 0, file->file, entry->entry); } + + t->m->heap->free(entry, sizeof(ZipFile::Entry)); } int64_t JNICALL @@ -1669,7 +1756,7 @@ loadLibrary(Thread* t, object, uintptr_t* arguments) loadLibrary (t, static_cast(t->m->classpath)->libraryPath, - RUNTIME_ARRAY_BODY(n), not absolute, false); + RUNTIME_ARRAY_BODY(n), not absolute, true); } // only safe to call during bootstrap when there's only one thread @@ -1698,6 +1785,15 @@ intercept(Thread* t, object c, const char* name, const char* spec, object runtimeData = getMethodRuntimeData(t, m); set(t, runtimeData, MethodRuntimeDataNative, native); + } else { + // If we can't find the method, just ignore it, since ProGuard may + // have stripped it out as unused. Otherwise, the code below can + // be uncommented for debugging purposes. + + // fprintf(stderr, "unable to find %s%s in %s\n", + // name, spec, &byteArrayBody(t, className(t, c), 0)); + + // abort(t); } } @@ -1765,60 +1861,6 @@ interceptFileOperations(Thread* t) } } - { object zipEntryClass = resolveClass - (t, root(t, Machine::BootLoader), "java/util/zip/ZipEntry", false); - - if (zipEntryClass) { - PROTECT(t, zipEntryClass); - - object zipEntryNameField = findFieldInClass2 - (t, zipEntryClass, "name", "Ljava/lang/String;"); - - if (zipEntryNameField) { - cp->zipEntryNameField = fieldOffset(t, zipEntryNameField); - - object zipEntryTimeField = findFieldInClass2 - (t, zipEntryClass, "time", "J"); - - if (zipEntryTimeField) { - cp->zipEntryTimeField = fieldOffset(t, zipEntryTimeField); - - object zipEntryCrcField = findFieldInClass2 - (t, zipEntryClass, "crc", "J"); - - if (zipEntryCrcField) { - cp->zipEntryCrcField = fieldOffset(t, zipEntryCrcField); - - object zipEntrySizeField = findFieldInClass2 - (t, zipEntryClass, "size", "J"); - - if (zipEntrySizeField) { - cp->zipEntrySizeField = fieldOffset(t, zipEntrySizeField); - - object zipEntryCsizeField = findFieldInClass2 - (t, zipEntryClass, "csize", "J"); - - if (zipEntryCsizeField) { - cp->zipEntryCsizeField = fieldOffset(t, zipEntryCsizeField); - - object zipEntryMethodField = findFieldInClass2 - (t, zipEntryClass, "method", "I"); - - if (zipEntryMethodField) { - cp->zipEntryMethodField = fieldOffset - (t, zipEntryMethodField); - - intercept(t, zipEntryClass, "initFields", "(J)V", - voidPointer(initializeZipEntryFields)); - } - } - } - } - } - } - } - } - { object zipFileClass = resolveClass (t, root(t, Machine::BootLoader), "java/util/zip/ZipFile", false); @@ -1831,19 +1873,22 @@ interceptFileOperations(Thread* t) if (zipFileJzfileField) { cp->zipFileJzfileField = fieldOffset(t, zipFileJzfileField); - intercept(t, zipFileClass, "open", "(Ljava/lang/String;IJ)J", + intercept(t, zipFileClass, "open", "(Ljava/lang/String;IJZ)J", voidPointer(openZipFile)); intercept(t, zipFileClass, "getTotal", "(J)I", voidPointer(getZipFileEntryCount)); - intercept(t, zipFileClass, "getEntry", "(JLjava/lang/String;Z)J", + intercept(t, zipFileClass, "getEntry", "(J[BZ)J", voidPointer(getZipFileEntry)); + intercept(t, zipFileClass, "getEntryBytes", "(JI)[B", + voidPointer(getZipFileEntryBytes)); + intercept(t, zipFileClass, "getNextEntry", "(JI)J", voidPointer(getNextZipFileEntry)); - intercept(t, zipFileClass, "getMethod", "(J)I", + intercept(t, zipFileClass, "getEntryMethod", "(J)I", voidPointer(getZipFileEntryMethod)); intercept(t, zipFileClass, "freeEntry", "(JJ)V", @@ -1852,10 +1897,10 @@ interceptFileOperations(Thread* t) intercept(t, zipFileClass, "read", "(JJJ[BII)I", voidPointer(readZipFileEntry)); - intercept(t, zipFileClass, "getCSize", "(J)J", + intercept(t, zipFileClass, "getEntryCSize", "(J)J", voidPointer(getZipFileEntryCompressedSize)); - intercept(t, zipFileClass, "getSize", "(J)J", + intercept(t, zipFileClass, "getEntrySize", "(J)J", voidPointer(getZipFileEntryUncompressedSize)); intercept(t, zipFileClass, "getZipMessage", "(J)Ljava/lang/String;", @@ -2176,6 +2221,14 @@ interruptLock(Thread* t, object thread) return threadInterruptLock(t, thread); } +void +clearInterrupted(Thread* t) +{ + monitorAcquire(t, local::interruptLock(t, t->javaThread)); + threadInterrupted(t, t->javaThread) = false; + monitorRelease(t, local::interruptLock(t, t->javaThread)); +} + bool pipeAvailable(int fd, int* available) { @@ -2271,6 +2324,24 @@ Avian_sun_misc_Unsafe_registerNatives // ignore } +extern "C" JNIEXPORT void +Avian_sun_misc_Perf_registerNatives +(Thread*, object, uintptr_t*) +{ + // ignore +} + +extern "C" JNIEXPORT int64_t +Avian_sun_misc_Perf_createLong +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast + (t->m->processor->invoke + (t, resolveMethod + (t, root(t, Machine::BootLoader), "java/nio/ByteBuffer", "allocate", + "(I)Ljava/nio/ByteBuffer;"), 0, 8)); +} + extern "C" JNIEXPORT int64_t Avian_sun_misc_Unsafe_addressSize (Thread*, object, uintptr_t*) @@ -2520,13 +2591,20 @@ Avian_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF } extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_getBoolean +Avian_sun_misc_Unsafe_getByte (Thread*, object, uintptr_t* arguments) { object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - return cast(o, offset); + return cast(o, offset); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getBoolean +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getByte(t, method, arguments); } extern "C" JNIEXPORT void JNICALL @@ -2576,6 +2654,13 @@ Avian_sun_misc_Unsafe_putObjectVolatile storeLoadMemoryBarrier(); } +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putOrderedObject +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putObjectVolatile(t, method, arguments); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_compareAndSwapInt (Thread*, object, uintptr_t* arguments) @@ -2671,12 +2756,15 @@ Avian_sun_misc_Unsafe_park if (time <= 0) { return; } - } else { - time /= 1000 * 1000; + } else if (time) { + // if not absolute, interpret time as nanoseconds, but make sure + // it doesn't become zero when we convert to milliseconds, since + // zero is interpreted as infinity below + time = (time / (1000 * 1000)) + 1; } monitorAcquire(t, local::interruptLock(t, t->javaThread)); - while (time > 0 + while (time >= 0 and (not (threadUnparked(t, t->javaThread) or monitorWait (t, local::interruptLock(t, t->javaThread), time)))) @@ -2684,11 +2772,41 @@ Avian_sun_misc_Unsafe_park int64_t now = t->m->system->now(); time -= now - then; then = now; + + if (time == 0) { + break; + } } threadUnparked(t, t->javaThread) = false; monitorRelease(t, local::interruptLock(t, t->javaThread)); } +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_copyMemory +(Thread* t, object, uintptr_t* arguments) +{ + object srcBase = reinterpret_cast(arguments[1]); + int64_t srcOffset; memcpy(&srcOffset, arguments + 2, 8); + object dstBase = reinterpret_cast(arguments[4]); + int64_t dstOffset; memcpy(&dstOffset, arguments + 5, 8); + int64_t count; memcpy(&count, arguments + 7, 8); + + PROTECT(t, srcBase); + PROTECT(t, dstBase); + + ACQUIRE(t, t->m->referenceLock); + + void* src = srcBase + ? &cast(srcBase, srcOffset) + : reinterpret_cast(srcOffset); + + void* dst = dstBase + ? &cast(dstBase, dstOffset) + : reinterpret_cast(dstOffset); + + memcpy(dst, src, count); +} + extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_monitorEnter (Thread* t, object, uintptr_t* arguments) @@ -2877,22 +2995,22 @@ jvmInitProperties(Thread* t, uintptr_t* arguments) GetCurrentDirectory(MAX_PATH, buffer); local::setProperty(t, method, *properties, "user.dir", buffer); -#else +#else // not PLATFORM_WINDOWS local::setProperty(t, method, *properties, "line.separator", "\n"); local::setProperty(t, method, *properties, "file.separator", "/"); local::setProperty(t, method, *properties, "path.separator", ":"); # ifdef __APPLE__ local::setProperty(t, method, *properties, "os.name", "Mac OS X"); -# else +# else // not __APPLE__ local::setProperty(t, method, *properties, "os.name", "Linux"); -# endif +# endif // not __APPLE__ local::setProperty(t, method, *properties, "java.io.tmpdir", "/tmp"); local::setProperty(t, method, *properties, "user.home", getenv("HOME")); char buffer[PATH_MAX]; local::setProperty(t, method, *properties, "user.dir", getcwd(buffer, PATH_MAX)); -#endif +#endif // not PLATFORM_WINDOWS local::setProperty(t, method, *properties, "java.protocol.handler.pkgs", "avian"); @@ -2908,6 +3026,11 @@ jvmInitProperties(Thread* t, uintptr_t* arguments) (t, method, *properties, "sun.boot.library.path", static_cast(t->m->classpath)->libraryPath); + local::setProperty + (t, method, *properties, "sun.boot.class.path", + static_cast + (systemClassLoaderFinder(t, root(t, Machine::BootLoader)))->path()); + local::setProperty(t, method, *properties, "file.encoding", "ASCII"); #ifdef ARCH_x86_32 local::setProperty(t, method, *properties, "os.arch", "x86"); @@ -3074,7 +3197,7 @@ jvmFillInStackTrace(Thread* t, uintptr_t* arguments) { jobject throwable = reinterpret_cast(arguments[0]); - object trace = getTrace(t, 1); + object trace = getTrace(t, 2); set(t, *throwable, ThrowableTrace, trace); return 1; @@ -3244,9 +3367,8 @@ jvmInterrupt(Thread* t, uintptr_t* arguments) Thread* p = reinterpret_cast(threadPeer(t, *thread)); if (p) { interrupt(t, p); - } else { - threadInterrupted(t, *thread) = true; } + threadInterrupted(t, *thread) = true; monitorRelease(t, local::interruptLock(t, *thread)); return 1; @@ -3768,10 +3890,9 @@ EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name, } extern "C" JNIEXPORT jclass JNICALL -EXPORT(JVM_FindClassFromBootLoader)(Thread* t, const char* name, - jboolean throwError) +JVM_FindClassFromBootLoader(Thread* t, const char* name) { - return EXPORT(JVM_FindClassFromClassLoader)(t, name, false, 0, throwError); + return EXPORT(JVM_FindClassFromClassLoader)(t, name, false, 0, false); } extern "C" JNIEXPORT jclass JNICALL @@ -4199,9 +4320,9 @@ jvmGetClassDeclaredMethods(Thread* t, uintptr_t* arguments) } object method = makeJmethod - (t, true, *c, i, name, returnType, parameterTypes, exceptionTypes, + (t, true, 0, *c, i, name, returnType, parameterTypes, exceptionTypes, methodFlags(t, vmMethod), signature, 0, annotationTable, 0, - annotationDefault, 0, 0, 0, 0, 0); + annotationDefault, 0, 0, 0); assert(t, ai < objectArrayLength(t, array)); @@ -4288,8 +4409,8 @@ jvmGetClassDeclaredFields(Thread* t, uintptr_t* arguments) } object field = makeJfield - (t, true, *c, i, name, type, fieldFlags - (t, vmField), signature, 0, annotationTable, 0, 0, 0, 0, 0, 0); + (t, true, 0, *c, i, name, type, fieldFlags + (t, vmField), signature, 0, annotationTable, 0, 0, 0, 0); assert(t, ai < objectArrayLength(t, array)); @@ -4379,8 +4500,8 @@ jvmGetClassDeclaredConstructors(Thread* t, uintptr_t* arguments) } object method = makeJconstructor - (t, true, *c, i, parameterTypes, exceptionTypes, methodFlags - (t, vmMethod), signature, 0, annotationTable, 0, 0, 0, 0, 0); + (t, true, 0, *c, i, parameterTypes, exceptionTypes, methodFlags + (t, vmMethod), signature, 0, annotationTable, 0, 0, 0, 0); assert(t, ai < objectArrayLength(t, array)); @@ -5152,9 +5273,11 @@ jboolean JNICALL GetBoolAttribute(Thread* t, jmmBoolAttribute attribute) { const unsigned JMM_THREAD_CPU_TIME = 24; + const unsigned JMM_THREAD_ALLOCATED_MEMORY = 25; switch (attribute) { case JMM_THREAD_CPU_TIME: + case JMM_THREAD_ALLOCATED_MEMORY: return false; default: @@ -5237,13 +5360,19 @@ extern "C" JNIEXPORT jobjectArray JNICALL EXPORT(JVM_GetThreadStateNames)(JNIEnv*, jint, jintArray) { abort(); } extern "C" JNIEXPORT void JNICALL -EXPORT(JVM_GetVersionInfo)(JNIEnv*, local::jvm_version_info*, size_t) -{ abort(); } +EXPORT(JVM_GetVersionInfo)(JNIEnv*, local::jvm_version_info* info, size_t size) +{ + memset(info, 0, size); + info->jvm_version = 0x01070000; +} extern "C" JNIEXPORT jboolean JNICALL EXPORT(JVM_CX8Field)(JNIEnv*, jobject*, jfieldID*, jlong, jlong) { abort(); } +extern "C" JNIEXPORT void JNICALL +EXPORT(JVM_SetNativeThreadName)(JNIEnv*, jobject, jstring) { abort(); } + } // namespace local } // namespace diff --git a/src/compile.cpp b/src/compile.cpp index c6c4f4aba1..fd3f3520e7 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -612,7 +612,7 @@ class MyStackWalker: public Processor::StackWalker { } void next() { - expect(t, count_ <= StackSizeInWords); + expect(t, count_ <= stackSizeInWords(t)); switch (state) { case Continuation: @@ -6237,8 +6237,10 @@ truncateIntArray(Thread* t, object array, unsigned length) PROTECT(t, array); object newArray = makeIntArray(t, length); - memcpy(&intArrayBody(t, newArray, 0), &intArrayBody(t, array, 0), - length * 4); + if (length) { + memcpy(&intArrayBody(t, newArray, 0), &intArrayBody(t, array, 0), + length * 4); + } return newArray; } @@ -6251,8 +6253,10 @@ truncateArray(Thread* t, object array, unsigned length) PROTECT(t, array); object newArray = makeArray(t, length); - memcpy(&arrayBody(t, newArray, 0), &arrayBody(t, array, 0), - length * BytesPerWord); + if (length) { + memcpy(&arrayBody(t, newArray, 0), &arrayBody(t, array, 0), + length * BytesPerWord); + } return newArray; } @@ -6265,9 +6269,11 @@ truncateLineNumberTable(Thread* t, object table, unsigned length) PROTECT(t, table); object newTable = makeLineNumberTable(t, length); - memcpy(&lineNumberTableBody(t, newTable, 0), - &lineNumberTableBody(t, table, 0), - length * sizeof(uint64_t)); + if (length) { + memcpy(&lineNumberTableBody(t, newTable, 0), + &lineNumberTableBody(t, table, 0), + length * sizeof(uint64_t)); + } return newTable; } @@ -8325,7 +8331,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments) uintptr_t stackLimit = t->stackLimit; uintptr_t stackPosition = reinterpret_cast(&t); if (stackLimit == 0) { - t->stackLimit = stackPosition - StackSizeInBytes; + t->stackLimit = stackPosition - t->m->stackSizeInBytes; } else if (stackPosition < stackLimit) { throwNew(t, Machine::StackOverflowErrorType); } diff --git a/src/interpret.cpp b/src/interpret.cpp index d38e89b16b..439f4ca069 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -40,7 +40,7 @@ class Thread: public vm::Thread { unsigned sp; int frame; object code; - uintptr_t stack[StackSizeInWords]; + uintptr_t stack[0]; }; inline void @@ -50,7 +50,7 @@ pushObject(Thread* t, object o) fprintf(stderr, "push object %p at %d\n", o, t->sp); } - assert(t, t->sp + 1 < StackSizeInWords / 2); + assert(t, t->sp + 1 < stackSizeInWords(t) / 2); t->stack[(t->sp * 2) ] = ObjectTag; t->stack[(t->sp * 2) + 1] = reinterpret_cast(o); ++ t->sp; @@ -63,7 +63,7 @@ pushInt(Thread* t, uint32_t v) fprintf(stderr, "push int %d at %d\n", v, t->sp); } - assert(t, t->sp + 1 < StackSizeInWords / 2); + assert(t, t->sp + 1 < stackSizeInWords(t) / 2); t->stack[(t->sp * 2) ] = IntTag; t->stack[(t->sp * 2) + 1] = v; ++ t->sp; @@ -156,7 +156,7 @@ peekObject(Thread* t, unsigned index) index); } - assert(t, index < StackSizeInWords / 2); + assert(t, index < stackSizeInWords(t) / 2); assert(t, t->stack[index * 2] == ObjectTag); return *reinterpret_cast(t->stack + (index * 2) + 1); } @@ -170,7 +170,7 @@ peekInt(Thread* t, unsigned index) index); } - assert(t, index < StackSizeInWords / 2); + assert(t, index < stackSizeInWords(t) / 2); assert(t, t->stack[index * 2] == IntTag); return t->stack[(index * 2) + 1]; } @@ -226,7 +226,7 @@ inline object* pushReference(Thread* t, object o) { if (o) { - expect(t, t->sp + 1 < StackSizeInWords / 2); + expect(t, t->sp + 1 < stackSizeInWords(t) / 2); pushObject(t, o); return reinterpret_cast(t->stack + ((t->sp - 1) * 2) + 1); } else { @@ -405,7 +405,7 @@ checkStack(Thread* t, object method) + codeMaxLocals(t, methodCode(t, method)) + FrameFootprint + codeMaxStack(t, methodCode(t, method)) - > StackSizeInWords / 2)) + > stackSizeInWords(t) / 2)) { throwNew(t, Machine::StackOverflowErrorType); } @@ -2879,7 +2879,7 @@ class MyProcessor: public Processor { virtual vm::Thread* makeThread(Machine* m, object javaThread, vm::Thread* parent) { - Thread* t = new (m->heap->allocate(sizeof(Thread))) + Thread* t = new (m->heap->allocate(sizeof(Thread) + m->stackSizeInBytes)) Thread(m, javaThread, parent); t->init(); return t; @@ -2996,7 +2996,7 @@ class MyProcessor: public Processor { assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 - > StackSizeInWords / 2)) + > stackSizeInWords(t) / 2)) { throwNew(t, Machine::StackOverflowErrorType); } @@ -3020,7 +3020,7 @@ class MyProcessor: public Processor { assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 - > StackSizeInWords / 2)) + > stackSizeInWords(t) / 2)) { throwNew(t, Machine::StackOverflowErrorType); } @@ -3043,7 +3043,7 @@ class MyProcessor: public Processor { or t->state == Thread::ExclusiveState); if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false) - > StackSizeInWords / 2)) + > stackSizeInWords(t) / 2)) { throwNew(t, Machine::StackOverflowErrorType); } diff --git a/src/jnienv.cpp b/src/jnienv.cpp index f815497078..ffc0937789 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3269,6 +3269,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) local::JavaVMInitArgs* a = static_cast(args); unsigned heapLimit = 0; + unsigned stackLimit = 0; const char* bootLibrary = 0; const char* classpath = 0; const char* javaHome = AVIAN_JAVA_HOME; @@ -3285,6 +3286,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) const char* p = a->options[i].optionString + 2; if (strncmp(p, "mx", 2) == 0) { heapLimit = local::parseSize(p + 2); + } else if (strncmp(p, "ss", 2) == 0) { + stackLimit = local::parseSize(p + 2); } else if (strncmp(p, BOOTCLASSPATH_PREPEND_OPTION ":", sizeof(BOOTCLASSPATH_PREPEND_OPTION)) == 0) { @@ -3327,6 +3330,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) } if (heapLimit == 0) heapLimit = 128 * 1024 * 1024; + + if (stackLimit == 0) stackLimit = 128 * 1024; if (classpath == 0) classpath = "."; @@ -3377,9 +3382,9 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) *(argumentPointer++) = a->options[i].optionString; } - *m = new (h->allocate(sizeof(Machine))) - Machine - (s, h, bf, af, p, c, properties, propertyCount, arguments, a->nOptions); + *m = new (h->allocate(sizeof(Machine))) Machine + (s, h, bf, af, p, c, properties, propertyCount, arguments, a->nOptions, + stackLimit); *t = p->makeThread(*m, 0, 0); diff --git a/src/machine.cpp b/src/machine.cpp index 258c873ec2..0fab1f3b1b 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1164,9 +1164,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) unsigned size = fieldSize(t, code); if (flags & ACC_STATIC) { - unsigned excess = (staticOffset % size) % BytesPerWord; - if (excess) { - staticOffset += BytesPerWord - excess; + while (staticOffset % size) { + ++ staticOffset; } fieldOffset(t, field) = staticOffset; @@ -1205,9 +1204,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) for (unsigned i = 0, offset = 0; i < staticCount; ++i) { unsigned size = fieldSize(t, RUNTIME_ARRAY_BODY(staticTypes)[i]); - unsigned excess = offset % size; - if (excess) { - offset += BytesPerWord - excess; + while (offset % size) { + ++ offset; } unsigned value = intArrayBody(t, staticValueTable, i); @@ -2457,7 +2455,8 @@ namespace vm { Machine::Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder, Processor* processor, Classpath* classpath, const char** properties, unsigned propertyCount, - const char** arguments, unsigned argumentCount): + const char** arguments, unsigned argumentCount, + unsigned stackSizeInBytes): vtable(&javaVMVTable), system(system), heapClient(new (heap->allocate(sizeof(HeapClient))) @@ -2480,6 +2479,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, liveCount(0), daemonCount(0), fixedFootprint(0), + stackSizeInBytes(stackSizeInBytes), localThread(0), stateLock(0), heapLock(0), diff --git a/src/machine.h b/src/machine.h index f163214917..eea9cc506b 100644 --- a/src/machine.h +++ b/src/machine.h @@ -112,9 +112,6 @@ const unsigned ThreadBackupHeapSizeInBytes = 2 * 1024; const unsigned ThreadBackupHeapSizeInWords = ThreadBackupHeapSizeInBytes / BytesPerWord; -const unsigned StackSizeInBytes = 128 * 1024; -const unsigned StackSizeInWords = StackSizeInBytes / BytesPerWord; - const unsigned ThreadHeapPoolSize = 64; const unsigned FixedFootprintThresholdInBytes @@ -1281,7 +1278,7 @@ class Machine { Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder, Processor* processor, Classpath* classpath, const char** properties, unsigned propertyCount, const char** arguments, - unsigned argumentCount); + unsigned argumentCount, unsigned stackSizeInBytes); ~Machine() { dispose(); @@ -1310,6 +1307,7 @@ class Machine { unsigned liveCount; unsigned daemonCount; unsigned fixedFootprint; + unsigned stackSizeInBytes; System::Local* localThread; System::Monitor* stateLock; System::Monitor* heapLock; @@ -1579,6 +1577,9 @@ class Classpath { virtual object makeThread(Thread* t, Thread* parent) = 0; + virtual void + clearInterrupted(Thread* t) = 0; + virtual void runThread(Thread* t) = 0; @@ -1639,6 +1640,12 @@ objectClass(Thread*, object o) return mask(cast(o, 0)); } +inline unsigned +stackSizeInWords(Thread* t) +{ + return t->m->stackSizeInBytes / BytesPerWord; +} + void enter(Thread* t, Thread::State state); @@ -3211,6 +3218,7 @@ wait(Thread* t, object o, int64_t milliseconds) if (interrupted) { if (t->m->alive or (t->flags & Thread::DaemonFlag) == 0) { + t->m->classpath->clearInterrupted(t); throwNew(t, Machine::InterruptedExceptionType); } else { throw_(t, root(t, Machine::Shutdown)); diff --git a/src/main.cpp b/src/main.cpp index a84630b68c..f5358e985c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -143,6 +143,7 @@ usageAndExit(const char* name) (stderr, "usage: %s\n" "\t[{-cp|-classpath} ]\n" "\t[-Xmx]\n" + "\t[-Xss]\n" "\t[-Xbootclasspath/p:]\n" "\t[-Xbootclasspath:]\n" "\t[-Xbootclasspath/a:]\n" diff --git a/src/openjdk/my_java_props_macosx.c b/src/openjdk/my_java_props_macosx.c new file mode 100644 index 0000000000..8a1850010f --- /dev/null +++ b/src/openjdk/my_java_props_macosx.c @@ -0,0 +1,28 @@ +#include "java_props_macosx.h" + +PreferredToolkit +getPreferredToolkit() +{ + return unset; +} + +void +setOSNameAndVersion(java_props_t* props) +{ + props->os_name = strdup("iOS"); + props->os_version = strdup("Unknown"); +} + +void +setProxyProperties(java_props_t* props) +{ + // ignore +} + +char* +setupMacOSXLocale(int cat) +{ + return 0; +} + +char* environ[0]; diff --git a/src/posix.cpp b/src/posix.cpp index 074c6b379c..35d2d6b7b1 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -122,8 +122,7 @@ pathOfExecutable(System* s, const char** retBuf, unsigned* size) const bool Verbose = false; -const unsigned Waiting = 1 << 0; -const unsigned Notified = 1 << 1; +const unsigned Notified = 1 << 0; class MySystem: public System { public: @@ -256,7 +255,14 @@ class MySystem: public System { } void append(Thread* t) { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + if (last) { + expect(s, t != last); last->next = t; last = t; } else { @@ -271,6 +277,7 @@ class MySystem: public System { if (current == first) { first = t->next; } else { + expect(s, previous != t->next); previous->next = t->next; } @@ -286,6 +293,12 @@ class MySystem: public System { current = current->next; } } + +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif } virtual void wait(System::Thread* context, int64_t time) { @@ -308,13 +321,13 @@ class MySystem: public System { { ACQUIRE(t->mutex); + expect(s, (t->flags & Notified) == 0); + interrupted = t->r->interrupted(); if (interrupted and clearInterrupted) { t->r->setInterrupted(false); } - t->flags |= Waiting; - append(t); depth = this->depth; @@ -343,14 +356,22 @@ class MySystem: public System { } notified = ((t->flags & Notified) != 0); - - t->flags = 0; } pthread_mutex_lock(&mutex); + { ACQUIRE(t->mutex); + t->flags = 0; + } + if (not notified) { remove(t); + } else { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif } t->next = 0; @@ -380,6 +401,7 @@ class MySystem: public System { Thread* t = first; first = first->next; if (t == last) { + expect(s, first == 0); last = 0; } diff --git a/src/types.def b/src/types.def index 9b19ccd9bc..31d96404a8 100644 --- a/src/types.def +++ b/src/types.def @@ -220,6 +220,8 @@ (type negativeArraySizeException java/lang/NegativeArraySizeException) +(type reflectiveOperationException java/lang/ReflectiveOperationException) + (type classCastException java/lang/ClassCastException) (type classNotFoundException java/lang/ClassNotFoundException) diff --git a/src/windows.cpp b/src/windows.cpp index 42a79d3024..37c9251726 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -215,6 +215,12 @@ class MySystem: public System { } void append(Thread* t) { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + if (last) { last->next = t; last = t; @@ -245,6 +251,12 @@ class MySystem: public System { current = current->next; } } + +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif } virtual void wait(System::Thread* context, int64_t time) { @@ -270,6 +282,8 @@ class MySystem: public System { { ACQUIRE(s, t->mutex); + expect(s, (t->flags & Notified) == 0); + interrupted = t->r->interrupted(); if (interrupted and clearInterrupted) { t->r->setInterrupted(false); @@ -306,15 +320,23 @@ class MySystem: public System { } notified = ((t->flags & Notified) != 0); - - t->flags = 0; } r = WaitForSingleObject(mutex, INFINITE); assert(s, r == WAIT_OBJECT_0); + { ACQUIRE(s, t->mutex); + t->flags = 0; + } + if (not notified) { remove(t); + } else { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif } t->next = 0; @@ -346,6 +368,7 @@ class MySystem: public System { Thread* t = first; first = first->next; if (t == last) { + expect(s, first == 0); last = 0; }