diff --git a/classpath/avian/Addendum.java b/classpath/avian/Addendum.java index b363ecfc7c..b5c86d9008 100644 --- a/classpath/avian/Addendum.java +++ b/classpath/avian/Addendum.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/ClassAddendum.java b/classpath/avian/ClassAddendum.java index 276be33fe9..48ac3bdd07 100644 --- a/classpath/avian/ClassAddendum.java +++ b/classpath/avian/ClassAddendum.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index 1d2ad9370e..a445114022 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/Continuations.java b/classpath/avian/Continuations.java index 4ca98d86bd..a2d4948c8b 100644 --- a/classpath/avian/Continuations.java +++ b/classpath/avian/Continuations.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/Machine.java b/classpath/avian/Machine.java index cbc62efae6..6115cf0c37 100644 --- a/classpath/avian/Machine.java +++ b/classpath/avian/Machine.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -10,8 +10,16 @@ package avian; +import sun.misc.Unsafe; + public abstract class Machine { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + public static native void dumpHeap(String outputFile); + public static Unsafe getUnsafe() { + return unsafe; + } + } diff --git a/classpath/avian/MethodAddendum.java b/classpath/avian/MethodAddendum.java index 597c169179..e2ae385b81 100644 --- a/classpath/avian/MethodAddendum.java +++ b/classpath/avian/MethodAddendum.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/OpenJDK.java b/classpath/avian/OpenJDK.java index de9c6f1f40..95248b2398 100644 --- a/classpath/avian/OpenJDK.java +++ b/classpath/avian/OpenJDK.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/Stream.java b/classpath/avian/Stream.java index 14e6fc5773..a0762e6213 100644 --- a/classpath/avian/Stream.java +++ b/classpath/avian/Stream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/SystemClassLoader.java b/classpath/avian/SystemClassLoader.java index defb9d490a..5c228cd9c1 100644 --- a/classpath/avian/SystemClassLoader.java +++ b/classpath/avian/SystemClassLoader.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/VMClass.java b/classpath/avian/VMClass.java index 5a3fdc662f..c3e87353b5 100644 --- a/classpath/avian/VMClass.java +++ b/classpath/avian/VMClass.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/VMField.java b/classpath/avian/VMField.java index 8df0d426c5..2e986321da 100644 --- a/classpath/avian/VMField.java +++ b/classpath/avian/VMField.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/VMMethod.java b/classpath/avian/VMMethod.java index e68d725242..843dd6012e 100644 --- a/classpath/avian/VMMethod.java +++ b/classpath/avian/VMMethod.java @@ -24,4 +24,8 @@ public class VMMethod { public MethodAddendum addendum; public VMClass class_; public Object code; + + public boolean hasAnnotations() { + return addendum != null && addendum.annotationTable != null; + } } diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 5b723114ae..86020f57c8 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -48,7 +48,6 @@ # define R_OK 4 # else # define OPEN _wopen -# define CREAT _wcreat # endif # define GET_CHARS GetStringChars @@ -71,7 +70,6 @@ typedef wchar_t char_t; # define STRUCT_STAT struct stat # define MKDIR mkdir # define CHMOD chmod -# define CREAT creat # define UNLINK unlink # define RENAME rename # define OPEN_MASK 0 @@ -102,12 +100,6 @@ OPEN(string_t path, int mask, int mode) return -1; } } - -inline int -CREAT(string_t path, int mode) -{ - return OPEN(path, _O_CREAT, mode); -} #endif inline bool @@ -407,21 +399,26 @@ Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path) } } -extern "C" JNIEXPORT void JNICALL +extern "C" JNIEXPORT jboolean JNICALL Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path) { + bool result = false; string_t chars = getChars(e, path); if (chars) { if (not exists(chars)) { - int fd = CREAT(chars, 0600); + int fd = OPEN(chars, O_CREAT | O_WRONLY | O_EXCL, 0600); if (fd == -1) { - throwNewErrno(e, "java/io/IOException"); + if (errno != EEXIST) { + throwNewErrno(e, "java/io/IOException"); + } } else { + result = true; doClose(e, fd); } } releaseChars(e, path, chars); } + return result; } extern "C" JNIEXPORT void JNICALL diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index bb087560fe..3cad9680a3 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -631,6 +631,36 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, return r; } +// System.getEnvironment() implementation +// TODO: For Win32, replace usage of deprecated _environ and add Unicode +// support (neither of which is likely to be of great importance). +#ifdef AVIAN_IOS +namespace { + const char* environ[] = { 0 }; +} +#elif defined __APPLE__ +# include +# define environ (*_NSGetEnviron()) +#else +extern char** environ; +#endif +extern "C" JNIEXPORT jobjectArray JNICALL +Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) { + int length; + for (length = 0; environ[length] != 0; ++length) ; + + jobjectArray stringArray = + env->NewObjectArray(length, env->FindClass("java/lang/String"), + env->NewStringUTF("")); + + for (int i = 0; i < length; i++) { + jobject varString = env->NewStringUTF(environ[i]); + env->SetObjectArrayElement(stringArray, i, varString); + } + + return stringArray; +} + extern "C" JNIEXPORT jlong JNICALL Java_java_lang_System_currentTimeMillis(JNIEnv*, jclass) { diff --git a/classpath/java-net.cpp b/classpath/java-net.cpp index 20d853adc2..1cfea1fbc2 100644 --- a/classpath/java-net.cpp +++ b/classpath/java-net.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java-util-zip.cpp b/classpath/java-util-zip.cpp index f883e528bc..6fb471bdfd 100644 --- a/classpath/java-util-zip.cpp +++ b/classpath/java-util-zip.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -76,7 +76,9 @@ Java_java_util_zip_Inflater_inflate int r = inflate(s, Z_SYNC_FLUSH); jint resultArray[3] - = { r, inputLength - s->avail_in, outputLength - s->avail_out }; + = { r, + static_cast(inputLength - s->avail_in), + static_cast(outputLength - s->avail_out) }; free(in); @@ -147,7 +149,9 @@ Java_java_util_zip_Deflater_deflate int r = deflate(s, finish ? Z_FINISH : Z_NO_FLUSH); jint resultArray[3] - = { r, inputLength - s->avail_in, outputLength - s->avail_out }; + = { r, + static_cast(inputLength - s->avail_in), + static_cast(outputLength - s->avail_out) }; free(in); diff --git a/classpath/java-util.cpp b/classpath/java-util.cpp index b880ff2d95..4c0a73161c 100644 --- a/classpath/java-util.cpp +++ b/classpath/java-util.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/BufferedInputStream.java b/classpath/java/io/BufferedInputStream.java index 67ac256a21..3f03a7c743 100644 --- a/classpath/java/io/BufferedInputStream.java +++ b/classpath/java/io/BufferedInputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/BufferedReader.java b/classpath/java/io/BufferedReader.java index 2618dfdbd6..5b90b62012 100644 --- a/classpath/java/io/BufferedReader.java +++ b/classpath/java/io/BufferedReader.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/ByteArrayOutputStream.java b/classpath/java/io/ByteArrayOutputStream.java index f0668da2da..0960dd3008 100644 --- a/classpath/java/io/ByteArrayOutputStream.java +++ b/classpath/java/io/ByteArrayOutputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index bfae0da9b6..86e093495b 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -35,11 +35,16 @@ public class File implements Serializable { this(parent.getPath() + FileSeparator + child); } - public static File createTempFile(String prefix, String suffix) { + public static File createTempFile(String prefix, String suffix) + throws IOException + { return createTempFile(prefix, suffix, null); } - public static File createTempFile(String prefix, String suffix, File directory) { + public static File createTempFile(String prefix, String suffix, + File directory) + throws IOException + { if(directory == null) { directory = new File(System.getProperty("java.io.tmpdir")); } @@ -199,15 +204,10 @@ public class File implements Serializable { } } - private static native void createNewFile(String path) throws IOException; + private static native boolean createNewFile(String path) throws IOException; - public boolean createNewFile() { - try { - createNewFile(path); - return true; - } catch (IOException e) { - return false; - } + public boolean createNewFile() throws IOException { + return createNewFile(path); } public static native void delete(String path) throws IOException; diff --git a/classpath/java/io/FileInputStream.java b/classpath/java/io/FileInputStream.java index 9c614e2f7e..d3cd3cd08e 100644 --- a/classpath/java/io/FileInputStream.java +++ b/classpath/java/io/FileInputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -16,6 +16,7 @@ public class FileInputStream extends InputStream { // } private int fd; + private int remaining; public FileInputStream(FileDescriptor fd) { this.fd = fd.value; @@ -23,12 +24,17 @@ public class FileInputStream extends InputStream { public FileInputStream(String path) throws IOException { fd = open(path); + remaining = (int) new File(path).length(); } public FileInputStream(File file) throws IOException { this(file.getPath()); } + public int available() throws IOException { + return remaining; + } + private static native int open(String path) throws IOException; private static native int read(int fd) throws IOException; @@ -39,7 +45,11 @@ public class FileInputStream extends InputStream { public static native void close(int fd) throws IOException; public int read() throws IOException { - return read(fd); + int c = read(fd); + if (c >= 0 && remaining > 0) { + -- remaining; + } + return c; } public int read(byte[] b, int offset, int length) throws IOException { @@ -51,7 +61,11 @@ public class FileInputStream extends InputStream { throw new ArrayIndexOutOfBoundsException(); } - return read(fd, b, offset, length); + int c = read(fd, b, offset, length); + if (c > 0 && remaining > 0) { + remaining -= c; + } + return c; } public void close() throws IOException { diff --git a/classpath/java/io/InputStream.java b/classpath/java/io/InputStream.java index 8e74c2db8d..ec29b52b7a 100644 --- a/classpath/java/io/InputStream.java +++ b/classpath/java/io/InputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/ObjectInputStream.java b/classpath/java/io/ObjectInputStream.java index 45bacc7380..b0f1ec0dd7 100644 --- a/classpath/java/io/ObjectInputStream.java +++ b/classpath/java/io/ObjectInputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/ObjectOutputStream.java b/classpath/java/io/ObjectOutputStream.java index 7e45f9d2cc..3f310128bd 100644 --- a/classpath/java/io/ObjectOutputStream.java +++ b/classpath/java/io/ObjectOutputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/PrintStream.java b/classpath/java/io/PrintStream.java index a720fac6a0..7bd27d06b1 100644 --- a/classpath/java/io/PrintStream.java +++ b/classpath/java/io/PrintStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/RandomAccessFile.java b/classpath/java/io/RandomAccessFile.java index cc3c41e757..b6e88dd00e 100644 --- a/classpath/java/io/RandomAccessFile.java +++ b/classpath/java/io/RandomAccessFile.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/Reader.java b/classpath/java/io/Reader.java index a09c8a24e9..2edfd70803 100644 --- a/classpath/java/io/Reader.java +++ b/classpath/java/io/Reader.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Character.java b/classpath/java/lang/Character.java index 88025280e8..3e7f1ed269 100644 --- a/classpath/java/lang/Character.java +++ b/classpath/java/lang/Character.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index 22b645793a..eb183260d6 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index e245e4c9f1..9f2a853c46 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Enum.java b/classpath/java/lang/Enum.java index cf1d033cc3..8d0d4756b0 100644 --- a/classpath/java/lang/Enum.java +++ b/classpath/java/lang/Enum.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Float.java b/classpath/java/lang/Float.java index d466cca2a3..408de61220 100644 --- a/classpath/java/lang/Float.java +++ b/classpath/java/lang/Float.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Package.java b/classpath/java/lang/Package.java index 5cd9b9547e..ed1e4e2985 100644 --- a/classpath/java/lang/Package.java +++ b/classpath/java/lang/Package.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided 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/java/lang/Runtime.java b/classpath/java/lang/Runtime.java index 88c8ba71e3..a3c00bcbbf 100644 --- a/classpath/java/lang/Runtime.java +++ b/classpath/java/lang/Runtime.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/RuntimePermission.java b/classpath/java/lang/RuntimePermission.java new file mode 100644 index 0000000000..a737444a6f --- /dev/null +++ b/classpath/java/lang/RuntimePermission.java @@ -0,0 +1,21 @@ +/* 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; + +import java.security.BasicPermission; + +public class RuntimePermission extends BasicPermission { + + public RuntimePermission(String name) { + super(name); + } + +} diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 83ce12dfa3..24a893ad87 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index 9506fb3457..859121c56d 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -17,12 +17,15 @@ import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileDescriptor; +import java.util.Map; +import java.util.Hashtable; import java.util.Properties; public abstract class System { private static final long NanoTimeBaseInMillis = currentTimeMillis(); private static Property properties; + private static Map environment; private static SecurityManager securityManager; // static { @@ -145,4 +148,37 @@ public abstract class System { this.next = next; } } + + public static String getenv(String name) throws NullPointerException, + SecurityException { + if (getSecurityManager() != null) { // is this allowed? + getSecurityManager(). + checkPermission(new RuntimePermission("getenv." + name)); + } + return getenv().get(name); + } + + public static Map getenv() throws SecurityException { + if (getSecurityManager() != null) { // is this allowed? + getSecurityManager().checkPermission(new RuntimePermission("getenv.*")); + } + + if (environment == null) { // build environment table + String[] vars = getEnvironment(); + environment = new Hashtable(vars.length); + for (String var : vars) { // parse name-value pairs + int equalsIndex = var.indexOf('='); + // null names and values are forbidden + if (equalsIndex != -1 && equalsIndex < var.length() - 1) { + environment.put(var.substring(0, equalsIndex), + var.substring(equalsIndex + 1)); + } + } + } + + return environment; + } + + /** Returns the native process environment. */ + private static native String[] getEnvironment(); } diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 4846287daf..539a709169 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -145,8 +145,8 @@ public class Thread implements Runnable { private static native boolean interrupt(long peer); - public boolean interrupted() { - return interrupted(peer); + public static boolean interrupted() { + return interrupted(currentThread().peer); } private static native boolean interrupted(long peer); diff --git a/classpath/java/lang/annotation/ElementType.java b/classpath/java/lang/annotation/ElementType.java new file mode 100644 index 0000000000..974fb10d64 --- /dev/null +++ b/classpath/java/lang/annotation/ElementType.java @@ -0,0 +1,22 @@ +/* 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.annotation; + +public enum ElementType { + ANNOTATION_TYPE, + CONSTRUCTOR, + FIELD, + LOCAL_VARIABLE, + METHOD, + PACKAGE, + PARAMETER, + TYPE +} diff --git a/classpath/java/lang/annotation/Target.java b/classpath/java/lang/annotation/Target.java new file mode 100644 index 0000000000..8d2550343c --- /dev/null +++ b/classpath/java/lang/annotation/Target.java @@ -0,0 +1,17 @@ +/* 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.annotation; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value=ElementType.ANNOTATION_TYPE) +public @interface Target { + public ElementType[] value(); +} diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index 524cb7613a..8d76a6258f 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/reflect/InvocationHandler.java b/classpath/java/lang/reflect/InvocationHandler.java index 9541797ad3..584ae0c430 100644 --- a/classpath/java/lang/reflect/InvocationHandler.java +++ b/classpath/java/lang/reflect/InvocationHandler.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/reflect/Member.java b/classpath/java/lang/reflect/Member.java index e5e74042c6..09b00759c4 100644 --- a/classpath/java/lang/reflect/Member.java +++ b/classpath/java/lang/reflect/Member.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2010, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 2c0addfaae..f90ed311a5 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -170,7 +170,7 @@ public class Method extends AccessibleObject implements Member { } public T getAnnotation(Class class_) { - if (vmMethod.addendum.annotationTable != null) { + if (vmMethod.hasAnnotations()) { Object[] table = (Object[]) vmMethod.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { Object[] a = (Object[]) table[i]; @@ -183,7 +183,7 @@ public class Method extends AccessibleObject implements Member { } public Annotation[] getAnnotations() { - if (vmMethod.addendum.annotationTable != null) { + if (vmMethod.hasAnnotations()) { Object[] table = (Object[]) vmMethod.addendum.annotationTable; Annotation[] array = new Annotation[table.length]; for (int i = 0; i < table.length; ++i) { diff --git a/classpath/java/lang/reflect/Proxy.java b/classpath/java/lang/reflect/Proxy.java index 2801f96618..cfc35a6077 100644 --- a/classpath/java/lang/reflect/Proxy.java +++ b/classpath/java/lang/reflect/Proxy.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -358,7 +358,7 @@ public class Proxy { int[] interfaceIndexes = new int[interfaces.length]; for (int i = 0; i < interfaces.length; ++i) { interfaceIndexes[i] = ConstantPool.addClass - (pool, interfaces[i].getName()); + (pool, interfaces[i].getName().replace('.', '/')); } Map virtualMap = new HashMap(); diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index d1c97450ec..f80e327997 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/net/URLConnection.java b/classpath/java/net/URLConnection.java index 0219fbe688..0ff8cacb4b 100644 --- a/classpath/java/net/URLConnection.java +++ b/classpath/java/net/URLConnection.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/net/URLStreamHandler.java b/classpath/java/net/URLStreamHandler.java index f3f64340c6..181f8868df 100644 --- a/classpath/java/net/URLStreamHandler.java +++ b/classpath/java/net/URLStreamHandler.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/Buffer.java b/classpath/java/nio/Buffer.java index c93c11f347..00e34c6932 100644 --- a/classpath/java/nio/Buffer.java +++ b/classpath/java/nio/Buffer.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/ByteBuffer.java b/classpath/java/nio/ByteBuffer.java index 2dee03f7d9..e63217f6ea 100644 --- a/classpath/java/nio/ByteBuffer.java +++ b/classpath/java/nio/ByteBuffer.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/Channels.java b/classpath/java/nio/channels/Channels.java index 849a16dffc..2e786e70b2 100644 --- a/classpath/java/nio/channels/Channels.java +++ b/classpath/java/nio/channels/Channels.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/SelectableChannel.java b/classpath/java/nio/channels/SelectableChannel.java index 734bce9fc8..0475f6adfe 100644 --- a/classpath/java/nio/channels/SelectableChannel.java +++ b/classpath/java/nio/channels/SelectableChannel.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/ServerSocketChannel.java b/classpath/java/nio/channels/ServerSocketChannel.java index 53e6eec36d..1b27e0f049 100644 --- a/classpath/java/nio/channels/ServerSocketChannel.java +++ b/classpath/java/nio/channels/ServerSocketChannel.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/SocketChannel.java b/classpath/java/nio/channels/SocketChannel.java index 65c9768d88..36fdf06c2e 100644 --- a/classpath/java/nio/channels/SocketChannel.java +++ b/classpath/java/nio/channels/SocketChannel.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/SocketSelector.java b/classpath/java/nio/channels/SocketSelector.java index a19d608918..82bcd6da41 100644 --- a/classpath/java/nio/channels/SocketSelector.java +++ b/classpath/java/nio/channels/SocketSelector.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/security/CodeSource.java b/classpath/java/security/CodeSource.java index 296f38c128..8ae784177a 100644 --- a/classpath/java/security/CodeSource.java +++ b/classpath/java/security/CodeSource.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/security/ProtectionDomain.java b/classpath/java/security/ProtectionDomain.java index 25673c8ee3..f17bf6810e 100644 --- a/classpath/java/security/ProtectionDomain.java +++ b/classpath/java/security/ProtectionDomain.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/AbstractCollection.java b/classpath/java/util/AbstractCollection.java index 54cd7288df..f7e06bad32 100644 --- a/classpath/java/util/AbstractCollection.java +++ b/classpath/java/util/AbstractCollection.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/AbstractQueue.java b/classpath/java/util/AbstractQueue.java new file mode 100644 index 0000000000..19fa46aaa1 --- /dev/null +++ b/classpath/java/util/AbstractQueue.java @@ -0,0 +1,60 @@ +/* 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.util; + +public abstract class AbstractQueue extends AbstractCollection implements Queue { + + protected AbstractQueue() { + super(); + } + + public boolean add(T element) { + if (offer(element)) { + return true; + } else { + throw new IllegalStateException(); + } + } + + public boolean addAll(Collection collection) { + if (collection == null) { + throw new NullPointerException(); + } + + for (T element : collection) { + add(element); + } + + return true; + } + + public void clear() { + while (size() > 0) { + poll(); + } + } + + public T element() { + emptyCheck(); + return peek(); + } + + public T remove() { + emptyCheck(); + return poll(); + } + + private void emptyCheck() { + if (size() == 0) { + throw new NoSuchElementException(); + } + } +} diff --git a/classpath/java/util/ArrayList.java b/classpath/java/util/ArrayList.java index 698f3f79df..3935aa44ec 100644 --- a/classpath/java/util/ArrayList.java +++ b/classpath/java/util/ArrayList.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -29,14 +29,15 @@ public class ArrayList extends AbstractList implements java.io.Serializabl addAll(source); } - private void grow() { - if (array == null || size >= array.length) { - resize(array == null ? MinimumCapacity : array.length * 2); + private void grow(int newSize) { + if (array == null || newSize > array.length) { + resize(Math.max(newSize, array == null + ? MinimumCapacity : array.length * 2)); } } - private void shrink() { - if (array.length / 2 >= MinimumCapacity && size <= array.length / 3) { + private void shrink(int newSize) { + if (array.length / 2 >= MinimumCapacity && newSize <= array.length / 3) { resize(array.length / 2); } } @@ -74,16 +75,15 @@ public class ArrayList extends AbstractList implements java.io.Serializabl } public void add(int index, T element) { - size = Math.max(size+1, index+1); - grow(); + int newSize = Math.max(size+1, index+1); + grow(newSize); + size = newSize; System.arraycopy(array, index, array, index+1, size-index-1); array[index] = element; } public boolean add(T element) { - ++ size; - grow(); - array[size - 1] = element; + add(size, element); return true; } @@ -137,8 +137,9 @@ public class ArrayList extends AbstractList implements java.io.Serializabl System.arraycopy(array, index + 1, array, index, size - index); } - -- size; - shrink(); + int newSize = size - 1; + shrink(newSize); + size = newSize; return v; } diff --git a/classpath/java/util/Collections.java b/classpath/java/util/Collections.java index 40c133f753..acb94cb40d 100644 --- a/classpath/java/util/Collections.java +++ b/classpath/java/util/Collections.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/Locale.java b/classpath/java/util/Locale.java index 373506bdec..66e685378b 100644 --- a/classpath/java/util/Locale.java +++ b/classpath/java/util/Locale.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2010, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/Properties.java b/classpath/java/util/Properties.java index 10b5c90687..9b1798491f 100644 --- a/classpath/java/util/Properties.java +++ b/classpath/java/util/Properties.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/Queue.java b/classpath/java/util/Queue.java new file mode 100644 index 0000000000..27855a7f61 --- /dev/null +++ b/classpath/java/util/Queue.java @@ -0,0 +1,20 @@ +/* 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.util; + +public interface Queue extends Collection, Iterable { + public boolean add(T element); + public T element(); + public boolean offer(T element); + public T peek(); + public T poll(); + public T remove(); +} diff --git a/classpath/java/util/Random.java b/classpath/java/util/Random.java index 311230f538..ac39a4417e 100644 --- a/classpath/java/util/Random.java +++ b/classpath/java/util/Random.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/SortedSet.java b/classpath/java/util/SortedSet.java new file mode 100644 index 0000000000..1e1b2b923e --- /dev/null +++ b/classpath/java/util/SortedSet.java @@ -0,0 +1,20 @@ +/* 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.util; + +public interface SortedSet extends Collection, Iterable, Set { + public Comparator comparator(); + public T first(); + public SortedSet headSet(T toElement); + public T last(); + public SortedSet subSet(T fromElement, T toElement); + public SortedSet tailSet(T fromElement); +} diff --git a/classpath/java/util/TreeSet.java b/classpath/java/util/TreeSet.java index 01e76496a2..1768d64843 100644 --- a/classpath/java/util/TreeSet.java +++ b/classpath/java/util/TreeSet.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -15,7 +15,6 @@ import avian.Cell; public class TreeSet extends AbstractSet implements Collection { private PersistentSet> set; - private int size; public TreeSet(final Comparator comparator) { set = new PersistentSet(new Comparator>() { @@ -23,7 +22,6 @@ public class TreeSet extends AbstractSet implements Collection { return comparator.compare(a.value, b.value); } }); - size = 0; } public TreeSet() { @@ -66,7 +64,6 @@ public class TreeSet extends AbstractSet implements Collection { PersistentSet.Path> p = set.find(new Cell(value, null)); if (p.fresh()) { set = p.add(); - ++size; return true; } return false; @@ -76,7 +73,6 @@ public class TreeSet extends AbstractSet implements Collection { PersistentSet.Path> p = set.find(new Cell(value, null)); if (p.fresh()) { set = p.add(); - ++size; return null; } else { T old = p.value().value; @@ -100,8 +96,6 @@ public class TreeSet extends AbstractSet implements Collection { if (p.fresh()) { return null; } else { - --size; - Cell old = p.value(); if (p.value().next != null) { @@ -119,11 +113,11 @@ public class TreeSet extends AbstractSet implements Collection { } public int size() { - return size; + return set.size(); } public boolean isEmpty() { - return size == 0; + return set.size() != 0; } public boolean contains(Object value) { @@ -132,7 +126,6 @@ public class TreeSet extends AbstractSet implements Collection { public void clear() { set = new PersistentSet(set.comparator()); - size = 0; } private class MyIterator implements java.util.Iterator { @@ -180,8 +173,6 @@ public class TreeSet extends AbstractSet implements Collection { public void remove() { if (! canRemove) throw new IllegalStateException(); - --size; - if (prevPrevCell != null && prevPrevCell.next == prevCell) { // cell to remove is not the first in the list. prevPrevCell.next = prevCell.next; diff --git a/classpath/java/util/Vector.java b/classpath/java/util/Vector.java index e95c8df414..0e1dadd7fe 100644 --- a/classpath/java/util/Vector.java +++ b/classpath/java/util/Vector.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/regex/Matcher.java b/classpath/java/util/regex/Matcher.java index 99f9d9daad..dd21a062af 100644 --- a/classpath/java/util/regex/Matcher.java +++ b/classpath/java/util/regex/Matcher.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2010, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/Deflater.java b/classpath/java/util/zip/Deflater.java index 8368bb0817..9b6b832039 100644 --- a/classpath/java/util/zip/Deflater.java +++ b/classpath/java/util/zip/Deflater.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/DeflaterOutputStream.java b/classpath/java/util/zip/DeflaterOutputStream.java index 3ee3fcdbb8..c77fbd1a52 100644 --- a/classpath/java/util/zip/DeflaterOutputStream.java +++ b/classpath/java/util/zip/DeflaterOutputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/Inflater.java b/classpath/java/util/zip/Inflater.java index 9f44415194..a4c00e6934 100644 --- a/classpath/java/util/zip/Inflater.java +++ b/classpath/java/util/zip/Inflater.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/ZipEntry.java b/classpath/java/util/zip/ZipEntry.java index ffa8a1a82e..31359a8507 100644 --- a/classpath/java/util/zip/ZipEntry.java +++ b/classpath/java/util/zip/ZipEntry.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/ZipFile.java b/classpath/java/util/zip/ZipFile.java index 94d8b99b08..f3d0428e82 100644 --- a/classpath/java/util/zip/ZipFile.java +++ b/classpath/java/util/zip/ZipFile.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -86,7 +86,7 @@ public class ZipFile { } public InputStream getInputStream(ZipEntry entry) throws IOException { - int pointer = ((MyEntry) entry).pointer(); + final int pointer = ((MyEntry) entry).pointer(); int method = compressionMethod(window, pointer); int size = compressedSize(window, pointer); InputStream in = new MyInputStream(file, fileData(window, pointer), size); @@ -99,7 +99,35 @@ public class ZipFile { return in; case Deflated: - return new InflaterInputStream(in, new Inflater(true)); + return new InflaterInputStream(in, new Inflater(true)) { + int remaining = uncompressedSize(window, pointer); + + public int read() throws IOException { + int c = super.read(); + if (c >= 0) { + -- remaining; + } + return c; + } + + public int read(byte[] buffer) throws IOException { + return read(buffer, 0, buffer.length); + } + + public int read(byte[] buffer, int offset, int length) + throws IOException + { + int c = super.read(buffer, offset, length); + if (c > 0) { + remaining -= c; + } + return c; + } + + public int available() { + return remaining; + } + }; default: throw new IOException(); diff --git a/classpath/jni-util.h b/classpath/jni-util.h index 4973891704..57e545a14b 100644 --- a/classpath/jni-util.h +++ b/classpath/jni-util.h @@ -73,8 +73,6 @@ typedef unsigned __int64 uint64_t; #endif // not _MSC_VER -namespace { - inline void throwNew(JNIEnv* e, const char* class_, const char* message, ...) { @@ -149,7 +147,4 @@ class RuntimeArray { #endif // not _MSC_VER - -} // namespace - #endif//JNI_UTIL diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java new file mode 100644 index 0000000000..b7613d2559 --- /dev/null +++ b/classpath/sun/misc/Unsafe.java @@ -0,0 +1,50 @@ +package sun.misc; + +public final class Unsafe { + private void Unsafe() { } + + private static final Unsafe Instance = new Unsafe(); + + public static Unsafe getUnsafe() { + return Instance; + } + + public native long allocateMemory(long bytes); + + public native void setMemory + (Object base, long offset, long count, byte value); + + public native void freeMemory(long address); + + public native byte getByte(long address); + + public native void putByte(long address, byte x); + + public native short getShort(long address); + + public native void putShort(long address, short x); + + public native char getChar(long address); + + public native void putChar(long address, char x); + + public native int getInt(long address); + + public native void putInt(long address, int x); + + public native long getLong(long address); + + public native void putLong(long address, long x); + + public native float getFloat(long address); + + public native void putFloat(long address, float x); + + public native double getDouble(long address); + + public native void putDouble(long address, double x); + + public native long getAddress(long address); + + public native void putAddress(long address, long x); +} diff --git a/hello/Hello.java b/hello/Hello.java new file mode 100644 index 0000000000..d7d4f91935 --- /dev/null +++ b/hello/Hello.java @@ -0,0 +1,5 @@ +public class Hello { + public static void main(String[] args) { + System.out.println("hello, world!"); + } +} diff --git a/hello/LzmaDec.o b/hello/LzmaDec.o new file mode 100644 index 0000000000..6e0f19285b Binary files /dev/null and b/hello/LzmaDec.o differ diff --git a/hello/bootimage-bin.o b/hello/bootimage-bin.o new file mode 100644 index 0000000000..8ce8e42e8e Binary files /dev/null and b/hello/bootimage-bin.o differ diff --git a/hello/bootimage-main.cpp b/hello/bootimage-main.cpp new file mode 100644 index 0000000000..9b1b541a7c --- /dev/null +++ b/hello/bootimage-main.cpp @@ -0,0 +1,91 @@ +#include "stdint.h" +#include "jni.h" + +#if (defined __MINGW32__) || (defined _MSC_VER) +# define EXPORT __declspec(dllexport) +#else +# define EXPORT __attribute__ ((visibility("default"))) +#endif + +#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) +# define BOOTIMAGE_BIN(x) binary_bootimage_bin_##x +# define CODEIMAGE_BIN(x) binary_codeimage_bin_##x +#else +# define BOOTIMAGE_BIN(x) _binary_bootimage_bin_##x +# define CODEIMAGE_BIN(x) _binary_codeimage_bin_##x +#endif + +extern "C" { + + extern const uint8_t BOOTIMAGE_BIN(start)[]; + extern const uint8_t BOOTIMAGE_BIN(end)[]; + + EXPORT const uint8_t* + bootimageBin(unsigned* size) + { + *size = BOOTIMAGE_BIN(end) - BOOTIMAGE_BIN(start); + return BOOTIMAGE_BIN(start); + } + + extern const uint8_t CODEIMAGE_BIN(start)[]; + extern const uint8_t CODEIMAGE_BIN(end)[]; + + EXPORT const uint8_t* + codeimageBin(unsigned* size) + { + *size = CODEIMAGE_BIN(end) - CODEIMAGE_BIN(start); + return CODEIMAGE_BIN(start); + } + +} // extern "C" + +int +main(int ac, const char** av) +{ + JavaVMInitArgs vmArgs; + vmArgs.version = JNI_VERSION_1_2; + vmArgs.nOptions = 2; + vmArgs.ignoreUnrecognized = JNI_TRUE; + + JavaVMOption options[vmArgs.nOptions]; + vmArgs.options = options; + + options[0].optionString + = const_cast("-Davian.bootimage=lzma:bootimageBin"); + + options[1].optionString + = const_cast("-Davian.codeimage=codeimageBin"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = e->FindClass("Hello"); + if (not e->ExceptionCheck()) { + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); + if (not e->ExceptionCheck()) { + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 1; i < ac; ++i) { + e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } + } + } + } + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + } + + vm->DestroyJavaVM(); + + return exitCode; +} diff --git a/hello/builtin.o b/hello/builtin.o new file mode 100644 index 0000000000..a44420ae4f Binary files /dev/null and b/hello/builtin.o differ diff --git a/hello/classpath-avian.o b/hello/classpath-avian.o new file mode 100644 index 0000000000..e89fa15edf Binary files /dev/null and b/hello/classpath-avian.o differ diff --git a/hello/codeimage-bin.o b/hello/codeimage-bin.o new file mode 100644 index 0000000000..67df9d99a3 Binary files /dev/null and b/hello/codeimage-bin.o differ diff --git a/hello/compile-x86-asm.o b/hello/compile-x86-asm.o new file mode 100644 index 0000000000..2c52c1e7d7 Binary files /dev/null and b/hello/compile-x86-asm.o differ diff --git a/hello/compile.o b/hello/compile.o new file mode 100644 index 0000000000..d189981a42 Binary files /dev/null and b/hello/compile.o differ diff --git a/hello/compiler.o b/hello/compiler.o new file mode 100644 index 0000000000..74bb19ae36 Binary files /dev/null and b/hello/compiler.o differ diff --git a/hello/finder.o b/hello/finder.o new file mode 100644 index 0000000000..864c058a04 Binary files /dev/null and b/hello/finder.o differ diff --git a/hello/heap.o b/hello/heap.o new file mode 100644 index 0000000000..e6b9f1d037 Binary files /dev/null and b/hello/heap.o differ diff --git a/hello/hello b/hello/hello new file mode 100755 index 0000000000..061a8ad780 Binary files /dev/null and b/hello/hello differ diff --git a/hello/java-io.o b/hello/java-io.o new file mode 100644 index 0000000000..a22b011d4c Binary files /dev/null and b/hello/java-io.o differ diff --git a/hello/java-lang.o b/hello/java-lang.o new file mode 100644 index 0000000000..2d832276f4 Binary files /dev/null and b/hello/java-lang.o differ diff --git a/hello/java-net.o b/hello/java-net.o new file mode 100644 index 0000000000..93c00c7c9d Binary files /dev/null and b/hello/java-net.o differ diff --git a/hello/java-nio.o b/hello/java-nio.o new file mode 100644 index 0000000000..8b5c345ec0 Binary files /dev/null and b/hello/java-nio.o differ diff --git a/hello/java-util-zip.o b/hello/java-util-zip.o new file mode 100644 index 0000000000..45562eec79 Binary files /dev/null and b/hello/java-util-zip.o differ diff --git a/hello/java-util.o b/hello/java-util.o new file mode 100644 index 0000000000..b2dd202121 Binary files /dev/null and b/hello/java-util.o differ diff --git a/hello/jnienv.o b/hello/jnienv.o new file mode 100644 index 0000000000..80c7d69c15 Binary files /dev/null and b/hello/jnienv.o differ diff --git a/hello/lzma-decode.o b/hello/lzma-decode.o new file mode 100644 index 0000000000..cbf93f38cc Binary files /dev/null and b/hello/lzma-decode.o differ diff --git a/hello/machine.o b/hello/machine.o new file mode 100644 index 0000000000..eb5e8a6626 Binary files /dev/null and b/hello/machine.o differ diff --git a/hello/main.o b/hello/main.o new file mode 100644 index 0000000000..fe571f20ce Binary files /dev/null and b/hello/main.o differ diff --git a/hello/posix.o b/hello/posix.o new file mode 100644 index 0000000000..1c17cfa8d9 Binary files /dev/null and b/hello/posix.o differ diff --git a/hello/process.o b/hello/process.o new file mode 100644 index 0000000000..cd73fef85e Binary files /dev/null and b/hello/process.o differ diff --git a/hello/stage1/Hello.class b/hello/stage1/Hello.class new file mode 100644 index 0000000000..c0dcb729f1 Binary files /dev/null and b/hello/stage1/Hello.class differ diff --git a/hello/stage1/META-INF/MANIFEST.MF b/hello/stage1/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..9ca4badc23 --- /dev/null +++ b/hello/stage1/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Created-By: 1.6.0-18 (Sun Microsystems Inc.) + diff --git a/hello/stage1/avian/Addendum.class b/hello/stage1/avian/Addendum.class new file mode 100644 index 0000000000..168be4e7b9 Binary files /dev/null and b/hello/stage1/avian/Addendum.class differ diff --git a/hello/stage1/avian/AnnotationInvocationHandler.class b/hello/stage1/avian/AnnotationInvocationHandler.class new file mode 100644 index 0000000000..d6208ba6f7 Binary files /dev/null and b/hello/stage1/avian/AnnotationInvocationHandler.class differ diff --git a/hello/stage1/avian/Assembler$MethodData.class b/hello/stage1/avian/Assembler$MethodData.class new file mode 100644 index 0000000000..60981875c2 Binary files /dev/null and b/hello/stage1/avian/Assembler$MethodData.class differ diff --git a/hello/stage1/avian/Assembler.class b/hello/stage1/avian/Assembler.class new file mode 100644 index 0000000000..9d2f9e2247 Binary files /dev/null and b/hello/stage1/avian/Assembler.class differ diff --git a/hello/stage1/avian/Atomic.class b/hello/stage1/avian/Atomic.class new file mode 100644 index 0000000000..0d841cc64c Binary files /dev/null and b/hello/stage1/avian/Atomic.class differ diff --git a/hello/stage1/avian/Callback.class b/hello/stage1/avian/Callback.class new file mode 100644 index 0000000000..6e746a6259 Binary files /dev/null and b/hello/stage1/avian/Callback.class differ diff --git a/hello/stage1/avian/CallbackReceiver.class b/hello/stage1/avian/CallbackReceiver.class new file mode 100644 index 0000000000..830731ad7b Binary files /dev/null and b/hello/stage1/avian/CallbackReceiver.class differ diff --git a/hello/stage1/avian/Cell.class b/hello/stage1/avian/Cell.class new file mode 100644 index 0000000000..4eac9e7405 Binary files /dev/null and b/hello/stage1/avian/Cell.class differ diff --git a/hello/stage1/avian/ClassAddendum.class b/hello/stage1/avian/ClassAddendum.class new file mode 100644 index 0000000000..8fa105fbc1 Binary files /dev/null and b/hello/stage1/avian/ClassAddendum.class differ diff --git a/hello/stage1/avian/Classes.class b/hello/stage1/avian/Classes.class new file mode 100644 index 0000000000..59d18190f5 Binary files /dev/null and b/hello/stage1/avian/Classes.class differ diff --git a/hello/stage1/avian/ConstantPool$ClassPoolEntry.class b/hello/stage1/avian/ConstantPool$ClassPoolEntry.class new file mode 100644 index 0000000000..489432a84d Binary files /dev/null and b/hello/stage1/avian/ConstantPool$ClassPoolEntry.class differ diff --git a/hello/stage1/avian/ConstantPool$FieldRefPoolEntry.class b/hello/stage1/avian/ConstantPool$FieldRefPoolEntry.class new file mode 100644 index 0000000000..df2bd1456b Binary files /dev/null and b/hello/stage1/avian/ConstantPool$FieldRefPoolEntry.class differ diff --git a/hello/stage1/avian/ConstantPool$IntegerPoolEntry.class b/hello/stage1/avian/ConstantPool$IntegerPoolEntry.class new file mode 100644 index 0000000000..a8ca4ec112 Binary files /dev/null and b/hello/stage1/avian/ConstantPool$IntegerPoolEntry.class differ diff --git a/hello/stage1/avian/ConstantPool$MethodRefPoolEntry.class b/hello/stage1/avian/ConstantPool$MethodRefPoolEntry.class new file mode 100644 index 0000000000..ddfb2548ba Binary files /dev/null and b/hello/stage1/avian/ConstantPool$MethodRefPoolEntry.class differ diff --git a/hello/stage1/avian/ConstantPool$NameAndTypePoolEntry.class b/hello/stage1/avian/ConstantPool$NameAndTypePoolEntry.class new file mode 100644 index 0000000000..f6a3bd166e Binary files /dev/null and b/hello/stage1/avian/ConstantPool$NameAndTypePoolEntry.class differ diff --git a/hello/stage1/avian/ConstantPool$PoolEntry.class b/hello/stage1/avian/ConstantPool$PoolEntry.class new file mode 100644 index 0000000000..ce96b8836c Binary files /dev/null and b/hello/stage1/avian/ConstantPool$PoolEntry.class differ diff --git a/hello/stage1/avian/ConstantPool$StringPoolEntry.class b/hello/stage1/avian/ConstantPool$StringPoolEntry.class new file mode 100644 index 0000000000..17b438e4fd Binary files /dev/null and b/hello/stage1/avian/ConstantPool$StringPoolEntry.class differ diff --git a/hello/stage1/avian/ConstantPool$Utf8PoolEntry.class b/hello/stage1/avian/ConstantPool$Utf8PoolEntry.class new file mode 100644 index 0000000000..1817d8de49 Binary files /dev/null and b/hello/stage1/avian/ConstantPool$Utf8PoolEntry.class differ diff --git a/hello/stage1/avian/ConstantPool.class b/hello/stage1/avian/ConstantPool.class new file mode 100644 index 0000000000..c56eadd24b Binary files /dev/null and b/hello/stage1/avian/ConstantPool.class differ diff --git a/hello/stage1/avian/Continuations$Continuation.class b/hello/stage1/avian/Continuations$Continuation.class new file mode 100644 index 0000000000..82493d7a9c Binary files /dev/null and b/hello/stage1/avian/Continuations$Continuation.class differ diff --git a/hello/stage1/avian/Continuations$UnwindResult.class b/hello/stage1/avian/Continuations$UnwindResult.class new file mode 100644 index 0000000000..c32084fad8 Binary files /dev/null and b/hello/stage1/avian/Continuations$UnwindResult.class differ diff --git a/hello/stage1/avian/Continuations.class b/hello/stage1/avian/Continuations.class new file mode 100644 index 0000000000..65ed444d01 Binary files /dev/null and b/hello/stage1/avian/Continuations.class differ diff --git a/hello/stage1/avian/FieldAddendum.class b/hello/stage1/avian/FieldAddendum.class new file mode 100644 index 0000000000..7b0e151c33 Binary files /dev/null and b/hello/stage1/avian/FieldAddendum.class differ diff --git a/hello/stage1/avian/IncompatibleContinuationException.class b/hello/stage1/avian/IncompatibleContinuationException.class new file mode 100644 index 0000000000..7164d997bc Binary files /dev/null and b/hello/stage1/avian/IncompatibleContinuationException.class differ diff --git a/hello/stage1/avian/Iso88591.class b/hello/stage1/avian/Iso88591.class new file mode 100644 index 0000000000..53fa13ec08 Binary files /dev/null and b/hello/stage1/avian/Iso88591.class differ diff --git a/hello/stage1/avian/Machine.class b/hello/stage1/avian/Machine.class new file mode 100644 index 0000000000..55158c4fb5 Binary files /dev/null and b/hello/stage1/avian/Machine.class differ diff --git a/hello/stage1/avian/MethodAddendum.class b/hello/stage1/avian/MethodAddendum.class new file mode 100644 index 0000000000..ccd77a23fb Binary files /dev/null and b/hello/stage1/avian/MethodAddendum.class differ diff --git a/hello/stage1/avian/OpenJDK.class b/hello/stage1/avian/OpenJDK.class new file mode 100644 index 0000000000..4269366c3b Binary files /dev/null and b/hello/stage1/avian/OpenJDK.class differ diff --git a/hello/stage1/avian/PersistentSet$1.class b/hello/stage1/avian/PersistentSet$1.class new file mode 100644 index 0000000000..fecf643ea6 Binary files /dev/null and b/hello/stage1/avian/PersistentSet$1.class differ diff --git a/hello/stage1/avian/PersistentSet$Iterator.class b/hello/stage1/avian/PersistentSet$Iterator.class new file mode 100644 index 0000000000..8234a92feb Binary files /dev/null and b/hello/stage1/avian/PersistentSet$Iterator.class differ diff --git a/hello/stage1/avian/PersistentSet$Node.class b/hello/stage1/avian/PersistentSet$Node.class new file mode 100644 index 0000000000..4e0374e039 Binary files /dev/null and b/hello/stage1/avian/PersistentSet$Node.class differ diff --git a/hello/stage1/avian/PersistentSet$Path.class b/hello/stage1/avian/PersistentSet$Path.class new file mode 100644 index 0000000000..15795a435a Binary files /dev/null and b/hello/stage1/avian/PersistentSet$Path.class differ diff --git a/hello/stage1/avian/PersistentSet.class b/hello/stage1/avian/PersistentSet.class new file mode 100644 index 0000000000..2e9e7942cf Binary files /dev/null and b/hello/stage1/avian/PersistentSet.class differ diff --git a/hello/stage1/avian/Singleton.class b/hello/stage1/avian/Singleton.class new file mode 100644 index 0000000000..86328e2f33 Binary files /dev/null and b/hello/stage1/avian/Singleton.class differ diff --git a/hello/stage1/avian/Stream.class b/hello/stage1/avian/Stream.class new file mode 100644 index 0000000000..d961626ee9 Binary files /dev/null and b/hello/stage1/avian/Stream.class differ diff --git a/hello/stage1/avian/SystemClassLoader.class b/hello/stage1/avian/SystemClassLoader.class new file mode 100644 index 0000000000..84856d2c37 Binary files /dev/null and b/hello/stage1/avian/SystemClassLoader.class differ diff --git a/hello/stage1/avian/Utf8.class b/hello/stage1/avian/Utf8.class new file mode 100644 index 0000000000..c38c370539 Binary files /dev/null and b/hello/stage1/avian/Utf8.class differ diff --git a/hello/stage1/avian/VMClass.class b/hello/stage1/avian/VMClass.class new file mode 100644 index 0000000000..7624289793 Binary files /dev/null and b/hello/stage1/avian/VMClass.class differ diff --git a/hello/stage1/avian/VMField.class b/hello/stage1/avian/VMField.class new file mode 100644 index 0000000000..01239c0773 Binary files /dev/null and b/hello/stage1/avian/VMField.class differ diff --git a/hello/stage1/avian/VMMethod.class b/hello/stage1/avian/VMMethod.class new file mode 100644 index 0000000000..0f26be9e98 Binary files /dev/null and b/hello/stage1/avian/VMMethod.class differ diff --git a/hello/stage1/avian/file/Handler$FileURLConnection.class b/hello/stage1/avian/file/Handler$FileURLConnection.class new file mode 100644 index 0000000000..f9aa8f0f86 Binary files /dev/null and b/hello/stage1/avian/file/Handler$FileURLConnection.class differ diff --git a/hello/stage1/avian/file/Handler.class b/hello/stage1/avian/file/Handler.class new file mode 100644 index 0000000000..1ee350aa15 Binary files /dev/null and b/hello/stage1/avian/file/Handler.class differ diff --git a/hello/stage1/avian/http/Handler.class b/hello/stage1/avian/http/Handler.class new file mode 100644 index 0000000000..473835185e Binary files /dev/null and b/hello/stage1/avian/http/Handler.class differ diff --git a/hello/stage1/avian/jar/Handler$MyJarURLConnection.class b/hello/stage1/avian/jar/Handler$MyJarURLConnection.class new file mode 100644 index 0000000000..4fd170e4c4 Binary files /dev/null and b/hello/stage1/avian/jar/Handler$MyJarURLConnection.class differ diff --git a/hello/stage1/avian/jar/Handler.class b/hello/stage1/avian/jar/Handler.class new file mode 100644 index 0000000000..da120910b7 Binary files /dev/null and b/hello/stage1/avian/jar/Handler.class differ diff --git a/hello/stage1/avian/resource/Handler$ResourceConnection.class b/hello/stage1/avian/resource/Handler$ResourceConnection.class new file mode 100644 index 0000000000..aac416da40 Binary files /dev/null and b/hello/stage1/avian/resource/Handler$ResourceConnection.class differ diff --git a/hello/stage1/avian/resource/Handler$ResourceInputStream.class b/hello/stage1/avian/resource/Handler$ResourceInputStream.class new file mode 100644 index 0000000000..53dc0a2f44 Binary files /dev/null and b/hello/stage1/avian/resource/Handler$ResourceInputStream.class differ diff --git a/hello/stage1/avian/resource/Handler.class b/hello/stage1/avian/resource/Handler.class new file mode 100644 index 0000000000..9b1460d3be Binary files /dev/null and b/hello/stage1/avian/resource/Handler.class differ diff --git a/hello/stage1/java/io/BufferedInputStream.class b/hello/stage1/java/io/BufferedInputStream.class new file mode 100644 index 0000000000..1a230db16a Binary files /dev/null and b/hello/stage1/java/io/BufferedInputStream.class differ diff --git a/hello/stage1/java/io/BufferedOutputStream.class b/hello/stage1/java/io/BufferedOutputStream.class new file mode 100644 index 0000000000..3d363cb6fc Binary files /dev/null and b/hello/stage1/java/io/BufferedOutputStream.class differ diff --git a/hello/stage1/java/io/BufferedReader.class b/hello/stage1/java/io/BufferedReader.class new file mode 100644 index 0000000000..3c43f9e2b8 Binary files /dev/null and b/hello/stage1/java/io/BufferedReader.class differ diff --git a/hello/stage1/java/io/BufferedWriter.class b/hello/stage1/java/io/BufferedWriter.class new file mode 100644 index 0000000000..429c1a5804 Binary files /dev/null and b/hello/stage1/java/io/BufferedWriter.class differ diff --git a/hello/stage1/java/io/ByteArrayInputStream.class b/hello/stage1/java/io/ByteArrayInputStream.class new file mode 100644 index 0000000000..310912d4e3 Binary files /dev/null and b/hello/stage1/java/io/ByteArrayInputStream.class differ diff --git a/hello/stage1/java/io/ByteArrayOutputStream$Cell.class b/hello/stage1/java/io/ByteArrayOutputStream$Cell.class new file mode 100644 index 0000000000..5eda03193e Binary files /dev/null and b/hello/stage1/java/io/ByteArrayOutputStream$Cell.class differ diff --git a/hello/stage1/java/io/ByteArrayOutputStream.class b/hello/stage1/java/io/ByteArrayOutputStream.class new file mode 100644 index 0000000000..4f144c16a0 Binary files /dev/null and b/hello/stage1/java/io/ByteArrayOutputStream.class differ diff --git a/hello/stage1/java/io/EOFException.class b/hello/stage1/java/io/EOFException.class new file mode 100644 index 0000000000..add6a3870f Binary files /dev/null and b/hello/stage1/java/io/EOFException.class differ diff --git a/hello/stage1/java/io/Externalizable.class b/hello/stage1/java/io/Externalizable.class new file mode 100644 index 0000000000..a1d93ddf04 Binary files /dev/null and b/hello/stage1/java/io/Externalizable.class differ diff --git a/hello/stage1/java/io/File$Pair.class b/hello/stage1/java/io/File$Pair.class new file mode 100644 index 0000000000..1e4afaf029 Binary files /dev/null and b/hello/stage1/java/io/File$Pair.class differ diff --git a/hello/stage1/java/io/File.class b/hello/stage1/java/io/File.class new file mode 100644 index 0000000000..1db64237da Binary files /dev/null and b/hello/stage1/java/io/File.class differ diff --git a/hello/stage1/java/io/FileDescriptor.class b/hello/stage1/java/io/FileDescriptor.class new file mode 100644 index 0000000000..f5b6fcb899 Binary files /dev/null and b/hello/stage1/java/io/FileDescriptor.class differ diff --git a/hello/stage1/java/io/FileInputStream.class b/hello/stage1/java/io/FileInputStream.class new file mode 100644 index 0000000000..e08cba5ddf Binary files /dev/null and b/hello/stage1/java/io/FileInputStream.class differ diff --git a/hello/stage1/java/io/FileNotFoundException.class b/hello/stage1/java/io/FileNotFoundException.class new file mode 100644 index 0000000000..05f89b3da2 Binary files /dev/null and b/hello/stage1/java/io/FileNotFoundException.class differ diff --git a/hello/stage1/java/io/FileOutputStream.class b/hello/stage1/java/io/FileOutputStream.class new file mode 100644 index 0000000000..4264f22a02 Binary files /dev/null and b/hello/stage1/java/io/FileOutputStream.class differ diff --git a/hello/stage1/java/io/FileReader.class b/hello/stage1/java/io/FileReader.class new file mode 100644 index 0000000000..96630d64cb Binary files /dev/null and b/hello/stage1/java/io/FileReader.class differ diff --git a/hello/stage1/java/io/FileWriter.class b/hello/stage1/java/io/FileWriter.class new file mode 100644 index 0000000000..866545cd3b Binary files /dev/null and b/hello/stage1/java/io/FileWriter.class differ diff --git a/hello/stage1/java/io/FilenameFilter.class b/hello/stage1/java/io/FilenameFilter.class new file mode 100644 index 0000000000..44383f8032 Binary files /dev/null and b/hello/stage1/java/io/FilenameFilter.class differ diff --git a/hello/stage1/java/io/FilterOutputStream.class b/hello/stage1/java/io/FilterOutputStream.class new file mode 100644 index 0000000000..e452178bf0 Binary files /dev/null and b/hello/stage1/java/io/FilterOutputStream.class differ diff --git a/hello/stage1/java/io/IOException.class b/hello/stage1/java/io/IOException.class new file mode 100644 index 0000000000..56674fcb0b Binary files /dev/null and b/hello/stage1/java/io/IOException.class differ diff --git a/hello/stage1/java/io/InputStream.class b/hello/stage1/java/io/InputStream.class new file mode 100644 index 0000000000..109e92aea2 Binary files /dev/null and b/hello/stage1/java/io/InputStream.class differ diff --git a/hello/stage1/java/io/InputStreamReader.class b/hello/stage1/java/io/InputStreamReader.class new file mode 100644 index 0000000000..49d65726ee Binary files /dev/null and b/hello/stage1/java/io/InputStreamReader.class differ diff --git a/hello/stage1/java/io/LineNumberReader.class b/hello/stage1/java/io/LineNumberReader.class new file mode 100644 index 0000000000..ed60e3594b Binary files /dev/null and b/hello/stage1/java/io/LineNumberReader.class differ diff --git a/hello/stage1/java/io/NotSerializableException.class b/hello/stage1/java/io/NotSerializableException.class new file mode 100644 index 0000000000..ec9be2db72 Binary files /dev/null and b/hello/stage1/java/io/NotSerializableException.class differ diff --git a/hello/stage1/java/io/ObjectInput.class b/hello/stage1/java/io/ObjectInput.class new file mode 100644 index 0000000000..40246e742e Binary files /dev/null and b/hello/stage1/java/io/ObjectInput.class differ diff --git a/hello/stage1/java/io/ObjectInputStream.class b/hello/stage1/java/io/ObjectInputStream.class new file mode 100644 index 0000000000..dac5b1770c Binary files /dev/null and b/hello/stage1/java/io/ObjectInputStream.class differ diff --git a/hello/stage1/java/io/ObjectOutput.class b/hello/stage1/java/io/ObjectOutput.class new file mode 100644 index 0000000000..dd3ccb1aec Binary files /dev/null and b/hello/stage1/java/io/ObjectOutput.class differ diff --git a/hello/stage1/java/io/ObjectOutputStream.class b/hello/stage1/java/io/ObjectOutputStream.class new file mode 100644 index 0000000000..42b3596c5f Binary files /dev/null and b/hello/stage1/java/io/ObjectOutputStream.class differ diff --git a/hello/stage1/java/io/ObjectStreamException.class b/hello/stage1/java/io/ObjectStreamException.class new file mode 100644 index 0000000000..b72153d8e3 Binary files /dev/null and b/hello/stage1/java/io/ObjectStreamException.class differ diff --git a/hello/stage1/java/io/OutputStream.class b/hello/stage1/java/io/OutputStream.class new file mode 100644 index 0000000000..7a0dde54d6 Binary files /dev/null and b/hello/stage1/java/io/OutputStream.class differ diff --git a/hello/stage1/java/io/OutputStreamWriter.class b/hello/stage1/java/io/OutputStreamWriter.class new file mode 100644 index 0000000000..2aae1fecb3 Binary files /dev/null and b/hello/stage1/java/io/OutputStreamWriter.class differ diff --git a/hello/stage1/java/io/PrintStream$Static.class b/hello/stage1/java/io/PrintStream$Static.class new file mode 100644 index 0000000000..0d45961b62 Binary files /dev/null and b/hello/stage1/java/io/PrintStream$Static.class differ diff --git a/hello/stage1/java/io/PrintStream.class b/hello/stage1/java/io/PrintStream.class new file mode 100644 index 0000000000..f3fbf0c754 Binary files /dev/null and b/hello/stage1/java/io/PrintStream.class differ diff --git a/hello/stage1/java/io/PrintWriter.class b/hello/stage1/java/io/PrintWriter.class new file mode 100644 index 0000000000..bc239d3d1a Binary files /dev/null and b/hello/stage1/java/io/PrintWriter.class differ diff --git a/hello/stage1/java/io/PushbackReader.class b/hello/stage1/java/io/PushbackReader.class new file mode 100644 index 0000000000..8e69745921 Binary files /dev/null and b/hello/stage1/java/io/PushbackReader.class differ diff --git a/hello/stage1/java/io/RandomAccessFile.class b/hello/stage1/java/io/RandomAccessFile.class new file mode 100644 index 0000000000..2aa9f060aa Binary files /dev/null and b/hello/stage1/java/io/RandomAccessFile.class differ diff --git a/hello/stage1/java/io/Reader.class b/hello/stage1/java/io/Reader.class new file mode 100644 index 0000000000..979c5cb52b Binary files /dev/null and b/hello/stage1/java/io/Reader.class differ diff --git a/hello/stage1/java/io/Serializable.class b/hello/stage1/java/io/Serializable.class new file mode 100644 index 0000000000..187117d220 Binary files /dev/null and b/hello/stage1/java/io/Serializable.class differ diff --git a/hello/stage1/java/io/StreamCorruptedException.class b/hello/stage1/java/io/StreamCorruptedException.class new file mode 100644 index 0000000000..c20d8130a1 Binary files /dev/null and b/hello/stage1/java/io/StreamCorruptedException.class differ diff --git a/hello/stage1/java/io/StringReader.class b/hello/stage1/java/io/StringReader.class new file mode 100644 index 0000000000..722922f695 Binary files /dev/null and b/hello/stage1/java/io/StringReader.class differ diff --git a/hello/stage1/java/io/StringWriter.class b/hello/stage1/java/io/StringWriter.class new file mode 100644 index 0000000000..61306aceee Binary files /dev/null and b/hello/stage1/java/io/StringWriter.class differ diff --git a/hello/stage1/java/io/UnsupportedEncodingException.class b/hello/stage1/java/io/UnsupportedEncodingException.class new file mode 100644 index 0000000000..e1aa3444d8 Binary files /dev/null and b/hello/stage1/java/io/UnsupportedEncodingException.class differ diff --git a/hello/stage1/java/io/Writer.class b/hello/stage1/java/io/Writer.class new file mode 100644 index 0000000000..1477960995 Binary files /dev/null and b/hello/stage1/java/io/Writer.class differ diff --git a/hello/stage1/java/lang/AbstractMethodError.class b/hello/stage1/java/lang/AbstractMethodError.class new file mode 100644 index 0000000000..236bb55945 Binary files /dev/null and b/hello/stage1/java/lang/AbstractMethodError.class differ diff --git a/hello/stage1/java/lang/Appendable.class b/hello/stage1/java/lang/Appendable.class new file mode 100644 index 0000000000..e14361fc18 Binary files /dev/null and b/hello/stage1/java/lang/Appendable.class differ diff --git a/hello/stage1/java/lang/ArithmeticException.class b/hello/stage1/java/lang/ArithmeticException.class new file mode 100644 index 0000000000..a94769f9c2 Binary files /dev/null and b/hello/stage1/java/lang/ArithmeticException.class differ diff --git a/hello/stage1/java/lang/ArrayIndexOutOfBoundsException.class b/hello/stage1/java/lang/ArrayIndexOutOfBoundsException.class new file mode 100644 index 0000000000..7ccee28049 Binary files /dev/null and b/hello/stage1/java/lang/ArrayIndexOutOfBoundsException.class differ diff --git a/hello/stage1/java/lang/ArrayStoreException.class b/hello/stage1/java/lang/ArrayStoreException.class new file mode 100644 index 0000000000..0636f8e556 Binary files /dev/null and b/hello/stage1/java/lang/ArrayStoreException.class differ diff --git a/hello/stage1/java/lang/AssertionError.class b/hello/stage1/java/lang/AssertionError.class new file mode 100644 index 0000000000..2b4469755c Binary files /dev/null and b/hello/stage1/java/lang/AssertionError.class differ diff --git a/hello/stage1/java/lang/Boolean.class b/hello/stage1/java/lang/Boolean.class new file mode 100644 index 0000000000..b0ca4d1663 Binary files /dev/null and b/hello/stage1/java/lang/Boolean.class differ diff --git a/hello/stage1/java/lang/Byte.class b/hello/stage1/java/lang/Byte.class new file mode 100644 index 0000000000..f80233638b Binary files /dev/null and b/hello/stage1/java/lang/Byte.class differ diff --git a/hello/stage1/java/lang/CharSequence.class b/hello/stage1/java/lang/CharSequence.class new file mode 100644 index 0000000000..12121efddb Binary files /dev/null and b/hello/stage1/java/lang/CharSequence.class differ diff --git a/hello/stage1/java/lang/Character.class b/hello/stage1/java/lang/Character.class new file mode 100644 index 0000000000..251d47f224 Binary files /dev/null and b/hello/stage1/java/lang/Character.class differ diff --git a/hello/stage1/java/lang/Class.class b/hello/stage1/java/lang/Class.class new file mode 100644 index 0000000000..b2cb774d5a Binary files /dev/null and b/hello/stage1/java/lang/Class.class differ diff --git a/hello/stage1/java/lang/ClassCastException.class b/hello/stage1/java/lang/ClassCastException.class new file mode 100644 index 0000000000..43b6f3142d Binary files /dev/null and b/hello/stage1/java/lang/ClassCastException.class differ diff --git a/hello/stage1/java/lang/ClassLoader.class b/hello/stage1/java/lang/ClassLoader.class new file mode 100644 index 0000000000..d646910bef Binary files /dev/null and b/hello/stage1/java/lang/ClassLoader.class differ diff --git a/hello/stage1/java/lang/ClassNotFoundException.class b/hello/stage1/java/lang/ClassNotFoundException.class new file mode 100644 index 0000000000..a776dafa55 Binary files /dev/null and b/hello/stage1/java/lang/ClassNotFoundException.class differ diff --git a/hello/stage1/java/lang/CloneNotSupportedException.class b/hello/stage1/java/lang/CloneNotSupportedException.class new file mode 100644 index 0000000000..999c1000c7 Binary files /dev/null and b/hello/stage1/java/lang/CloneNotSupportedException.class differ diff --git a/hello/stage1/java/lang/Cloneable.class b/hello/stage1/java/lang/Cloneable.class new file mode 100644 index 0000000000..d9e937109b Binary files /dev/null and b/hello/stage1/java/lang/Cloneable.class differ diff --git a/hello/stage1/java/lang/Comparable.class b/hello/stage1/java/lang/Comparable.class new file mode 100644 index 0000000000..6d9a5cdc08 Binary files /dev/null and b/hello/stage1/java/lang/Comparable.class differ diff --git a/hello/stage1/java/lang/Double.class b/hello/stage1/java/lang/Double.class new file mode 100644 index 0000000000..181f6978b7 Binary files /dev/null and b/hello/stage1/java/lang/Double.class differ diff --git a/hello/stage1/java/lang/Enum.class b/hello/stage1/java/lang/Enum.class new file mode 100644 index 0000000000..d42a6b9f0a Binary files /dev/null and b/hello/stage1/java/lang/Enum.class differ diff --git a/hello/stage1/java/lang/Error.class b/hello/stage1/java/lang/Error.class new file mode 100644 index 0000000000..829a919c28 Binary files /dev/null and b/hello/stage1/java/lang/Error.class differ diff --git a/hello/stage1/java/lang/Exception.class b/hello/stage1/java/lang/Exception.class new file mode 100644 index 0000000000..fc98802d3a Binary files /dev/null and b/hello/stage1/java/lang/Exception.class differ diff --git a/hello/stage1/java/lang/ExceptionInInitializerError.class b/hello/stage1/java/lang/ExceptionInInitializerError.class new file mode 100644 index 0000000000..57e100766c Binary files /dev/null and b/hello/stage1/java/lang/ExceptionInInitializerError.class differ diff --git a/hello/stage1/java/lang/Float.class b/hello/stage1/java/lang/Float.class new file mode 100644 index 0000000000..28fc8f9625 Binary files /dev/null and b/hello/stage1/java/lang/Float.class differ diff --git a/hello/stage1/java/lang/IllegalAccessError.class b/hello/stage1/java/lang/IllegalAccessError.class new file mode 100644 index 0000000000..13a6d16eba Binary files /dev/null and b/hello/stage1/java/lang/IllegalAccessError.class differ diff --git a/hello/stage1/java/lang/IllegalAccessException.class b/hello/stage1/java/lang/IllegalAccessException.class new file mode 100644 index 0000000000..9112b4bf6a Binary files /dev/null and b/hello/stage1/java/lang/IllegalAccessException.class differ diff --git a/hello/stage1/java/lang/IllegalArgumentException.class b/hello/stage1/java/lang/IllegalArgumentException.class new file mode 100644 index 0000000000..74b28de118 Binary files /dev/null and b/hello/stage1/java/lang/IllegalArgumentException.class differ diff --git a/hello/stage1/java/lang/IllegalMonitorStateException.class b/hello/stage1/java/lang/IllegalMonitorStateException.class new file mode 100644 index 0000000000..41f8aa9ac9 Binary files /dev/null and b/hello/stage1/java/lang/IllegalMonitorStateException.class differ diff --git a/hello/stage1/java/lang/IllegalStateException.class b/hello/stage1/java/lang/IllegalStateException.class new file mode 100644 index 0000000000..6788de26e4 Binary files /dev/null and b/hello/stage1/java/lang/IllegalStateException.class differ diff --git a/hello/stage1/java/lang/IllegalThreadStateException.class b/hello/stage1/java/lang/IllegalThreadStateException.class new file mode 100644 index 0000000000..5b37f2a02a Binary files /dev/null and b/hello/stage1/java/lang/IllegalThreadStateException.class differ diff --git a/hello/stage1/java/lang/IncompatibleClassChangeError.class b/hello/stage1/java/lang/IncompatibleClassChangeError.class new file mode 100644 index 0000000000..98c21a680a Binary files /dev/null and b/hello/stage1/java/lang/IncompatibleClassChangeError.class differ diff --git a/hello/stage1/java/lang/IndexOutOfBoundsException.class b/hello/stage1/java/lang/IndexOutOfBoundsException.class new file mode 100644 index 0000000000..c15ba31832 Binary files /dev/null and b/hello/stage1/java/lang/IndexOutOfBoundsException.class differ diff --git a/hello/stage1/java/lang/InheritableThreadLocal.class b/hello/stage1/java/lang/InheritableThreadLocal.class new file mode 100644 index 0000000000..5caf70c7fe Binary files /dev/null and b/hello/stage1/java/lang/InheritableThreadLocal.class differ diff --git a/hello/stage1/java/lang/InstantiationError.class b/hello/stage1/java/lang/InstantiationError.class new file mode 100644 index 0000000000..bd5e4b3d00 Binary files /dev/null and b/hello/stage1/java/lang/InstantiationError.class differ diff --git a/hello/stage1/java/lang/InstantiationException.class b/hello/stage1/java/lang/InstantiationException.class new file mode 100644 index 0000000000..ed10b820f4 Binary files /dev/null and b/hello/stage1/java/lang/InstantiationException.class differ diff --git a/hello/stage1/java/lang/Integer.class b/hello/stage1/java/lang/Integer.class new file mode 100644 index 0000000000..f901b16a92 Binary files /dev/null and b/hello/stage1/java/lang/Integer.class differ diff --git a/hello/stage1/java/lang/InterruptedException.class b/hello/stage1/java/lang/InterruptedException.class new file mode 100644 index 0000000000..a5e0c5dcd9 Binary files /dev/null and b/hello/stage1/java/lang/InterruptedException.class differ diff --git a/hello/stage1/java/lang/Iterable.class b/hello/stage1/java/lang/Iterable.class new file mode 100644 index 0000000000..13b241869e Binary files /dev/null and b/hello/stage1/java/lang/Iterable.class differ diff --git a/hello/stage1/java/lang/LinkageError.class b/hello/stage1/java/lang/LinkageError.class new file mode 100644 index 0000000000..8ad2db2ca0 Binary files /dev/null and b/hello/stage1/java/lang/LinkageError.class differ diff --git a/hello/stage1/java/lang/Long.class b/hello/stage1/java/lang/Long.class new file mode 100644 index 0000000000..2349d0c2ed Binary files /dev/null and b/hello/stage1/java/lang/Long.class differ diff --git a/hello/stage1/java/lang/Math.class b/hello/stage1/java/lang/Math.class new file mode 100644 index 0000000000..80f99fe1a9 Binary files /dev/null and b/hello/stage1/java/lang/Math.class differ diff --git a/hello/stage1/java/lang/NegativeArraySizeException.class b/hello/stage1/java/lang/NegativeArraySizeException.class new file mode 100644 index 0000000000..d9f24feb16 Binary files /dev/null and b/hello/stage1/java/lang/NegativeArraySizeException.class differ diff --git a/hello/stage1/java/lang/NoClassDefFoundError.class b/hello/stage1/java/lang/NoClassDefFoundError.class new file mode 100644 index 0000000000..8271e81bcf Binary files /dev/null and b/hello/stage1/java/lang/NoClassDefFoundError.class differ diff --git a/hello/stage1/java/lang/NoSuchFieldError.class b/hello/stage1/java/lang/NoSuchFieldError.class new file mode 100644 index 0000000000..003327588c Binary files /dev/null and b/hello/stage1/java/lang/NoSuchFieldError.class differ diff --git a/hello/stage1/java/lang/NoSuchFieldException.class b/hello/stage1/java/lang/NoSuchFieldException.class new file mode 100644 index 0000000000..67983f453a Binary files /dev/null and b/hello/stage1/java/lang/NoSuchFieldException.class differ diff --git a/hello/stage1/java/lang/NoSuchMethodError.class b/hello/stage1/java/lang/NoSuchMethodError.class new file mode 100644 index 0000000000..7cb6613484 Binary files /dev/null and b/hello/stage1/java/lang/NoSuchMethodError.class differ diff --git a/hello/stage1/java/lang/NoSuchMethodException.class b/hello/stage1/java/lang/NoSuchMethodException.class new file mode 100644 index 0000000000..2643496787 Binary files /dev/null and b/hello/stage1/java/lang/NoSuchMethodException.class differ diff --git a/hello/stage1/java/lang/NullPointerException.class b/hello/stage1/java/lang/NullPointerException.class new file mode 100644 index 0000000000..87c87e6fdb Binary files /dev/null and b/hello/stage1/java/lang/NullPointerException.class differ diff --git a/hello/stage1/java/lang/Number.class b/hello/stage1/java/lang/Number.class new file mode 100644 index 0000000000..71b65d0766 Binary files /dev/null and b/hello/stage1/java/lang/Number.class differ diff --git a/hello/stage1/java/lang/NumberFormatException.class b/hello/stage1/java/lang/NumberFormatException.class new file mode 100644 index 0000000000..cebea4bbb9 Binary files /dev/null and b/hello/stage1/java/lang/NumberFormatException.class differ diff --git a/hello/stage1/java/lang/Object.class b/hello/stage1/java/lang/Object.class new file mode 100644 index 0000000000..0b610b57b9 Binary files /dev/null and b/hello/stage1/java/lang/Object.class differ diff --git a/hello/stage1/java/lang/OutOfMemoryError.class b/hello/stage1/java/lang/OutOfMemoryError.class new file mode 100644 index 0000000000..ae9808c3f9 Binary files /dev/null and b/hello/stage1/java/lang/OutOfMemoryError.class differ diff --git a/hello/stage1/java/lang/Override.class b/hello/stage1/java/lang/Override.class new file mode 100644 index 0000000000..b11e2e0cf1 Binary files /dev/null and b/hello/stage1/java/lang/Override.class differ diff --git a/hello/stage1/java/lang/Package.class b/hello/stage1/java/lang/Package.class new file mode 100644 index 0000000000..84cac8f3e1 Binary files /dev/null and b/hello/stage1/java/lang/Package.class differ diff --git a/hello/stage1/java/lang/Process.class b/hello/stage1/java/lang/Process.class new file mode 100644 index 0000000000..ab045ca251 Binary files /dev/null and b/hello/stage1/java/lang/Process.class differ diff --git a/hello/stage1/java/lang/ReflectiveOperationException.class b/hello/stage1/java/lang/ReflectiveOperationException.class new file mode 100644 index 0000000000..dec6f208cc Binary files /dev/null and b/hello/stage1/java/lang/ReflectiveOperationException.class differ diff --git a/hello/stage1/java/lang/Runnable.class b/hello/stage1/java/lang/Runnable.class new file mode 100644 index 0000000000..b50c713c0c Binary files /dev/null and b/hello/stage1/java/lang/Runnable.class differ diff --git a/hello/stage1/java/lang/Runtime$1.class b/hello/stage1/java/lang/Runtime$1.class new file mode 100644 index 0000000000..4cdea4d0b2 Binary files /dev/null and b/hello/stage1/java/lang/Runtime$1.class differ diff --git a/hello/stage1/java/lang/Runtime$MyProcess.class b/hello/stage1/java/lang/Runtime$MyProcess.class new file mode 100644 index 0000000000..048ba7998e Binary files /dev/null and b/hello/stage1/java/lang/Runtime$MyProcess.class differ diff --git a/hello/stage1/java/lang/Runtime.class b/hello/stage1/java/lang/Runtime.class new file mode 100644 index 0000000000..53ef7dee26 Binary files /dev/null and b/hello/stage1/java/lang/Runtime.class differ diff --git a/hello/stage1/java/lang/RuntimeException.class b/hello/stage1/java/lang/RuntimeException.class new file mode 100644 index 0000000000..d8c5eaa404 Binary files /dev/null and b/hello/stage1/java/lang/RuntimeException.class differ diff --git a/hello/stage1/java/lang/RuntimePermission.class b/hello/stage1/java/lang/RuntimePermission.class new file mode 100644 index 0000000000..99807a7f3b Binary files /dev/null and b/hello/stage1/java/lang/RuntimePermission.class differ diff --git a/hello/stage1/java/lang/SecurityException.class b/hello/stage1/java/lang/SecurityException.class new file mode 100644 index 0000000000..b882c3be3f Binary files /dev/null and b/hello/stage1/java/lang/SecurityException.class differ diff --git a/hello/stage1/java/lang/SecurityManager.class b/hello/stage1/java/lang/SecurityManager.class new file mode 100644 index 0000000000..4c3e3eb752 Binary files /dev/null and b/hello/stage1/java/lang/SecurityManager.class differ diff --git a/hello/stage1/java/lang/Short.class b/hello/stage1/java/lang/Short.class new file mode 100644 index 0000000000..ebc72c4c95 Binary files /dev/null and b/hello/stage1/java/lang/Short.class differ diff --git a/hello/stage1/java/lang/StackOverflowError.class b/hello/stage1/java/lang/StackOverflowError.class new file mode 100644 index 0000000000..c0f5236840 Binary files /dev/null and b/hello/stage1/java/lang/StackOverflowError.class differ diff --git a/hello/stage1/java/lang/StackTraceElement.class b/hello/stage1/java/lang/StackTraceElement.class new file mode 100644 index 0000000000..b2e41770c2 Binary files /dev/null and b/hello/stage1/java/lang/StackTraceElement.class differ diff --git a/hello/stage1/java/lang/String$1.class b/hello/stage1/java/lang/String$1.class new file mode 100644 index 0000000000..75b115c0d5 Binary files /dev/null and b/hello/stage1/java/lang/String$1.class differ diff --git a/hello/stage1/java/lang/String.class b/hello/stage1/java/lang/String.class new file mode 100644 index 0000000000..e1828d3266 Binary files /dev/null and b/hello/stage1/java/lang/String.class differ diff --git a/hello/stage1/java/lang/StringBuffer.class b/hello/stage1/java/lang/StringBuffer.class new file mode 100644 index 0000000000..dcad67574a Binary files /dev/null and b/hello/stage1/java/lang/StringBuffer.class differ diff --git a/hello/stage1/java/lang/StringBuilder$Cell.class b/hello/stage1/java/lang/StringBuilder$Cell.class new file mode 100644 index 0000000000..9c6539dee1 Binary files /dev/null and b/hello/stage1/java/lang/StringBuilder$Cell.class differ diff --git a/hello/stage1/java/lang/StringBuilder.class b/hello/stage1/java/lang/StringBuilder.class new file mode 100644 index 0000000000..98907a3d68 Binary files /dev/null and b/hello/stage1/java/lang/StringBuilder.class differ diff --git a/hello/stage1/java/lang/SuppressWarnings.class b/hello/stage1/java/lang/SuppressWarnings.class new file mode 100644 index 0000000000..40e1d43187 Binary files /dev/null and b/hello/stage1/java/lang/SuppressWarnings.class differ diff --git a/hello/stage1/java/lang/System$Property.class b/hello/stage1/java/lang/System$Property.class new file mode 100644 index 0000000000..c063fec4f3 Binary files /dev/null and b/hello/stage1/java/lang/System$Property.class differ diff --git a/hello/stage1/java/lang/System.class b/hello/stage1/java/lang/System.class new file mode 100644 index 0000000000..2dc8cc032d Binary files /dev/null and b/hello/stage1/java/lang/System.class differ diff --git a/hello/stage1/java/lang/Thread$1.class b/hello/stage1/java/lang/Thread$1.class new file mode 100644 index 0000000000..f66decefd6 Binary files /dev/null and b/hello/stage1/java/lang/Thread$1.class differ diff --git a/hello/stage1/java/lang/Thread$State.class b/hello/stage1/java/lang/Thread$State.class new file mode 100644 index 0000000000..83bef2c01b Binary files /dev/null and b/hello/stage1/java/lang/Thread$State.class differ diff --git a/hello/stage1/java/lang/Thread$UncaughtExceptionHandler.class b/hello/stage1/java/lang/Thread$UncaughtExceptionHandler.class new file mode 100644 index 0000000000..1cc8710e94 Binary files /dev/null and b/hello/stage1/java/lang/Thread$UncaughtExceptionHandler.class differ diff --git a/hello/stage1/java/lang/Thread.class b/hello/stage1/java/lang/Thread.class new file mode 100644 index 0000000000..552e2b1919 Binary files /dev/null and b/hello/stage1/java/lang/Thread.class differ diff --git a/hello/stage1/java/lang/ThreadDeath.class b/hello/stage1/java/lang/ThreadDeath.class new file mode 100644 index 0000000000..79d53976bf Binary files /dev/null and b/hello/stage1/java/lang/ThreadDeath.class differ diff --git a/hello/stage1/java/lang/ThreadGroup.class b/hello/stage1/java/lang/ThreadGroup.class new file mode 100644 index 0000000000..9973b77273 Binary files /dev/null and b/hello/stage1/java/lang/ThreadGroup.class differ diff --git a/hello/stage1/java/lang/ThreadLocal.class b/hello/stage1/java/lang/ThreadLocal.class new file mode 100644 index 0000000000..19837d2174 Binary files /dev/null and b/hello/stage1/java/lang/ThreadLocal.class differ diff --git a/hello/stage1/java/lang/Throwable.class b/hello/stage1/java/lang/Throwable.class new file mode 100644 index 0000000000..66e28434e5 Binary files /dev/null and b/hello/stage1/java/lang/Throwable.class differ diff --git a/hello/stage1/java/lang/UnsatisfiedLinkError.class b/hello/stage1/java/lang/UnsatisfiedLinkError.class new file mode 100644 index 0000000000..ede00c23e4 Binary files /dev/null and b/hello/stage1/java/lang/UnsatisfiedLinkError.class differ diff --git a/hello/stage1/java/lang/UnsupportedOperationException.class b/hello/stage1/java/lang/UnsupportedOperationException.class new file mode 100644 index 0000000000..dc62cfb8e5 Binary files /dev/null and b/hello/stage1/java/lang/UnsupportedOperationException.class differ diff --git a/hello/stage1/java/lang/VirtualMachineError.class b/hello/stage1/java/lang/VirtualMachineError.class new file mode 100644 index 0000000000..93e295efb6 Binary files /dev/null and b/hello/stage1/java/lang/VirtualMachineError.class differ diff --git a/hello/stage1/java/lang/Void.class b/hello/stage1/java/lang/Void.class new file mode 100644 index 0000000000..d0fdac0c20 Binary files /dev/null and b/hello/stage1/java/lang/Void.class differ diff --git a/hello/stage1/java/lang/annotation/Annotation.class b/hello/stage1/java/lang/annotation/Annotation.class new file mode 100644 index 0000000000..373cf28af5 Binary files /dev/null and b/hello/stage1/java/lang/annotation/Annotation.class differ diff --git a/hello/stage1/java/lang/annotation/ElementType.class b/hello/stage1/java/lang/annotation/ElementType.class new file mode 100644 index 0000000000..a77fb229d1 Binary files /dev/null and b/hello/stage1/java/lang/annotation/ElementType.class differ diff --git a/hello/stage1/java/lang/annotation/Retention.class b/hello/stage1/java/lang/annotation/Retention.class new file mode 100644 index 0000000000..f186d42afa Binary files /dev/null and b/hello/stage1/java/lang/annotation/Retention.class differ diff --git a/hello/stage1/java/lang/annotation/RetentionPolicy.class b/hello/stage1/java/lang/annotation/RetentionPolicy.class new file mode 100644 index 0000000000..a55c765927 Binary files /dev/null and b/hello/stage1/java/lang/annotation/RetentionPolicy.class differ diff --git a/hello/stage1/java/lang/annotation/Target.class b/hello/stage1/java/lang/annotation/Target.class new file mode 100644 index 0000000000..cce190790f Binary files /dev/null and b/hello/stage1/java/lang/annotation/Target.class differ diff --git a/hello/stage1/java/lang/ref/PhantomReference.class b/hello/stage1/java/lang/ref/PhantomReference.class new file mode 100644 index 0000000000..ea42f36bfc Binary files /dev/null and b/hello/stage1/java/lang/ref/PhantomReference.class differ diff --git a/hello/stage1/java/lang/ref/Reference.class b/hello/stage1/java/lang/ref/Reference.class new file mode 100644 index 0000000000..4ed25d5800 Binary files /dev/null and b/hello/stage1/java/lang/ref/Reference.class differ diff --git a/hello/stage1/java/lang/ref/ReferenceQueue.class b/hello/stage1/java/lang/ref/ReferenceQueue.class new file mode 100644 index 0000000000..77e64ff96f Binary files /dev/null and b/hello/stage1/java/lang/ref/ReferenceQueue.class differ diff --git a/hello/stage1/java/lang/ref/SoftReference.class b/hello/stage1/java/lang/ref/SoftReference.class new file mode 100644 index 0000000000..fa76e4a2ba Binary files /dev/null and b/hello/stage1/java/lang/ref/SoftReference.class differ diff --git a/hello/stage1/java/lang/ref/WeakReference.class b/hello/stage1/java/lang/ref/WeakReference.class new file mode 100644 index 0000000000..734ed2ddef Binary files /dev/null and b/hello/stage1/java/lang/ref/WeakReference.class differ diff --git a/hello/stage1/java/lang/reflect/AccessibleObject.class b/hello/stage1/java/lang/reflect/AccessibleObject.class new file mode 100644 index 0000000000..85a684a58f Binary files /dev/null and b/hello/stage1/java/lang/reflect/AccessibleObject.class differ diff --git a/hello/stage1/java/lang/reflect/AnnotatedElement.class b/hello/stage1/java/lang/reflect/AnnotatedElement.class new file mode 100644 index 0000000000..82998ec1d2 Binary files /dev/null and b/hello/stage1/java/lang/reflect/AnnotatedElement.class differ diff --git a/hello/stage1/java/lang/reflect/Array.class b/hello/stage1/java/lang/reflect/Array.class new file mode 100644 index 0000000000..3cb58fc390 Binary files /dev/null and b/hello/stage1/java/lang/reflect/Array.class differ diff --git a/hello/stage1/java/lang/reflect/Constructor.class b/hello/stage1/java/lang/reflect/Constructor.class new file mode 100644 index 0000000000..f91fd8a355 Binary files /dev/null and b/hello/stage1/java/lang/reflect/Constructor.class differ diff --git a/hello/stage1/java/lang/reflect/Field.class b/hello/stage1/java/lang/reflect/Field.class new file mode 100644 index 0000000000..ccbe102a49 Binary files /dev/null and b/hello/stage1/java/lang/reflect/Field.class differ diff --git a/hello/stage1/java/lang/reflect/InvocationHandler.class b/hello/stage1/java/lang/reflect/InvocationHandler.class new file mode 100644 index 0000000000..99ef284a65 Binary files /dev/null and b/hello/stage1/java/lang/reflect/InvocationHandler.class differ diff --git a/hello/stage1/java/lang/reflect/InvocationTargetException.class b/hello/stage1/java/lang/reflect/InvocationTargetException.class new file mode 100644 index 0000000000..c93d5dd443 Binary files /dev/null and b/hello/stage1/java/lang/reflect/InvocationTargetException.class differ diff --git a/hello/stage1/java/lang/reflect/Member.class b/hello/stage1/java/lang/reflect/Member.class new file mode 100644 index 0000000000..c087c6be22 Binary files /dev/null and b/hello/stage1/java/lang/reflect/Member.class differ diff --git a/hello/stage1/java/lang/reflect/Method.class b/hello/stage1/java/lang/reflect/Method.class new file mode 100644 index 0000000000..bb1c983b1d Binary files /dev/null and b/hello/stage1/java/lang/reflect/Method.class differ diff --git a/hello/stage1/java/lang/reflect/Modifier.class b/hello/stage1/java/lang/reflect/Modifier.class new file mode 100644 index 0000000000..0f64a6b1aa Binary files /dev/null and b/hello/stage1/java/lang/reflect/Modifier.class differ diff --git a/hello/stage1/java/lang/reflect/Proxy.class b/hello/stage1/java/lang/reflect/Proxy.class new file mode 100644 index 0000000000..37b2b8fa65 Binary files /dev/null and b/hello/stage1/java/lang/reflect/Proxy.class differ diff --git a/hello/stage1/java/lang/reflect/Type.class b/hello/stage1/java/lang/reflect/Type.class new file mode 100644 index 0000000000..d30373b187 Binary files /dev/null and b/hello/stage1/java/lang/reflect/Type.class differ diff --git a/hello/stage1/java/net/InetAddress.class b/hello/stage1/java/net/InetAddress.class new file mode 100644 index 0000000000..11d40059e9 Binary files /dev/null and b/hello/stage1/java/net/InetAddress.class differ diff --git a/hello/stage1/java/net/InetSocketAddress.class b/hello/stage1/java/net/InetSocketAddress.class new file mode 100644 index 0000000000..b0dc56c417 Binary files /dev/null and b/hello/stage1/java/net/InetSocketAddress.class differ diff --git a/hello/stage1/java/net/JarURLConnection.class b/hello/stage1/java/net/JarURLConnection.class new file mode 100644 index 0000000000..7522808919 Binary files /dev/null and b/hello/stage1/java/net/JarURLConnection.class differ diff --git a/hello/stage1/java/net/MalformedURLException.class b/hello/stage1/java/net/MalformedURLException.class new file mode 100644 index 0000000000..1f8640028a Binary files /dev/null and b/hello/stage1/java/net/MalformedURLException.class differ diff --git a/hello/stage1/java/net/ServerSocket.class b/hello/stage1/java/net/ServerSocket.class new file mode 100644 index 0000000000..7b4f46045d Binary files /dev/null and b/hello/stage1/java/net/ServerSocket.class differ diff --git a/hello/stage1/java/net/Socket.class b/hello/stage1/java/net/Socket.class new file mode 100644 index 0000000000..20c7f8b877 Binary files /dev/null and b/hello/stage1/java/net/Socket.class differ diff --git a/hello/stage1/java/net/SocketAddress.class b/hello/stage1/java/net/SocketAddress.class new file mode 100644 index 0000000000..cb7dcbf5c9 Binary files /dev/null and b/hello/stage1/java/net/SocketAddress.class differ diff --git a/hello/stage1/java/net/SocketException.class b/hello/stage1/java/net/SocketException.class new file mode 100644 index 0000000000..53fb070a95 Binary files /dev/null and b/hello/stage1/java/net/SocketException.class differ diff --git a/hello/stage1/java/net/URL.class b/hello/stage1/java/net/URL.class new file mode 100644 index 0000000000..b1836e35d0 Binary files /dev/null and b/hello/stage1/java/net/URL.class differ diff --git a/hello/stage1/java/net/URLConnection.class b/hello/stage1/java/net/URLConnection.class new file mode 100644 index 0000000000..2c27304ce8 Binary files /dev/null and b/hello/stage1/java/net/URLConnection.class differ diff --git a/hello/stage1/java/net/URLStreamHandler.class b/hello/stage1/java/net/URLStreamHandler.class new file mode 100644 index 0000000000..bd2093d547 Binary files /dev/null and b/hello/stage1/java/net/URLStreamHandler.class differ diff --git a/hello/stage1/java/net/UnknownHostException.class b/hello/stage1/java/net/UnknownHostException.class new file mode 100644 index 0000000000..22b8a5b9d7 Binary files /dev/null and b/hello/stage1/java/net/UnknownHostException.class differ diff --git a/hello/stage1/java/net/UnknownServiceException.class b/hello/stage1/java/net/UnknownServiceException.class new file mode 100644 index 0000000000..7e8c9e78c1 Binary files /dev/null and b/hello/stage1/java/net/UnknownServiceException.class differ diff --git a/hello/stage1/java/nio/Buffer.class b/hello/stage1/java/nio/Buffer.class new file mode 100644 index 0000000000..defb201fe9 Binary files /dev/null and b/hello/stage1/java/nio/Buffer.class differ diff --git a/hello/stage1/java/nio/ByteBuffer.class b/hello/stage1/java/nio/ByteBuffer.class new file mode 100644 index 0000000000..950b900b40 Binary files /dev/null and b/hello/stage1/java/nio/ByteBuffer.class differ diff --git a/hello/stage1/java/nio/ReadOnlyBufferException.class b/hello/stage1/java/nio/ReadOnlyBufferException.class new file mode 100644 index 0000000000..48940df40b Binary files /dev/null and b/hello/stage1/java/nio/ReadOnlyBufferException.class differ diff --git a/hello/stage1/java/nio/channels/Channel.class b/hello/stage1/java/nio/channels/Channel.class new file mode 100644 index 0000000000..af21855d52 Binary files /dev/null and b/hello/stage1/java/nio/channels/Channel.class differ diff --git a/hello/stage1/java/nio/channels/Channels$InputStreamChannel.class b/hello/stage1/java/nio/channels/Channels$InputStreamChannel.class new file mode 100644 index 0000000000..fc054b6c77 Binary files /dev/null and b/hello/stage1/java/nio/channels/Channels$InputStreamChannel.class differ diff --git a/hello/stage1/java/nio/channels/Channels$MyInputStream.class b/hello/stage1/java/nio/channels/Channels$MyInputStream.class new file mode 100644 index 0000000000..2986ca7a5f Binary files /dev/null and b/hello/stage1/java/nio/channels/Channels$MyInputStream.class differ diff --git a/hello/stage1/java/nio/channels/Channels$MyOutputStream.class b/hello/stage1/java/nio/channels/Channels$MyOutputStream.class new file mode 100644 index 0000000000..f8b6c647e5 Binary files /dev/null and b/hello/stage1/java/nio/channels/Channels$MyOutputStream.class differ diff --git a/hello/stage1/java/nio/channels/Channels$OutputStreamChannel.class b/hello/stage1/java/nio/channels/Channels$OutputStreamChannel.class new file mode 100644 index 0000000000..639894aaa7 Binary files /dev/null and b/hello/stage1/java/nio/channels/Channels$OutputStreamChannel.class differ diff --git a/hello/stage1/java/nio/channels/Channels.class b/hello/stage1/java/nio/channels/Channels.class new file mode 100644 index 0000000000..b67d4e88cf Binary files /dev/null and b/hello/stage1/java/nio/channels/Channels.class differ diff --git a/hello/stage1/java/nio/channels/ClosedSelectorException.class b/hello/stage1/java/nio/channels/ClosedSelectorException.class new file mode 100644 index 0000000000..48228a2352 Binary files /dev/null and b/hello/stage1/java/nio/channels/ClosedSelectorException.class differ diff --git a/hello/stage1/java/nio/channels/GatheringByteChannel.class b/hello/stage1/java/nio/channels/GatheringByteChannel.class new file mode 100644 index 0000000000..293374d47f Binary files /dev/null and b/hello/stage1/java/nio/channels/GatheringByteChannel.class differ diff --git a/hello/stage1/java/nio/channels/ReadableByteChannel.class b/hello/stage1/java/nio/channels/ReadableByteChannel.class new file mode 100644 index 0000000000..d229a49a3e Binary files /dev/null and b/hello/stage1/java/nio/channels/ReadableByteChannel.class differ diff --git a/hello/stage1/java/nio/channels/SelectableChannel.class b/hello/stage1/java/nio/channels/SelectableChannel.class new file mode 100644 index 0000000000..f6479e3e83 Binary files /dev/null and b/hello/stage1/java/nio/channels/SelectableChannel.class differ diff --git a/hello/stage1/java/nio/channels/SelectionKey.class b/hello/stage1/java/nio/channels/SelectionKey.class new file mode 100644 index 0000000000..5e3f642daf Binary files /dev/null and b/hello/stage1/java/nio/channels/SelectionKey.class differ diff --git a/hello/stage1/java/nio/channels/Selector.class b/hello/stage1/java/nio/channels/Selector.class new file mode 100644 index 0000000000..13dd3efd13 Binary files /dev/null and b/hello/stage1/java/nio/channels/Selector.class differ diff --git a/hello/stage1/java/nio/channels/ServerSocketChannel$Handle.class b/hello/stage1/java/nio/channels/ServerSocketChannel$Handle.class new file mode 100644 index 0000000000..ec51b977f2 Binary files /dev/null and b/hello/stage1/java/nio/channels/ServerSocketChannel$Handle.class differ diff --git a/hello/stage1/java/nio/channels/ServerSocketChannel.class b/hello/stage1/java/nio/channels/ServerSocketChannel.class new file mode 100644 index 0000000000..52eff8a035 Binary files /dev/null and b/hello/stage1/java/nio/channels/ServerSocketChannel.class differ diff --git a/hello/stage1/java/nio/channels/SocketChannel$Handle.class b/hello/stage1/java/nio/channels/SocketChannel$Handle.class new file mode 100644 index 0000000000..584dfd7a02 Binary files /dev/null and b/hello/stage1/java/nio/channels/SocketChannel$Handle.class differ diff --git a/hello/stage1/java/nio/channels/SocketChannel.class b/hello/stage1/java/nio/channels/SocketChannel.class new file mode 100644 index 0000000000..9dc163aefd Binary files /dev/null and b/hello/stage1/java/nio/channels/SocketChannel.class differ diff --git a/hello/stage1/java/nio/channels/SocketSelector.class b/hello/stage1/java/nio/channels/SocketSelector.class new file mode 100644 index 0000000000..1e70697275 Binary files /dev/null and b/hello/stage1/java/nio/channels/SocketSelector.class differ diff --git a/hello/stage1/java/nio/channels/UnsupportedAddressTypeException.class b/hello/stage1/java/nio/channels/UnsupportedAddressTypeException.class new file mode 100644 index 0000000000..0e372df282 Binary files /dev/null and b/hello/stage1/java/nio/channels/UnsupportedAddressTypeException.class differ diff --git a/hello/stage1/java/nio/channels/WritableByteChannel.class b/hello/stage1/java/nio/channels/WritableByteChannel.class new file mode 100644 index 0000000000..c989de48ec Binary files /dev/null and b/hello/stage1/java/nio/channels/WritableByteChannel.class differ diff --git a/hello/stage1/java/security/AccessControlException.class b/hello/stage1/java/security/AccessControlException.class new file mode 100644 index 0000000000..952030f9df Binary files /dev/null and b/hello/stage1/java/security/AccessControlException.class differ diff --git a/hello/stage1/java/security/AccessController.class b/hello/stage1/java/security/AccessController.class new file mode 100644 index 0000000000..0cfd36c095 Binary files /dev/null and b/hello/stage1/java/security/AccessController.class differ diff --git a/hello/stage1/java/security/AllPermission.class b/hello/stage1/java/security/AllPermission.class new file mode 100644 index 0000000000..8d24e3a75a Binary files /dev/null and b/hello/stage1/java/security/AllPermission.class differ diff --git a/hello/stage1/java/security/BasicPermission.class b/hello/stage1/java/security/BasicPermission.class new file mode 100644 index 0000000000..ad0ef893b0 Binary files /dev/null and b/hello/stage1/java/security/BasicPermission.class differ diff --git a/hello/stage1/java/security/CodeSource.class b/hello/stage1/java/security/CodeSource.class new file mode 100644 index 0000000000..97b8fa0f34 Binary files /dev/null and b/hello/stage1/java/security/CodeSource.class differ diff --git a/hello/stage1/java/security/Permission.class b/hello/stage1/java/security/Permission.class new file mode 100644 index 0000000000..c18dd37a8a Binary files /dev/null and b/hello/stage1/java/security/Permission.class differ diff --git a/hello/stage1/java/security/PermissionCollection.class b/hello/stage1/java/security/PermissionCollection.class new file mode 100644 index 0000000000..444c9fab93 Binary files /dev/null and b/hello/stage1/java/security/PermissionCollection.class differ diff --git a/hello/stage1/java/security/Permissions$1.class b/hello/stage1/java/security/Permissions$1.class new file mode 100644 index 0000000000..4d6b8f736a Binary files /dev/null and b/hello/stage1/java/security/Permissions$1.class differ diff --git a/hello/stage1/java/security/Permissions$MyPermissionCollection.class b/hello/stage1/java/security/Permissions$MyPermissionCollection.class new file mode 100644 index 0000000000..040728429e Binary files /dev/null and b/hello/stage1/java/security/Permissions$MyPermissionCollection.class differ diff --git a/hello/stage1/java/security/Permissions.class b/hello/stage1/java/security/Permissions.class new file mode 100644 index 0000000000..0eca9d95ac Binary files /dev/null and b/hello/stage1/java/security/Permissions.class differ diff --git a/hello/stage1/java/security/PrivilegedAction.class b/hello/stage1/java/security/PrivilegedAction.class new file mode 100644 index 0000000000..cffde329c0 Binary files /dev/null and b/hello/stage1/java/security/PrivilegedAction.class differ diff --git a/hello/stage1/java/security/ProtectionDomain.class b/hello/stage1/java/security/ProtectionDomain.class new file mode 100644 index 0000000000..5aca5341c5 Binary files /dev/null and b/hello/stage1/java/security/ProtectionDomain.class differ diff --git a/hello/stage1/java/security/SecurityPermission.class b/hello/stage1/java/security/SecurityPermission.class new file mode 100644 index 0000000000..cf592f3277 Binary files /dev/null and b/hello/stage1/java/security/SecurityPermission.class differ diff --git a/hello/stage1/java/security/cert/Certificate.class b/hello/stage1/java/security/cert/Certificate.class new file mode 100644 index 0000000000..5e8b00734d Binary files /dev/null and b/hello/stage1/java/security/cert/Certificate.class differ diff --git a/hello/stage1/java/text/DateFormatSymbols.class b/hello/stage1/java/text/DateFormatSymbols.class new file mode 100644 index 0000000000..56891a1ea7 Binary files /dev/null and b/hello/stage1/java/text/DateFormatSymbols.class differ diff --git a/hello/stage1/java/text/FieldPosition.class b/hello/stage1/java/text/FieldPosition.class new file mode 100644 index 0000000000..13d0763e34 Binary files /dev/null and b/hello/stage1/java/text/FieldPosition.class differ diff --git a/hello/stage1/java/text/Format.class b/hello/stage1/java/text/Format.class new file mode 100644 index 0000000000..011731680d Binary files /dev/null and b/hello/stage1/java/text/Format.class differ diff --git a/hello/stage1/java/text/MessageFormat.class b/hello/stage1/java/text/MessageFormat.class new file mode 100644 index 0000000000..16f6befc8d Binary files /dev/null and b/hello/stage1/java/text/MessageFormat.class differ diff --git a/hello/stage1/java/util/AbstractCollection.class b/hello/stage1/java/util/AbstractCollection.class new file mode 100644 index 0000000000..4974eabed3 Binary files /dev/null and b/hello/stage1/java/util/AbstractCollection.class differ diff --git a/hello/stage1/java/util/AbstractList.class b/hello/stage1/java/util/AbstractList.class new file mode 100644 index 0000000000..91c7021bec Binary files /dev/null and b/hello/stage1/java/util/AbstractList.class differ diff --git a/hello/stage1/java/util/AbstractMap.class b/hello/stage1/java/util/AbstractMap.class new file mode 100644 index 0000000000..6203629db6 Binary files /dev/null and b/hello/stage1/java/util/AbstractMap.class differ diff --git a/hello/stage1/java/util/AbstractQueue.class b/hello/stage1/java/util/AbstractQueue.class new file mode 100644 index 0000000000..fab35151b7 Binary files /dev/null and b/hello/stage1/java/util/AbstractQueue.class differ diff --git a/hello/stage1/java/util/AbstractSequentialList.class b/hello/stage1/java/util/AbstractSequentialList.class new file mode 100644 index 0000000000..9fd89dda6c Binary files /dev/null and b/hello/stage1/java/util/AbstractSequentialList.class differ diff --git a/hello/stage1/java/util/AbstractSet.class b/hello/stage1/java/util/AbstractSet.class new file mode 100644 index 0000000000..dd41d8bd83 Binary files /dev/null and b/hello/stage1/java/util/AbstractSet.class differ diff --git a/hello/stage1/java/util/ArrayList.class b/hello/stage1/java/util/ArrayList.class new file mode 100644 index 0000000000..b8752a3634 Binary files /dev/null and b/hello/stage1/java/util/ArrayList.class differ diff --git a/hello/stage1/java/util/Arrays$1.class b/hello/stage1/java/util/Arrays$1.class new file mode 100644 index 0000000000..5c7773467b Binary files /dev/null and b/hello/stage1/java/util/Arrays$1.class differ diff --git a/hello/stage1/java/util/Arrays$2.class b/hello/stage1/java/util/Arrays$2.class new file mode 100644 index 0000000000..d6e90bb690 Binary files /dev/null and b/hello/stage1/java/util/Arrays$2.class differ diff --git a/hello/stage1/java/util/Arrays.class b/hello/stage1/java/util/Arrays.class new file mode 100644 index 0000000000..7656cf0d53 Binary files /dev/null and b/hello/stage1/java/util/Arrays.class differ diff --git a/hello/stage1/java/util/BitSet.class b/hello/stage1/java/util/BitSet.class new file mode 100644 index 0000000000..5a47337a94 Binary files /dev/null and b/hello/stage1/java/util/BitSet.class differ diff --git a/hello/stage1/java/util/Calendar$MyCalendar.class b/hello/stage1/java/util/Calendar$MyCalendar.class new file mode 100644 index 0000000000..b11b5e1513 Binary files /dev/null and b/hello/stage1/java/util/Calendar$MyCalendar.class differ diff --git a/hello/stage1/java/util/Calendar.class b/hello/stage1/java/util/Calendar.class new file mode 100644 index 0000000000..3ba311e638 Binary files /dev/null and b/hello/stage1/java/util/Calendar.class differ diff --git a/hello/stage1/java/util/Collection.class b/hello/stage1/java/util/Collection.class new file mode 100644 index 0000000000..0a2218b68b Binary files /dev/null and b/hello/stage1/java/util/Collection.class differ diff --git a/hello/stage1/java/util/Collections$ArrayListIterator.class b/hello/stage1/java/util/Collections$ArrayListIterator.class new file mode 100644 index 0000000000..bdaf8d85b5 Binary files /dev/null and b/hello/stage1/java/util/Collections$ArrayListIterator.class differ diff --git a/hello/stage1/java/util/Collections$IteratorEnumeration.class b/hello/stage1/java/util/Collections$IteratorEnumeration.class new file mode 100644 index 0000000000..9a98fe3dcf Binary files /dev/null and b/hello/stage1/java/util/Collections$IteratorEnumeration.class differ diff --git a/hello/stage1/java/util/Collections$KeyIterator.class b/hello/stage1/java/util/Collections$KeyIterator.class new file mode 100644 index 0000000000..6f602aa5c6 Binary files /dev/null and b/hello/stage1/java/util/Collections$KeyIterator.class differ diff --git a/hello/stage1/java/util/Collections$ReverseComparator.class b/hello/stage1/java/util/Collections$ReverseComparator.class new file mode 100644 index 0000000000..e026c9f787 Binary files /dev/null and b/hello/stage1/java/util/Collections$ReverseComparator.class differ diff --git a/hello/stage1/java/util/Collections$SynchronizedCollection.class b/hello/stage1/java/util/Collections$SynchronizedCollection.class new file mode 100644 index 0000000000..cffee6d5f3 Binary files /dev/null and b/hello/stage1/java/util/Collections$SynchronizedCollection.class differ diff --git a/hello/stage1/java/util/Collections$SynchronizedIterator.class b/hello/stage1/java/util/Collections$SynchronizedIterator.class new file mode 100644 index 0000000000..8496bc1aba Binary files /dev/null and b/hello/stage1/java/util/Collections$SynchronizedIterator.class differ diff --git a/hello/stage1/java/util/Collections$SynchronizedMap.class b/hello/stage1/java/util/Collections$SynchronizedMap.class new file mode 100644 index 0000000000..dcb0e325c7 Binary files /dev/null and b/hello/stage1/java/util/Collections$SynchronizedMap.class differ diff --git a/hello/stage1/java/util/Collections$SynchronizedSet.class b/hello/stage1/java/util/Collections$SynchronizedSet.class new file mode 100644 index 0000000000..c8a6fb7f80 Binary files /dev/null and b/hello/stage1/java/util/Collections$SynchronizedSet.class differ diff --git a/hello/stage1/java/util/Collections$UnmodifiableList.class b/hello/stage1/java/util/Collections$UnmodifiableList.class new file mode 100644 index 0000000000..a97c2ffaca Binary files /dev/null and b/hello/stage1/java/util/Collections$UnmodifiableList.class differ diff --git a/hello/stage1/java/util/Collections$UnmodifiableMap.class b/hello/stage1/java/util/Collections$UnmodifiableMap.class new file mode 100644 index 0000000000..91e15a202a Binary files /dev/null and b/hello/stage1/java/util/Collections$UnmodifiableMap.class differ diff --git a/hello/stage1/java/util/Collections$UnmodifiableSet.class b/hello/stage1/java/util/Collections$UnmodifiableSet.class new file mode 100644 index 0000000000..8da38e617c Binary files /dev/null and b/hello/stage1/java/util/Collections$UnmodifiableSet.class differ diff --git a/hello/stage1/java/util/Collections$ValueIterator.class b/hello/stage1/java/util/Collections$ValueIterator.class new file mode 100644 index 0000000000..deea7ccc0e Binary files /dev/null and b/hello/stage1/java/util/Collections$ValueIterator.class differ diff --git a/hello/stage1/java/util/Collections.class b/hello/stage1/java/util/Collections.class new file mode 100644 index 0000000000..687217a790 Binary files /dev/null and b/hello/stage1/java/util/Collections.class differ diff --git a/hello/stage1/java/util/Comparator.class b/hello/stage1/java/util/Comparator.class new file mode 100644 index 0000000000..ae986770b1 Binary files /dev/null and b/hello/stage1/java/util/Comparator.class differ diff --git a/hello/stage1/java/util/ConcurrentModificationException.class b/hello/stage1/java/util/ConcurrentModificationException.class new file mode 100644 index 0000000000..bf18e2f826 Binary files /dev/null and b/hello/stage1/java/util/ConcurrentModificationException.class differ diff --git a/hello/stage1/java/util/Date.class b/hello/stage1/java/util/Date.class new file mode 100644 index 0000000000..9a57242e88 Binary files /dev/null and b/hello/stage1/java/util/Date.class differ diff --git a/hello/stage1/java/util/Enumeration.class b/hello/stage1/java/util/Enumeration.class new file mode 100644 index 0000000000..256bb2cbf6 Binary files /dev/null and b/hello/stage1/java/util/Enumeration.class differ diff --git a/hello/stage1/java/util/EventListener.class b/hello/stage1/java/util/EventListener.class new file mode 100644 index 0000000000..7e4d9612e5 Binary files /dev/null and b/hello/stage1/java/util/EventListener.class differ diff --git a/hello/stage1/java/util/EventObject.class b/hello/stage1/java/util/EventObject.class new file mode 100644 index 0000000000..3000ea22ad Binary files /dev/null and b/hello/stage1/java/util/EventObject.class differ diff --git a/hello/stage1/java/util/HashMap$1.class b/hello/stage1/java/util/HashMap$1.class new file mode 100644 index 0000000000..65f4ff5ba5 Binary files /dev/null and b/hello/stage1/java/util/HashMap$1.class differ diff --git a/hello/stage1/java/util/HashMap$Cell.class b/hello/stage1/java/util/HashMap$Cell.class new file mode 100644 index 0000000000..bd63c5b1bd Binary files /dev/null and b/hello/stage1/java/util/HashMap$Cell.class differ diff --git a/hello/stage1/java/util/HashMap$EntrySet.class b/hello/stage1/java/util/HashMap$EntrySet.class new file mode 100644 index 0000000000..7614e6b153 Binary files /dev/null and b/hello/stage1/java/util/HashMap$EntrySet.class differ diff --git a/hello/stage1/java/util/HashMap$Helper.class b/hello/stage1/java/util/HashMap$Helper.class new file mode 100644 index 0000000000..17fbe57611 Binary files /dev/null and b/hello/stage1/java/util/HashMap$Helper.class differ diff --git a/hello/stage1/java/util/HashMap$KeySet.class b/hello/stage1/java/util/HashMap$KeySet.class new file mode 100644 index 0000000000..3c93e57983 Binary files /dev/null and b/hello/stage1/java/util/HashMap$KeySet.class differ diff --git a/hello/stage1/java/util/HashMap$MyCell.class b/hello/stage1/java/util/HashMap$MyCell.class new file mode 100644 index 0000000000..c1e6a3af44 Binary files /dev/null and b/hello/stage1/java/util/HashMap$MyCell.class differ diff --git a/hello/stage1/java/util/HashMap$MyHelper.class b/hello/stage1/java/util/HashMap$MyHelper.class new file mode 100644 index 0000000000..996940affd Binary files /dev/null and b/hello/stage1/java/util/HashMap$MyHelper.class differ diff --git a/hello/stage1/java/util/HashMap$MyIterator.class b/hello/stage1/java/util/HashMap$MyIterator.class new file mode 100644 index 0000000000..11544fc348 Binary files /dev/null and b/hello/stage1/java/util/HashMap$MyIterator.class differ diff --git a/hello/stage1/java/util/HashMap$Values.class b/hello/stage1/java/util/HashMap$Values.class new file mode 100644 index 0000000000..e9845589ec Binary files /dev/null and b/hello/stage1/java/util/HashMap$Values.class differ diff --git a/hello/stage1/java/util/HashMap.class b/hello/stage1/java/util/HashMap.class new file mode 100644 index 0000000000..7a48e58e00 Binary files /dev/null and b/hello/stage1/java/util/HashMap.class differ diff --git a/hello/stage1/java/util/HashSet$MyIterator.class b/hello/stage1/java/util/HashSet$MyIterator.class new file mode 100644 index 0000000000..8accfe9f27 Binary files /dev/null and b/hello/stage1/java/util/HashSet$MyIterator.class differ diff --git a/hello/stage1/java/util/HashSet.class b/hello/stage1/java/util/HashSet.class new file mode 100644 index 0000000000..91937d6276 Binary files /dev/null and b/hello/stage1/java/util/HashSet.class differ diff --git a/hello/stage1/java/util/Hashtable.class b/hello/stage1/java/util/Hashtable.class new file mode 100644 index 0000000000..d2f080eeff Binary files /dev/null and b/hello/stage1/java/util/Hashtable.class differ diff --git a/hello/stage1/java/util/IdentityHashMap$1.class b/hello/stage1/java/util/IdentityHashMap$1.class new file mode 100644 index 0000000000..dce92531bc Binary files /dev/null and b/hello/stage1/java/util/IdentityHashMap$1.class differ diff --git a/hello/stage1/java/util/IdentityHashMap$MyHelper.class b/hello/stage1/java/util/IdentityHashMap$MyHelper.class new file mode 100644 index 0000000000..b27b589ac9 Binary files /dev/null and b/hello/stage1/java/util/IdentityHashMap$MyHelper.class differ diff --git a/hello/stage1/java/util/IdentityHashMap.class b/hello/stage1/java/util/IdentityHashMap.class new file mode 100644 index 0000000000..71b45d38b5 Binary files /dev/null and b/hello/stage1/java/util/IdentityHashMap.class differ diff --git a/hello/stage1/java/util/Iterator.class b/hello/stage1/java/util/Iterator.class new file mode 100644 index 0000000000..c560a1f0f1 Binary files /dev/null and b/hello/stage1/java/util/Iterator.class differ diff --git a/hello/stage1/java/util/LinkedList$1.class b/hello/stage1/java/util/LinkedList$1.class new file mode 100644 index 0000000000..9a84e46627 Binary files /dev/null and b/hello/stage1/java/util/LinkedList$1.class differ diff --git a/hello/stage1/java/util/LinkedList$Cell.class b/hello/stage1/java/util/LinkedList$Cell.class new file mode 100644 index 0000000000..3d38e80082 Binary files /dev/null and b/hello/stage1/java/util/LinkedList$Cell.class differ diff --git a/hello/stage1/java/util/LinkedList$MyIterator.class b/hello/stage1/java/util/LinkedList$MyIterator.class new file mode 100644 index 0000000000..f4f253efc0 Binary files /dev/null and b/hello/stage1/java/util/LinkedList$MyIterator.class differ diff --git a/hello/stage1/java/util/LinkedList.class b/hello/stage1/java/util/LinkedList.class new file mode 100644 index 0000000000..e621a5964d Binary files /dev/null and b/hello/stage1/java/util/LinkedList.class differ diff --git a/hello/stage1/java/util/List.class b/hello/stage1/java/util/List.class new file mode 100644 index 0000000000..b4211d72df Binary files /dev/null and b/hello/stage1/java/util/List.class differ diff --git a/hello/stage1/java/util/ListIterator.class b/hello/stage1/java/util/ListIterator.class new file mode 100644 index 0000000000..06a0553208 Binary files /dev/null and b/hello/stage1/java/util/ListIterator.class differ diff --git a/hello/stage1/java/util/Locale.class b/hello/stage1/java/util/Locale.class new file mode 100644 index 0000000000..9965b4698f Binary files /dev/null and b/hello/stage1/java/util/Locale.class differ diff --git a/hello/stage1/java/util/Map$Entry.class b/hello/stage1/java/util/Map$Entry.class new file mode 100644 index 0000000000..b664a49279 Binary files /dev/null and b/hello/stage1/java/util/Map$Entry.class differ diff --git a/hello/stage1/java/util/Map.class b/hello/stage1/java/util/Map.class new file mode 100644 index 0000000000..7929c7cda0 Binary files /dev/null and b/hello/stage1/java/util/Map.class differ diff --git a/hello/stage1/java/util/MissingResourceException.class b/hello/stage1/java/util/MissingResourceException.class new file mode 100644 index 0000000000..8518cf321d Binary files /dev/null and b/hello/stage1/java/util/MissingResourceException.class differ diff --git a/hello/stage1/java/util/NoSuchElementException.class b/hello/stage1/java/util/NoSuchElementException.class new file mode 100644 index 0000000000..0fbb29e3b4 Binary files /dev/null and b/hello/stage1/java/util/NoSuchElementException.class differ diff --git a/hello/stage1/java/util/Properties$1.class b/hello/stage1/java/util/Properties$1.class new file mode 100644 index 0000000000..cb6b8b40c3 Binary files /dev/null and b/hello/stage1/java/util/Properties$1.class differ diff --git a/hello/stage1/java/util/Properties$InputStreamParser.class b/hello/stage1/java/util/Properties$InputStreamParser.class new file mode 100644 index 0000000000..1c3a524153 Binary files /dev/null and b/hello/stage1/java/util/Properties$InputStreamParser.class differ diff --git a/hello/stage1/java/util/Properties$Parser.class b/hello/stage1/java/util/Properties$Parser.class new file mode 100644 index 0000000000..7204e7a2e9 Binary files /dev/null and b/hello/stage1/java/util/Properties$Parser.class differ diff --git a/hello/stage1/java/util/Properties$ReaderParser.class b/hello/stage1/java/util/Properties$ReaderParser.class new file mode 100644 index 0000000000..0f1e6dc335 Binary files /dev/null and b/hello/stage1/java/util/Properties$ReaderParser.class differ diff --git a/hello/stage1/java/util/Properties.class b/hello/stage1/java/util/Properties.class new file mode 100644 index 0000000000..e110356c70 Binary files /dev/null and b/hello/stage1/java/util/Properties.class differ diff --git a/hello/stage1/java/util/PropertyResourceBundle.class b/hello/stage1/java/util/PropertyResourceBundle.class new file mode 100644 index 0000000000..c608d3ee73 Binary files /dev/null and b/hello/stage1/java/util/PropertyResourceBundle.class differ diff --git a/hello/stage1/java/util/Queue.class b/hello/stage1/java/util/Queue.class new file mode 100644 index 0000000000..455fd5d872 Binary files /dev/null and b/hello/stage1/java/util/Queue.class differ diff --git a/hello/stage1/java/util/Random.class b/hello/stage1/java/util/Random.class new file mode 100644 index 0000000000..3343230c13 Binary files /dev/null and b/hello/stage1/java/util/Random.class differ diff --git a/hello/stage1/java/util/RandomAccess.class b/hello/stage1/java/util/RandomAccess.class new file mode 100644 index 0000000000..b8255485ef Binary files /dev/null and b/hello/stage1/java/util/RandomAccess.class differ diff --git a/hello/stage1/java/util/ResourceBundle.class b/hello/stage1/java/util/ResourceBundle.class new file mode 100644 index 0000000000..633b0ceb77 Binary files /dev/null and b/hello/stage1/java/util/ResourceBundle.class differ diff --git a/hello/stage1/java/util/Set.class b/hello/stage1/java/util/Set.class new file mode 100644 index 0000000000..d73e2e0f34 Binary files /dev/null and b/hello/stage1/java/util/Set.class differ diff --git a/hello/stage1/java/util/SortedSet.class b/hello/stage1/java/util/SortedSet.class new file mode 100644 index 0000000000..f2cfebe315 Binary files /dev/null and b/hello/stage1/java/util/SortedSet.class differ diff --git a/hello/stage1/java/util/Stack.class b/hello/stage1/java/util/Stack.class new file mode 100644 index 0000000000..ad83ec25b0 Binary files /dev/null and b/hello/stage1/java/util/Stack.class differ diff --git a/hello/stage1/java/util/StringTokenizer.class b/hello/stage1/java/util/StringTokenizer.class new file mode 100644 index 0000000000..76fec1f698 Binary files /dev/null and b/hello/stage1/java/util/StringTokenizer.class differ diff --git a/hello/stage1/java/util/TreeMap$1.class b/hello/stage1/java/util/TreeMap$1.class new file mode 100644 index 0000000000..76d2ed42a4 Binary files /dev/null and b/hello/stage1/java/util/TreeMap$1.class differ diff --git a/hello/stage1/java/util/TreeMap$2.class b/hello/stage1/java/util/TreeMap$2.class new file mode 100644 index 0000000000..b04a335d50 Binary files /dev/null and b/hello/stage1/java/util/TreeMap$2.class differ diff --git a/hello/stage1/java/util/TreeMap$KeySet.class b/hello/stage1/java/util/TreeMap$KeySet.class new file mode 100644 index 0000000000..ade545313f Binary files /dev/null and b/hello/stage1/java/util/TreeMap$KeySet.class differ diff --git a/hello/stage1/java/util/TreeMap$MyEntry.class b/hello/stage1/java/util/TreeMap$MyEntry.class new file mode 100644 index 0000000000..85740c0727 Binary files /dev/null and b/hello/stage1/java/util/TreeMap$MyEntry.class differ diff --git a/hello/stage1/java/util/TreeMap$Values.class b/hello/stage1/java/util/TreeMap$Values.class new file mode 100644 index 0000000000..03e84aceb1 Binary files /dev/null and b/hello/stage1/java/util/TreeMap$Values.class differ diff --git a/hello/stage1/java/util/TreeMap.class b/hello/stage1/java/util/TreeMap.class new file mode 100644 index 0000000000..d541e9b6ed Binary files /dev/null and b/hello/stage1/java/util/TreeMap.class differ diff --git a/hello/stage1/java/util/TreeSet$1.class b/hello/stage1/java/util/TreeSet$1.class new file mode 100644 index 0000000000..d14035da8c Binary files /dev/null and b/hello/stage1/java/util/TreeSet$1.class differ diff --git a/hello/stage1/java/util/TreeSet$2.class b/hello/stage1/java/util/TreeSet$2.class new file mode 100644 index 0000000000..ed3882fdec Binary files /dev/null and b/hello/stage1/java/util/TreeSet$2.class differ diff --git a/hello/stage1/java/util/TreeSet$MyIterator.class b/hello/stage1/java/util/TreeSet$MyIterator.class new file mode 100644 index 0000000000..4c42cd5d9e Binary files /dev/null and b/hello/stage1/java/util/TreeSet$MyIterator.class differ diff --git a/hello/stage1/java/util/TreeSet.class b/hello/stage1/java/util/TreeSet.class new file mode 100644 index 0000000000..f669864e79 Binary files /dev/null and b/hello/stage1/java/util/TreeSet.class differ diff --git a/hello/stage1/java/util/UUID.class b/hello/stage1/java/util/UUID.class new file mode 100644 index 0000000000..604b8d540c Binary files /dev/null and b/hello/stage1/java/util/UUID.class differ diff --git a/hello/stage1/java/util/Vector.class b/hello/stage1/java/util/Vector.class new file mode 100644 index 0000000000..bd7951f8e4 Binary files /dev/null and b/hello/stage1/java/util/Vector.class differ diff --git a/hello/stage1/java/util/WeakHashMap$1.class b/hello/stage1/java/util/WeakHashMap$1.class new file mode 100644 index 0000000000..e8546e54a8 Binary files /dev/null and b/hello/stage1/java/util/WeakHashMap$1.class differ diff --git a/hello/stage1/java/util/WeakHashMap$MyCell.class b/hello/stage1/java/util/WeakHashMap$MyCell.class new file mode 100644 index 0000000000..a9dc585dd4 Binary files /dev/null and b/hello/stage1/java/util/WeakHashMap$MyCell.class differ diff --git a/hello/stage1/java/util/WeakHashMap$MyHelper.class b/hello/stage1/java/util/WeakHashMap$MyHelper.class new file mode 100644 index 0000000000..f734d36d06 Binary files /dev/null and b/hello/stage1/java/util/WeakHashMap$MyHelper.class differ diff --git a/hello/stage1/java/util/WeakHashMap.class b/hello/stage1/java/util/WeakHashMap.class new file mode 100644 index 0000000000..9bd2233f9a Binary files /dev/null and b/hello/stage1/java/util/WeakHashMap.class differ diff --git a/hello/stage1/java/util/concurrent/Callable.class b/hello/stage1/java/util/concurrent/Callable.class new file mode 100644 index 0000000000..99700a8479 Binary files /dev/null and b/hello/stage1/java/util/concurrent/Callable.class differ diff --git a/hello/stage1/java/util/concurrent/ConcurrentLinkedQueue$Node.class b/hello/stage1/java/util/concurrent/ConcurrentLinkedQueue$Node.class new file mode 100644 index 0000000000..31a5006d9d Binary files /dev/null and b/hello/stage1/java/util/concurrent/ConcurrentLinkedQueue$Node.class differ diff --git a/hello/stage1/java/util/concurrent/ConcurrentLinkedQueue.class b/hello/stage1/java/util/concurrent/ConcurrentLinkedQueue.class new file mode 100644 index 0000000000..a3a70bda1b Binary files /dev/null and b/hello/stage1/java/util/concurrent/ConcurrentLinkedQueue.class differ diff --git a/hello/stage1/java/util/jar/JarEntry.class b/hello/stage1/java/util/jar/JarEntry.class new file mode 100644 index 0000000000..406242e52d Binary files /dev/null and b/hello/stage1/java/util/jar/JarEntry.class differ diff --git a/hello/stage1/java/util/jar/JarFile$JarEntryFactory.class b/hello/stage1/java/util/jar/JarFile$JarEntryFactory.class new file mode 100644 index 0000000000..6d9bab9775 Binary files /dev/null and b/hello/stage1/java/util/jar/JarFile$JarEntryFactory.class differ diff --git a/hello/stage1/java/util/jar/JarFile$MyJarEntry.class b/hello/stage1/java/util/jar/JarFile$MyJarEntry.class new file mode 100644 index 0000000000..3381d08655 Binary files /dev/null and b/hello/stage1/java/util/jar/JarFile$MyJarEntry.class differ diff --git a/hello/stage1/java/util/jar/JarFile.class b/hello/stage1/java/util/jar/JarFile.class new file mode 100644 index 0000000000..77369d06ad Binary files /dev/null and b/hello/stage1/java/util/jar/JarFile.class differ diff --git a/hello/stage1/java/util/logging/Handler.class b/hello/stage1/java/util/logging/Handler.class new file mode 100644 index 0000000000..ee6db93941 Binary files /dev/null and b/hello/stage1/java/util/logging/Handler.class differ diff --git a/hello/stage1/java/util/logging/Level.class b/hello/stage1/java/util/logging/Level.class new file mode 100644 index 0000000000..c296aa2073 Binary files /dev/null and b/hello/stage1/java/util/logging/Level.class differ diff --git a/hello/stage1/java/util/logging/LogRecord.class b/hello/stage1/java/util/logging/LogRecord.class new file mode 100644 index 0000000000..0b32c8c336 Binary files /dev/null and b/hello/stage1/java/util/logging/LogRecord.class differ diff --git a/hello/stage1/java/util/logging/Logger$DefaultHandler.class b/hello/stage1/java/util/logging/Logger$DefaultHandler.class new file mode 100644 index 0000000000..8a0540c562 Binary files /dev/null and b/hello/stage1/java/util/logging/Logger$DefaultHandler.class differ diff --git a/hello/stage1/java/util/logging/Logger.class b/hello/stage1/java/util/logging/Logger.class new file mode 100644 index 0000000000..ce74042c80 Binary files /dev/null and b/hello/stage1/java/util/logging/Logger.class differ diff --git a/hello/stage1/java/util/regex/Matcher.class b/hello/stage1/java/util/regex/Matcher.class new file mode 100644 index 0000000000..f47b2380a9 Binary files /dev/null and b/hello/stage1/java/util/regex/Matcher.class differ diff --git a/hello/stage1/java/util/regex/Pattern.class b/hello/stage1/java/util/regex/Pattern.class new file mode 100644 index 0000000000..ed8258206c Binary files /dev/null and b/hello/stage1/java/util/regex/Pattern.class differ diff --git a/hello/stage1/java/util/zip/CRC32.class b/hello/stage1/java/util/zip/CRC32.class new file mode 100644 index 0000000000..5f6756dd4f Binary files /dev/null and b/hello/stage1/java/util/zip/CRC32.class differ diff --git a/hello/stage1/java/util/zip/DataFormatException.class b/hello/stage1/java/util/zip/DataFormatException.class new file mode 100644 index 0000000000..e9efc1cfd0 Binary files /dev/null and b/hello/stage1/java/util/zip/DataFormatException.class differ diff --git a/hello/stage1/java/util/zip/Deflater.class b/hello/stage1/java/util/zip/Deflater.class new file mode 100644 index 0000000000..a3d73bb05e Binary files /dev/null and b/hello/stage1/java/util/zip/Deflater.class differ diff --git a/hello/stage1/java/util/zip/DeflaterOutputStream.class b/hello/stage1/java/util/zip/DeflaterOutputStream.class new file mode 100644 index 0000000000..358f62b4dd Binary files /dev/null and b/hello/stage1/java/util/zip/DeflaterOutputStream.class differ diff --git a/hello/stage1/java/util/zip/Inflater.class b/hello/stage1/java/util/zip/Inflater.class new file mode 100644 index 0000000000..2c967e74a0 Binary files /dev/null and b/hello/stage1/java/util/zip/Inflater.class differ diff --git a/hello/stage1/java/util/zip/InflaterInputStream.class b/hello/stage1/java/util/zip/InflaterInputStream.class new file mode 100644 index 0000000000..3a938a5f94 Binary files /dev/null and b/hello/stage1/java/util/zip/InflaterInputStream.class differ diff --git a/hello/stage1/java/util/zip/ZipEntry.class b/hello/stage1/java/util/zip/ZipEntry.class new file mode 100644 index 0000000000..9ee0117e87 Binary files /dev/null and b/hello/stage1/java/util/zip/ZipEntry.class differ diff --git a/hello/stage1/java/util/zip/ZipFile$1.class b/hello/stage1/java/util/zip/ZipFile$1.class new file mode 100644 index 0000000000..1d7a562668 Binary files /dev/null and b/hello/stage1/java/util/zip/ZipFile$1.class differ diff --git a/hello/stage1/java/util/zip/ZipFile$EntryFactory.class b/hello/stage1/java/util/zip/ZipFile$EntryFactory.class new file mode 100644 index 0000000000..c6cc79e130 Binary files /dev/null and b/hello/stage1/java/util/zip/ZipFile$EntryFactory.class differ diff --git a/hello/stage1/java/util/zip/ZipFile$MyEntry.class b/hello/stage1/java/util/zip/ZipFile$MyEntry.class new file mode 100644 index 0000000000..719d5be2db Binary files /dev/null and b/hello/stage1/java/util/zip/ZipFile$MyEntry.class differ diff --git a/hello/stage1/java/util/zip/ZipFile$MyEnumeration.class b/hello/stage1/java/util/zip/ZipFile$MyEnumeration.class new file mode 100644 index 0000000000..f3fb35ef91 Binary files /dev/null and b/hello/stage1/java/util/zip/ZipFile$MyEnumeration.class differ diff --git a/hello/stage1/java/util/zip/ZipFile$MyInputStream.class b/hello/stage1/java/util/zip/ZipFile$MyInputStream.class new file mode 100644 index 0000000000..43ee789fc2 Binary files /dev/null and b/hello/stage1/java/util/zip/ZipFile$MyInputStream.class differ diff --git a/hello/stage1/java/util/zip/ZipFile$MyZipEntry.class b/hello/stage1/java/util/zip/ZipFile$MyZipEntry.class new file mode 100644 index 0000000000..66d3b5fd7b Binary files /dev/null and b/hello/stage1/java/util/zip/ZipFile$MyZipEntry.class differ diff --git a/hello/stage1/java/util/zip/ZipFile$Window.class b/hello/stage1/java/util/zip/ZipFile$Window.class new file mode 100644 index 0000000000..e73b7c0283 Binary files /dev/null and b/hello/stage1/java/util/zip/ZipFile$Window.class differ diff --git a/hello/stage1/java/util/zip/ZipFile$ZipEntryFactory.class b/hello/stage1/java/util/zip/ZipFile$ZipEntryFactory.class new file mode 100644 index 0000000000..f2f84c6675 Binary files /dev/null and b/hello/stage1/java/util/zip/ZipFile$ZipEntryFactory.class differ diff --git a/hello/stage1/java/util/zip/ZipFile.class b/hello/stage1/java/util/zip/ZipFile.class new file mode 100644 index 0000000000..75ce9caee7 Binary files /dev/null and b/hello/stage1/java/util/zip/ZipFile.class differ diff --git a/hello/stage1/sun/misc/Cleaner.class b/hello/stage1/sun/misc/Cleaner.class new file mode 100644 index 0000000000..afbb0c00e1 Binary files /dev/null and b/hello/stage1/sun/misc/Cleaner.class differ diff --git a/hello/stage1/sun/misc/Unsafe.class b/hello/stage1/sun/misc/Unsafe.class new file mode 100644 index 0000000000..36ad112abe Binary files /dev/null and b/hello/stage1/sun/misc/Unsafe.class differ diff --git a/hello/stage1/sun/reflect/ConstantPool.class b/hello/stage1/sun/reflect/ConstantPool.class new file mode 100644 index 0000000000..bfac6f9144 Binary files /dev/null and b/hello/stage1/sun/reflect/ConstantPool.class differ diff --git a/hello/util.o b/hello/util.o new file mode 100644 index 0000000000..f1ba661b96 Binary files /dev/null and b/hello/util.o differ diff --git a/hello/x86-asm.o b/hello/x86-asm.o new file mode 100644 index 0000000000..4f82f63fd6 Binary files /dev/null and b/hello/x86-asm.o differ diff --git a/hello/x86.o b/hello/x86.o new file mode 100644 index 0000000000..15ce72609d Binary files /dev/null and b/hello/x86.o differ diff --git a/license.txt b/license.txt index 4ed92c217a..22265643ee 100644 --- a/license.txt +++ b/license.txt @@ -1,4 +1,4 @@ -Copyright (c) 2008-2011, Avian Contributors +Copyright (c) 2008-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 diff --git a/makefile b/makefile index 5bfcd04ca9..e97c24905d 100755 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ MAKEFLAGS = -s name = avian -version = 0.5 +version = 0.6 build-arch := $(shell uname -m \ | sed 's/^i.86$$/i386/' \ @@ -18,9 +18,11 @@ build-platform := \ | sed 's/^cygwin.*$$/cygwin/') arch = $(build-arch) +target-arch = $(arch) bootimage-platform = \ $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) platform = $(bootimage-platform) +target-platform = $(platform) mode = fast process = compile @@ -31,6 +33,9 @@ endif ifneq ($(mode),fast) options := $(options)-$(mode) endif +ifneq ($(lzma),) + options := $(options)-lzma +endif ifeq ($(bootimage),true) options := $(options)-bootimage endif @@ -66,6 +71,8 @@ ifeq ($(build-platform),cygwin) native-path = cygpath -m endif +windows-path = echo + path-separator = : ifneq (,$(filter mingw32 cygwin,$(build-platform))) @@ -113,8 +120,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 @@ -131,8 +143,13 @@ endif input = List -build-cxx = g++ -build-cc = gcc +ifeq ($(use-clang),true) + build-cxx = clang -std=c++11 + build-cc = clang +else + build-cxx = g++ + build-cc = gcc +endif mflag = ifneq ($(platform),darwin) @@ -175,6 +192,8 @@ common-cflags = $(warnings) -fno-rtti -fno-exceptions \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" $(target-cflags) +asmflags = $(target-cflags) + ifneq (,$(filter i386 x86_64,$(arch))) ifeq ($(use-frame-pointer),true) common-cflags += -fno-omit-frame-pointer -DAVIAN_USE_FRAME_POINTER @@ -185,8 +204,11 @@ endif build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread -converter-cflags = -D__STDC_CONSTANT_MACROS -Isrc/binaryToObject \ - -fno-rtti -fno-exceptions +converter-cflags = -D__STDC_CONSTANT_MACROS -Isrc/binaryToObject -Isrc/ \ + -fno-rtti -fno-exceptions \ + -DAVIAN_TARGET_ARCH=AVIAN_ARCH_UNKNOWN \ + -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_UNKNOWN \ + -Wall -Wextra -Werror -Wunused-parameter -Winit-self -Wno-non-virtual-dtor cflags = $(build-cflags) @@ -210,6 +232,8 @@ so-suffix = .so shared = -shared +no-error = -Wno-error + openjdk-extra-cflags = -fvisibility=hidden bootimage-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) @@ -226,6 +250,7 @@ endif ifeq ($(arch),i386) pointer-size = 4 endif + ifeq ($(arch),powerpc) asm = powerpc pointer-size = 4 @@ -236,7 +261,6 @@ ifeq ($(arch),powerpc) ifneq ($(platform),darwin) ifneq ($(arch),$(build-arch)) - converter-cflags += -DOPPOSITE_ENDIAN cxx = powerpc-linux-gnu-g++ cc = powerpc-linux-gnu-gcc ar = powerpc-linux-gnu-ar @@ -245,9 +269,11 @@ ifeq ($(arch),powerpc) endif endif endif + ifeq ($(arch),arm) asm = arm pointer-size = 4 + ifeq ($(build-platform),darwin) ios = true else @@ -277,10 +303,6 @@ ifeq ($(ios),true) cflags += -DAVIAN_IOS endif -ifeq ($(platform),linux) - bootimage-cflags += -DTARGET_PLATFORM_LINUX -endif - ifeq ($(build-platform),darwin) build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src) cflags += -I/System/Library/Frameworks/JavaVM.framework/Headers/ @@ -288,8 +310,6 @@ ifeq ($(build-platform),darwin) endif ifeq ($(platform),darwin) - bootimage-cflags += -DTARGET_PLATFORM_DARWIN - ifeq (${OSX_SDK_SYSROOT},) OSX_SDK_SYSROOT = 10.4u endif @@ -309,8 +329,14 @@ ifeq ($(platform),darwin) version-script-flag = lflags = $(common-lflags) -ldl -framework CoreFoundation + + ifeq (,$(shell ld -v 2>&1 | grep cctools)) + lflags += -Wl,-compatibility_version,1.0.0 + endif + ifneq ($(arch),arm) - lflags += -framework CoreServices + lflags += -framework CoreServices -framework SystemConfiguration \ + -framework Security endif ifeq ($(bootimage),true) bootimage-lflags = -Wl,-segprot,__RWX,rwx,rwx @@ -322,20 +348,18 @@ ifeq ($(platform),darwin) sdk-dir = $(developer-dir)/Platforms/iPhoneOS.platform/Developer/SDKs - ios-version := $(shell if test -d $(sdk-dir)/iPhoneOS5.1.sdk; then echo 5.1; \ - elif test -d $(sdk-dir)/iPhoneOS5.0.sdk; then echo 5.0; \ - elif test -d $(sdk-dir)/iPhoneOS4.3.sdk; then echo 4.3; \ - elif test -d $(sdk-dir)/iPhoneOS4.2.sdk; then echo 4.2; \ - else echo; fi) - - ifeq ($(ios-version),) - x := $(error "couldn't find SDK for iOS version") - endif - ifeq ($(arch),arm) - ifeq ($(build-arch),powerpc) - converter-cflags += -DOPPOSITE_ENDIAN + ios-version := \ + $(shell if test -d $(sdk-dir)/iPhoneOS5.1.sdk; then echo 5.1; \ + elif test -d $(sdk-dir)/iPhoneOS5.0.sdk; then echo 5.0; \ + elif test -d $(sdk-dir)/iPhoneOS4.3.sdk; then echo 4.3; \ + elif test -d $(sdk-dir)/iPhoneOS4.2.sdk; then echo 4.2; \ + else echo; fi) + + ifeq ($(ios-version),) + x := $(error "couldn't find SDK for iOS version") endif + flags = -arch armv7 -isysroot \ $(sdk-dir)/iPhoneOS$(ios-version).sdk/ openjdk-extra-cflags += $(flags) @@ -345,9 +369,6 @@ ifeq ($(platform),darwin) endif ifeq ($(arch),powerpc) - ifneq (,$(filter i386 x86_64 arm,$(build-arch))) - converter-cflags += -DOPPOSITE_ENDIAN - endif openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} asmflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} @@ -355,9 +376,6 @@ ifeq ($(platform),darwin) endif ifeq ($(arch),i386) - ifeq ($(build-arch),powerpc) - converter-cflags += -DOPPOSITE_ENDIAN - endif openjdk-extra-cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} @@ -365,9 +383,6 @@ ifeq ($(platform),darwin) endif ifeq ($(arch),x86_64) - ifeq ($(build-arch),powerpc) - converter-cflags += -DOPPOSITE_ENDIAN - endif openjdk-extra-cflags += -arch x86_64 cflags += -arch x86_64 asmflags += -arch x86_64 @@ -376,8 +391,6 @@ ifeq ($(platform),darwin) endif ifeq ($(platform),windows) - bootimage-cflags += -DTARGET_PLATFORM_WINDOWS - inc = "$(win32)/include" lib = "$(win32)/lib" @@ -389,9 +402,8 @@ ifeq ($(platform),windows) so-suffix = .dll exe-suffix = .exe - lflags = -L$(lib) $(common-lflags) -lws2_32 -mwindows -mconsole - cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 -DTARGET_PLATFORM_WINDOWS - + 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 @@ -430,11 +442,14 @@ ifeq ($(platform),windows) strip = x86_64-w64-mingw32-strip inc = "$(win64)/include" lib = "$(win64)/lib" + else + shared += -Wl,--add-stdcall-alias endif endif ifeq ($(mode),debug) optimization-cflags = -O0 -g3 + converter-cflags += -O0 -g3 strip = : endif ifeq ($(mode),debug-fast) @@ -450,23 +465,36 @@ ifeq ($(mode),stress-major) strip = : endif ifeq ($(mode),fast) - optimization-cflags = -O3 -g3 -DNDEBUG + ifeq ($(use-clang),true) + optimization-cflags = -O4 -g3 -DNDEBUG + else + optimization-cflags = -O3 -g3 -DNDEBUG + endif use-lto = true endif ifeq ($(mode),small) - optimization-cflags = -Os -g3 -DNDEBUG + ifeq ($(use-clang),true) + optimization-cflags = -Oz -g3 -DNDEBUG + else + optimization-cflags = -Os -g3 -DNDEBUG + endif use-lto = true endif ifeq ($(use-lto),true) -# only try to use LTO when GCC 4.6.0 or greater is available - gcc-major := $(shell $(cc) -dumpversion | cut -f1 -d.) - gcc-minor := $(shell $(cc) -dumpversion | cut -f2 -d.) - ifeq ($(shell expr 4 \< $(gcc-major) \ - \| \( 4 \<= $(gcc-major) \& 6 \<= $(gcc-minor) \)),1) + ifeq ($(use-clang),true) optimization-cflags += -flto - no-lto = -fno-lto lflags += $(optimization-cflags) + else +# only try to use LTO when GCC 4.6.0 or greater is available + gcc-major := $(shell $(cc) -dumpversion | cut -f1 -d.) + gcc-minor := $(shell $(cc) -dumpversion | cut -f2 -d.) + ifeq ($(shell expr 4 \< $(gcc-major) \ + \| \( 4 \<= $(gcc-major) \& 6 \<= $(gcc-minor) \)),1) + optimization-cflags += -flto + no-lto = -fno-lto + lflags += $(optimization-cflags) + endif endif endif @@ -476,6 +504,7 @@ ifneq ($(platform),darwin) ifeq ($(arch),i386) # this is necessary to support __sync_bool_compare_and_swap: cflags += -march=i586 + lflags += -march=i586 endif endif @@ -485,8 +514,10 @@ ld := $(cc) build-ld := $(build-cc) ifdef msvc - windows-java-home := $(shell cygpath -m "$(JAVA_HOME)") - zlib := $(shell cygpath -m "$(win32)/msvc") + no-error = + windows-path = $(native-path) + windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") + zlib := $(shell $(windows-path) "$(win32)/msvc") cxx = "$(msvc)/BIN/cl.exe" cc = $(cxx) ld = "$(msvc)/BIN/link.exe" @@ -496,7 +527,12 @@ ifdef msvc -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I"$(build)" \ -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ - -DTARGET_BYTES_PER_WORD=$(pointer-size) -DTARGET_PLATFORM_WINDOWS + -DTARGET_BYTES_PER_WORD=$(pointer-size) + + ifneq ($(lzma),) + cflags += -I$(shell $(windows-path) "$(lzma)") + endif + shared = -dll lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ -DEFAULTLIB:zlib -MANIFEST -debug @@ -520,6 +556,7 @@ ifdef msvc strip = : endif +c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x))) asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x))) java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x))) @@ -582,15 +619,15 @@ ifeq ($(continuations),true) asmflags += -DAVIAN_CONTINUATIONS endif -bootimage-generator-sources = $(src)/bootimage.cpp +bootimage-generator-sources = $(src)/bootimage.cpp +ifneq ($(lzma),) + bootimage-generator-sources += $(src)/lzma-encode.cpp +endif bootimage-generator-objects = \ $(call cpp-objects,$(bootimage-generator-sources),$(src),$(build)) bootimage-generator = $(build)/bootimage-generator -bootimage-bin = $(build)/bootimage.bin bootimage-object = $(build)/bootimage-bin.o - -codeimage-bin = $(build)/codeimage.bin codeimage-object = $(build)/codeimage-bin.o ifeq ($(bootimage),true) @@ -620,20 +657,74 @@ generator-sources = \ $(src)/type-generator.cpp \ $(src)/$(build-system).cpp \ $(src)/finder.cpp + +ifneq ($(lzma),) + common-cflags += -I$(lzma) -DAVIAN_USE_LZMA -D_7ZIP_ST + + vm-sources += \ + $(src)/lzma-decode.cpp + + generator-sources += \ + $(src)/lzma-decode.cpp + + lzma-decode-sources = \ + $(lzma)/C/LzmaDec.c + + lzma-decode-objects = \ + $(call c-objects,$(lzma-decode-sources),$(lzma)/C,$(build)) + + lzma-encode-sources = \ + $(lzma)/C/LzmaEnc.c \ + $(lzma)/C/LzFind.c + + lzma-encode-objects = \ + $(call c-objects,$(lzma-encode-sources),$(lzma)/C,$(build)) + + lzma-encoder = $(build)/lzma/lzma + + lzma-encoder-cflags = -D__STDC_CONSTANT_MACROS -fno-rtti -fno-exceptions \ + -I$(lzma)/C + + lzma-encoder-sources = \ + $(src)/lzma/main.cpp + + lzma-encoder-objects = \ + $(call cpp-objects,$(lzma-encoder-sources),$(src),$(build)) + + lzma-encoder-lzma-sources = $(lzma-encode-sources) $(lzma-decode-sources) + + lzma-encoder-lzma-objects = \ + $(call generator-c-objects,$(lzma-encoder-lzma-sources),$(lzma)/C,$(build)) + + lzma-loader = $(build)/lzma/load.o +endif + generator-cpp-objects = \ $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%-build.o,$(x))) +generator-c-objects = \ + $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-build.o,$(x))) generator-objects = \ $(call generator-cpp-objects,$(generator-sources),$(src),$(build)) +generator-lzma-objects = \ + $(call generator-c-objects,$(lzma-decode-sources),$(lzma)/C,$(build)) generator = $(build)/generator -converter-objects = \ - $(build)/binaryToObject-main.o \ - $(build)/binaryToObject-elf64.o \ - $(build)/binaryToObject-elf32.o \ - $(build)/binaryToObject-mach-o64.o \ - $(build)/binaryToObject-mach-o32.o \ - $(build)/binaryToObject-pe.o -converter = $(build)/binaryToObject +converter-depends = \ + $(src)/binaryToObject/tools.h \ + $(src)/binaryToObject/endianness.h + +converter-sources = \ + $(src)/binaryToObject/tools.cpp \ + $(src)/binaryToObject/elf.cpp \ + $(src)/binaryToObject/mach-o.cpp \ + $(src)/binaryToObject/pe.cpp + +converter-tool-sources = \ + $(src)/binaryToObject/main.cpp + +converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) +converter-tool-objects = $(call cpp-objects,$(converter-tool-sources),$(src),$(build)) +converter = $(build)/binaryToObject/binaryToObject static-library = $(build)/lib$(name).a executable = $(build)/$(name)${exe-suffix} @@ -682,7 +773,10 @@ vm-classes = \ avian/*.class \ avian/resource/*.class +test-support-sources = $(shell find $(test)/avian/ -name '*.java') test-sources = $(wildcard $(test)/*.java) +test-sources += $(test-support-sources) +test-support-classes = $(call java-classes, $(test-support-sources),$(test),$(test-build)) test-classes = $(call java-classes,$(test-sources),$(test),$(test-build)) test-dep = $(test-build).dep @@ -703,6 +797,34 @@ ifeq ($(tails),true) extra.Tails endif +ifeq ($(target-arch),i386) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86 +endif + +ifeq ($(target-arch),x86_64) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86_64 +endif + +ifeq ($(target-arch),powerpc) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_POWERPC +endif + +ifeq ($(target-arch),arm) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_ARM +endif + +ifeq ($(target-platform),linux) + cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_LINUX +endif + +ifeq ($(target-platform),windows) + cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_WINDOWS +endif + +ifeq ($(target-platform),darwin) + cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_DARWIN +endif + class-name = $(patsubst $(1)/%.class,%,$(2)) class-names = $(foreach x,$(2),$(call class-name,$(1),$(x))) @@ -711,8 +833,9 @@ test-flags = -cp $(build)/test test-args = $(test-flags) $(input) .PHONY: build -build: $(static-library) $(executable) $(dynamic-library) \ - $(executable-dynamic) $(classpath-dep) $(test-dep) $(test-extra-dep) +build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \ + $(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \ + $(test-extra-dep) $(test-dep): $(classpath-dep) @@ -734,7 +857,7 @@ vg: build test: build $(library-path) /bin/sh $(test)/test.sh 2>/dev/null \ $(test-executable) $(mode) "$(test-flags)" \ - $(call class-names,$(test-build),$(test-classes)) \ + $(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \ $(continuation-tests) $(tail-tests) .PHONY: tarball @@ -802,7 +925,7 @@ $(test-extra-dep): $(test-extra-sources) define compile-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(cxx) $(cflags) -c $(<) $(call output,$(@)) + $(cxx) $(cflags) -c $$($(windows-path) $(<)) $(call output,$(@)) endef define compile-asm-object @@ -814,6 +937,11 @@ endef $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(compile-object) +$(build)/%.o: $(lzma)/C/%.c + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) $(no-error) -c $$($(windows-path) $(<)) $(call output,$(@)) + $(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S $(compile-asm-object) @@ -838,26 +966,22 @@ $(boot-object): $(boot-source) $(boot-javahome-object): $(src)/boot-javahome.cpp $(compile-object) -$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp - $(build-cxx) $(converter-cflags) -c $(^) -o $(@) +$(converter-objects) $(converter-tool-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $(converter-depends) + @mkdir -p $(dir $(@)) + $(build-cxx) $(converter-cflags) -c $(<) -o $(@) -$(build)/binaryToObject-elf64.o: $(src)/binaryToObject/elf.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) +$(converter): $(converter-objects) $(converter-tool-objects) + $(build-cc) $(^) -g -o $(@) -$(build)/binaryToObject-elf32.o: $(src)/binaryToObject/elf.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@) +$(lzma-encoder-objects): $(build)/lzma/%.o: $(src)/lzma/%.cpp + @mkdir -p $(dir $(@)) + $(build-cxx) $(lzma-encoder-cflags) -c $(<) -o $(@) -$(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) +$(lzma-encoder): $(lzma-encoder-objects) $(lzma-encoder-lzma-objects) + $(build-cc) $(^) -g -o $(@) -$(build)/binaryToObject-mach-o32.o: $(src)/binaryToObject/mach-o.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@) - -$(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp - $(build-cxx) $(converter-cflags) -c $(^) -o $(@) - -$(converter): $(converter-objects) - $(build-cc) $(^) -o $(@) +$(lzma-loader): $(src)/lzma/load.cpp + $(compile-object) $(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) @echo "creating $(@)" @@ -881,41 +1005,41 @@ $(javahome-object): $(build)/javahome.jar $(converter) $(converter) $(<) $(@) _binary_javahome_jar_start \ _binary_javahome_jar_end $(platform) $(arch) -$(generator-objects): $(generator-depends) -$(generator-objects): $(build)/%-build.o: $(src)/%.cpp +define compile-generator-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ -c $(<) -o $(@) +endef + +$(generator-objects): $(generator-depends) +$(generator-objects): $(build)/%-build.o: $(src)/%.cpp + $(compile-generator-object) + +$(build)/%-build.o: $(lzma)/C/%.c + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ + $(no-error) -c $(<) -o $(@) $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp $(compile-object) $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ - $(javahome-object) $(boot-javahome-object) + $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) @echo "creating $(@)" rm -rf $(@) $(ar) cru $(@) $(^) $(ranlib) $(@) -$(bootimage-bin): $(bootimage-generator) - $(<) $(classpath-build) $(@) $(codeimage-bin) - -$(bootimage-object): $(bootimage-bin) $(converter) - @echo "creating $(@)" - $(converter) $(<) $(@) _binary_bootimage_bin_start \ - _binary_bootimage_bin_end $(platform) $(arch) $(pointer-size) \ - writable - -$(codeimage-object): $(bootimage-bin) $(converter) - @echo "creating $(@)" - $(converter) $(codeimage-bin) $(@) _binary_codeimage_bin_start \ - _binary_codeimage_bin_end $(platform) $(arch) $(pointer-size) \ - executable +$(bootimage-object) $(codeimage-object): $(bootimage-generator) + $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ + -bootimage-symbols _binary_bootimage_bin_start:_binary_bootimage_bin_end \ + -codeimage-symbols _binary_codeimage_bin_start:_binary_codeimage_bin_end executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ - $(javahome-object) $(boot-javahome-object) + $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) $(executable): $(executable-objects) @echo "linking $(@)" @@ -934,10 +1058,13 @@ else endif $(strip) $(strip-all) $(@) -$(bootimage-generator): +$(bootimage-generator): $(bootimage-generator-objects) + echo arch=$(arch) platform=$(platform) $(MAKE) mode=$(mode) \ arch=$(build-arch) \ + target-arch=$(arch) \ platform=$(bootimage-platform) \ + target-platform=$(platform) \ openjdk=$(openjdk) \ openjdk-src=$(openjdk-src) \ bootimage-generator= \ @@ -948,7 +1075,8 @@ $(bootimage-generator): $(build-bootimage-generator): \ $(vm-objects) $(classpath-object) $(classpath-objects) \ - $(heapwalk-objects) $(bootimage-generator-objects) + $(heapwalk-objects) $(bootimage-generator-objects) $(converter-objects) \ + $(lzma-decode-objects) $(lzma-encode-objects) @echo "linking $(@)" ifeq ($(platform),windows) ifdef msvc @@ -966,7 +1094,8 @@ endif $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ - $(classpath-libraries) $(javahome-object) $(boot-javahome-object) + $(classpath-libraries) $(javahome-object) $(boot-javahome-object) \ + $(lzma-decode-objects) @echo "linking $(@)" ifdef msvc $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ @@ -992,7 +1121,7 @@ else endif $(strip) $(strip-all) $(@) -$(generator): $(generator-objects) +$(generator): $(generator-objects) $(generator-lzma-objects) @echo "linking $(@)" $(build-ld) $(^) $(build-lflags) -o $(@) @@ -1001,6 +1130,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,$(@)) @@ -1031,6 +1172,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 $(@) @@ -1042,6 +1219,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..fbbce2e5e8 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,13 +230,16 @@ 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 \ -Ds6_bytes=_s6_bytes else openjdk-sources += \ - $(openjdk-src)/solaris/native/common/jdk_util_md.c \ + $(shell find $(openjdk-src)/solaris/native/common -name '*.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 +270,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,19 +298,54 @@ 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/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" \ + "-I$(openjdk-src)/solaris/native/common/deps/fontconfig2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gtk2" \ + $(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 -c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-openjdk.o,$(x))) +openjdk-c-objects = \ + $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-openjdk.o,$(x))) openjdk-objects = \ - $(call c-objects,$(openjdk-sources),$(openjdk-src),$(build)/openjdk) + $(call openjdk-c-objects,$(openjdk-sources),$(openjdk-src),$(build)/openjdk) openjdk-local-objects = \ - $(call c-objects,$(openjdk-local-sources),$(src)/openjdk,$(build)/openjdk) + $(call openjdk-c-objects,$(openjdk-local-sources),$(src)/openjdk,$(build)/openjdk) openjdk-headers-dep = $(build)/openjdk/headers.dep diff --git a/openjdk.pro b/openjdk.pro index dd9e07a910..8207016de5 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 { @@ -108,6 +114,9 @@ private long handle; } +-keep class java.net.NetworkInterface { + ; + } -keep class java.net.InetAddress { ; } @@ -217,3 +226,21 @@ -keep class sun.util.resources.TimeZoneNames -keep class sun.text.resources.FormatData +# loaded via reflection from DefaultFileSystemProvider: +-keep class sun.nio.fs.LinuxFileSystemProvider +-keep class sun.nio.fs.BsdFileSystemProvider + +# loaded via JNI in UnixNativeDispatcher.c: +-keep class sun.nio.fs.UnixFileAttributes { + ; +} +-keep class sun.nio.fs.UnixFileStoreAttributes { + ; +} +-keep class sun.nio.fs.UnixMountEntry { + ; +} + +-keep class sun.nio.fs.UnixException { + UnixException(int); + } diff --git a/readme.txt b/readme.txt index a81b6b2693..e9185b2c85 100644 --- a/readme.txt +++ b/readme.txt @@ -54,7 +54,7 @@ Avian can currently target the following platforms: Linux (i386, x86_64, ARM, and 32-bit PowerPC) Windows (i386 and x86_64) Mac OS X (i386, x86_64 and 32-bit PowerPC) - + Apple iOS (i386 and ARM) Building -------- @@ -63,6 +63,7 @@ Build requirements include: * GNU make 3.80 or later * GCC 3.4 or later (4.5.1 or later for Windows/x86_64) + or LLVM Clang 3.1 or later (see use-clang option below) * JDK 1.5 or later * MinGW 3.4 or later (only if compiling for Windows) * zlib 1.2.3 or later @@ -78,10 +79,13 @@ certain flags described below, all of which are optional. arch={i386,x86_64,powerpc,arm} \ process={compile,interpret} \ mode={debug,debug-fast,fast,small} \ + lzma= \ + ios={true,false} \ bootimage={true,false} \ heapdump={true,false} \ tails={true,false} \ continuations={true,false} \ + use-clang={true,false} \ openjdk= \ openjdk-src= @@ -93,13 +97,27 @@ certain flags described below, all of which are optional. default: output of $(uname -m), normalized in some cases (e.g. i686 -> i386) + * process - choice between pure interpreter or JIT compiler + default: compile + * mode - which set of compilation flags to use to determine optimization level, debug symbols, and whether to enable assertions default: fast - * process - choice between pure interpreter or JIT compiler - default: compile + * lzma - if set, support use of LZMA to compress embedded JARs and + boot images. The value of this option should be a directory + containing a recent LZMA SDK (available at + http://www.7-zip.org/sdk.html). Currently, only version 9.20 of + the SDK has been tested, but other versions might work. + default: not set + + * ios - if true, cross-compile for iOS on OS X. Note that + non-jailbroken iOS devices do not allow JIT compilation, so only + process=interpret or bootimage=true builds will run on such + devices. See https://github.com/ReadyTalk/hello-ios for an + example of an Xcode project for iOS which uses Avian. + default: false * bootimage - if true, create a boot image containing the pre-parsed class library and ahead-of-time compiled methods. This option is @@ -126,6 +144,11 @@ certain flags described below, all of which are optional. only valid for process=compile builds. default: false + * use-clang - if true, use LLVM's clang instead of GCC to build. + Note that this does not currently affect cross compiles, only + native builds. + default: false + * openjdk - if set, use OpenJDK class library instead of the default Avian class library. See "Building with the OpenJDK Class Library" below for details. @@ -220,11 +243,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 +258,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 +283,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 +294,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 @@ -356,15 +374,27 @@ EOF Step 3: Make an object file out of the jar. - $ ../build/${platform}-${arch}/binaryToObject boot.jar boot-jar.o \ - _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch} + $ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar \ + boot-jar.o _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch} + +If you've built Avian using the lzma option, you may optionally +compress the jar before generating the object: + + $ ../build/$(platform}-${arch}-lzma/lzma/lzma encode boot.jar boot.jar.lzma + && ../build/${platform}-${arch}-lzma/binaryToObject/binaryToObject \ + boot.jar.lzma boot-jar.o _binary_boot_jar_start _binary_boot_jar_end \ + ${platform} ${arch} + +Note that you'll need to specify "-Xbootclasspath:[lzma:bootJar]" +instead of "-Xbootclasspath:[bootJar]" in the next step if you've used +LZMA to compress the jar. Step 4: Write a driver which starts the VM and runs the desired main 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 <allocate(size); +} + #endif//ALLOCATOR_H diff --git a/src/arm.cpp b/src/arm.cpp index af1c6398a2..4f7c74b7d4 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -21,6 +21,10 @@ using namespace vm; namespace { namespace isa { +// SYSTEM REGISTERS +const int FPSID = 0x0; +const int FPSCR = 0x1; +const int FPEXC = 0x8; // INSTRUCTION OPTIONS enum CONDITION { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV }; enum SHIFTOP { LSL, LSR, ASR, ROR }; @@ -51,6 +55,14 @@ inline int SWI(int cond, int imm) { return cond<<28 | 0x0f<<24 | (imm&0xffffff); } inline int SWAP(int cond, int B, int Rn, int Rd, int Rm) { return cond<<28 | 1<<24 | B<<22 | Rn<<16 | Rd<<12 | 9<<4 | Rm; } +inline int COOP(int cond, int opcode_1, int CRn, int CRd, int cp_num, int opcode_2, int CRm) +{ return cond<<28 | 0xe<<24 | opcode_1<<20 | CRn<<16 | CRd<<12 | cp_num<<8 | opcode_2<<5 | CRm; } +inline int COXFER(int cond, int P, int U, int N, int W, int L, int Rn, int CRd, int cp_num, int offset) // offset is in words, not bytes +{ return cond<<28 | 0x6<<25 | P<<24 | U<<23 | N<<22 | W<<21 | L<<20 | Rn<<16 | CRd<<12 | cp_num<<8 | (offset&0xff)>>2; } +inline int COREG(int cond, int opcode_1, int L, int CRn, int Rd, int cp_num, int opcode_2, int CRm) +{ return cond<<28 | 0xe<<24 | opcode_1<<21 | L<<20 | CRn<<16 | Rd<<12 | cp_num<<8 | opcode_2<<5 | 1<<4 | CRm; } +inline int COREG2(int cond, int L, int Rn, int Rd, int cp_num, int opcode, int CRm) +{ return cond<<28 | 0xc4<<20 | L<<20 | Rn<<16 | Rd<<12 | cp_num<<8 | opcode<<4 | CRm;} // FIELD CALCULATORS inline int calcU(int imm) { return imm >= 0 ? 1 : 0; } // INSTRUCTIONS @@ -115,6 +127,99 @@ inline int ldmfd(int Rn, int rlist) { return BLOCKXFER(AL, 0, 1, 0, 1, 1, Rn, rl inline int stmfd(int Rn, int rlist) { return BLOCKXFER(AL, 1, 0, 0, 1, 0, Rn, rlist); } inline int swp(int Rd, int Rm, int Rn) { return SWAP(AL, 0, Rn, Rd, Rm); } inline int swpb(int Rd, int Rm, int Rn) { return SWAP(AL, 1, Rn, Rd, Rm); } +// breakpoint instruction, this really has its own instruction format +inline int bkpt(int16_t immed) { return 0xe1200070 | (((unsigned)immed & 0xffff) >> 4 << 8) | (immed & 0xf); } +// COPROCESSOR INSTRUCTIONS +inline int cdp(int coproc, int opcode_1, int CRd, int CRn, int CRm, int opcode_2) { return COOP(AL, opcode_1, CRn, CRd, coproc, opcode_2, CRm); } +inline int mcr(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm); } +inline int mcrr(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm); } +inline int mrc(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm); } +inline int mrrc(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm); } +inline int ldc(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 0, W, 1, Rn, CRd, coproc, offset); } +inline int ldcl(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 1, W, 1, Rn, CRd, coproc, offset); } +inline int stc(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 0, W, 0, Rn, CRd, coproc, offset); } +inline int stcl(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 1, W, 0, Rn, CRd, coproc, offset); } +// VFP FLOATING-POINT INSTRUCTIONS +inline int fmacs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fnmacs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } +inline int fmscs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|1, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fnmscs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|1, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } +inline int fmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fnmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } +inline int fadds(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fsubs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } +inline int fdivs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|8, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fmacd(int Dd, int Dn, int Dm) { return COOP(AL, 0, Dn, Dd, 11, 0, Dm); } +inline int fnmacd(int Dd, int Dn, int Dm) { return COOP(AL, 0, Dn, Dd, 11, 2, Dm); } +inline int fmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 0, Dm); } +inline int fnmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 2, Dm); } +inline int fmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 0, Dm); } +inline int fnmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 2, Dm); } +inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); } +inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); } +inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); } +inline int fcpys(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fabss(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fnegs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fsqrts(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fcmps(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fcmpes(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fcmpzs(int Sd) { return COOP(AL, 0xb|(Sd&1)<<2, 5, Sd>>1, 10, 2, 0); } +inline int fcmpezs(int Sd) { return COOP(AL, 0xb|(Sd&1)<<2, 5, Sd>>1, 10, 6, 0); } +inline int fcvtds(int Dd, int Sm) { return COOP(AL, 0xb, 7, Dd, 10, 6|(Sm&1), Sm>>1); } +inline int fuitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fsitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int ftouis(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int ftouizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int ftosis(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int ftosizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fcpyd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); } +inline int fabsd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); } +inline int fnegd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); } +inline int fsqrtd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 6, Dm); } +// double-precision comparison instructions +inline int fcmpd(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); } +inline int fcmped(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 6, Dm); } +inline int fcmpzd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 2, 0); } +inline int fcmpezd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 6, 0); } +// double-precision conversion instructions +inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 7, Sd>>1, 11, 6, Dm); } +inline int fuitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 2|(Sm&1), Sm>>1); } +inline int fsitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 6|(Sm&1), Sm>>1); } +inline int ftouid(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 11, 2, Dm); } +inline int ftouizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 11, 6, Dm); } +inline int ftosid(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 2, Dm); } +inline int ftosizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 6, Dm); } +// these are the multiple load/store analogs for VFP, useless for now +inline int fldms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, count); } +inline int fldmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1); } +inline int fldmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1|1); } +inline int fstms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, count); } +inline int fstmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, count<<1); } +inline int fstmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, count<<1|1); } +// single load/store instructions for both precision types +inline int flds(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); }; +inline int fldd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); }; +inline int fsts(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); }; +inline int fstd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset); }; +// move between GPRs and FPRs +inline int fmsr(int Sn, int Rd) { return mcr(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } +inline int fmrs(int Rd, int Sn) { return mrc(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } +/* move to/from the low/high parts of double-precision registers, + seemingly redundant */ +inline int fmdlr(int Dn, int Rd) { return mcr(11, 0, Rd, Dn, 0); } +inline int fmrdl(int Rd, int Dn) { return mrc(11, 0, Rd, Dn, 0); } +inline int fmdhr(int Dn, int Rd) { return mcr(11, 1, Rd, Dn, 0); } +inline int fmrdh(int Rd, int Dn) { return mrc(11, 1, Rd, Dn, 0); } +// move to/from VFP system registers +inline int fmxr(int reg, int Rd) { return mcr(10, 7, Rd, reg, 0); } +inline int fmrx(int Rd, int reg) { return mrc(10, 7, Rd, reg, 0); } +// these move around pairs of single-precision registers +inline int fmsrr(int Sm, int Rd, int Rn) { return mcrr(10, 1 | ((Sm&1)<<1), Rd, Rn, Sm>>1); } +inline int fmrrs(int Rd, int Rn, int Sm) { return mrrc(10, 1 | ((Sm&1)<<1), Rd, Rn, Sm>>1); } +inline int fmdrr(int Dm, int Rd, int Rn) { return mcrr(11, 1, Rd, Rn, Dm); } +inline int fmrrd(int Rd, int Rn, int Dm) { return mrrc(11, 1, Rd, Rn, Dm); } +// FLAG SETTERS inline int SETCOND(int ins, int cond) { return ((ins&0x0fffffff) | (cond<<28)); } inline int SETS(int ins) { return ins | 1<<20; } // PSEUDO-INSTRUCTIONS @@ -136,6 +241,12 @@ inline int ble(int offset) { return SETCOND(b(offset), LE); } inline int bge(int offset) { return SETCOND(b(offset), GE); } inline int blo(int offset) { return SETCOND(b(offset), CC); } inline int bhs(int offset) { return SETCOND(b(offset), CS); } +inline int bpl(int offset) { return SETCOND(b(offset), PL); } +inline int fmstat() { return fmrx(15, FPSCR); } +// HARDWARE FLAGS +bool vfpSupported() { + return true; // TODO +} } const uint64_t MASK_LO32 = 0xffffffff; @@ -149,10 +260,10 @@ inline unsigned lo8(int64_t i) { return (unsigned)(i&MASK_LO8); } inline unsigned hi8(int64_t i) { return lo8(i>>8); } inline int ha16(int32_t i) { - return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff; + return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff; } inline int unha16(int32_t high, int32_t low) { - return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low; + return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low; } inline bool isInt8(target_intptr_t v) { return v == static_cast(v); } @@ -164,6 +275,24 @@ inline int carry16(target_intptr_t v) { return static_cast(v) < 0 ? 1 : inline bool isOfWidth(int64_t i, int size) { return static_cast(i) >> size == 0; } inline bool isOfWidth(int i, int size) { return static_cast(i) >> size == 0; } +const int N_GPRS = 16; +const int N_FPRS = 16; +const uint32_t GPR_MASK = 0xffff; +const uint32_t FPR_MASK = 0xffff0000; +// for source-to-destination masks +const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32; +// making the following const somehow breaks debug symbol output in GDB +/* const */ uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32; + +inline bool isFpr(Assembler::Register* reg) { + return reg->low >= N_GPRS; +} + +inline int fpr64(int reg) { return reg - N_GPRS; } +inline int fpr64(Assembler::Register* reg) { return fpr64(reg->low); } +inline int fpr32(int reg) { return fpr64(reg) << 1; } +inline int fpr32(Assembler::Register* reg) { return fpr64(reg) << 1; } + const unsigned FrameHeaderSize = 1; const unsigned StackAlignmentInBytes = 8; @@ -227,7 +356,7 @@ class Context { public: Context(System* s, Allocator* a, Zone* zone): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(this, 0)), + firstBlock(new(zone) MyBlock(this, 0)), lastBlock(firstBlock), poolOffsetHead(0), poolOffsetTail(0), constantPool(0), constantPoolCount(0) { } @@ -250,7 +379,7 @@ class Task { public: Task(Task* next): next(next) { } - virtual void run(Context* c) = 0; + virtual void run(Context* con) = 0; Task* next; }; @@ -287,41 +416,41 @@ class ArchitectureContext { }; inline void NO_RETURN -abort(Context* c) +abort(Context* con) { - abort(c->s); + abort(con->s); } inline void NO_RETURN -abort(ArchitectureContext* c) +abort(ArchitectureContext* con) { - abort(c->s); + abort(con->s); } #ifndef NDEBUG inline void -assert(Context* c, bool v) +assert(Context* con, bool v) { - assert(c->s, v); + assert(con->s, v); } inline void -assert(ArchitectureContext* c, bool v) +assert(ArchitectureContext* con, bool v) { - assert(c->s, v); + assert(con->s, v); } #endif // not NDEBUG inline void -expect(Context* c, bool v) +expect(Context* con, bool v) { - expect(c->s, v); + expect(con->s, v); } class Offset: public Promise { public: - Offset(Context* c, MyBlock* block, unsigned offset, bool forTrace): - c(c), block(block), offset(offset), forTrace(forTrace) + Offset(Context* con, MyBlock* block, unsigned offset, bool forTrace): + con(con), block(block), offset(offset), forTrace(forTrace) { } virtual bool resolved() { @@ -329,24 +458,23 @@ class Offset: public Promise { } virtual int64_t value() { - assert(c, resolved()); + assert(con, resolved()); unsigned o = offset - block->offset; return block->start + padding (block, forTrace ? o - TargetBytesPerWord : o) + o; } - Context* c; + Context* con; MyBlock* block; unsigned offset; bool forTrace; }; Promise* -offset(Context* c, bool forTrace = false) +offset(Context* con, bool forTrace = false) { - return new (c->zone->allocate(sizeof(Offset))) - Offset(c, c->lastBlock, c->code.length(), forTrace); + return new(con->zone) Offset(con, con->lastBlock, con->code.length(), forTrace); } bool @@ -396,13 +524,13 @@ class OffsetTask: public Task { instructionOffset(instructionOffset) { } - virtual void run(Context* c) { + virtual void run(Context* con) { if (promise->resolved()) { updateOffset - (c->s, c->result + instructionOffset->value(), promise->value()); + (con->s, con->result + instructionOffset->value(), promise->value()); } else { new (promise->listen(sizeof(OffsetListener))) - OffsetListener(c->s, c->result + instructionOffset->value()); + OffsetListener(con->s, con->result + instructionOffset->value()); } } @@ -411,10 +539,9 @@ class OffsetTask: public Task { }; void -appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset) +appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset) { - c->tasks = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask - (c->tasks, promise, instructionOffset); + con->tasks = new(con->zone) OffsetTask(con->tasks, promise, instructionOffset); } inline unsigned @@ -447,17 +574,17 @@ isFloatBranch(TernaryOperation op) } inline unsigned -index(ArchitectureContext* c UNUSED, +index(ArchitectureContext* con UNUSED, TernaryOperation operation, OperandType operand1) { - assert(c, not isBranch(operation)); + assert(con, not isBranch(operation)); return operation + (NonBranchTernaryOperationCount * operand1); } unsigned -branchIndex(ArchitectureContext* c UNUSED, OperandType operand1, +branchIndex(ArchitectureContext* con UNUSED, OperandType operand1, OperandType operand2) { return operand1 + (OperandTypeCount * operand2); @@ -469,9 +596,37 @@ using namespace isa; // shortcut functions inline void emit(Context* con, int code) { con->code.append4(code); } -inline int newTemp(Context* con) { return con->client->acquireTemporary(); } -inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); } -inline int64_t getValue(Assembler::Constant* c) { return c->value->value(); } + +inline int newTemp(Context* con) { + return con->client->acquireTemporary(GPR_MASK); +} + +inline int newTemp(Context* con, unsigned mask) { + return con->client->acquireTemporary(mask); +} + +inline void freeTemp(Context* con, int r) { + con->client->releaseTemporary(r); +} + +inline int64_t getValue(Assembler::Constant* con) { + return con->value->value(); +} + +inline Assembler::Register makeTemp(Context* con) { + Assembler::Register tmp(newTemp(con)); + return tmp; +} + +inline Assembler::Register makeTemp64(Context* con) { + Assembler::Register tmp(newTemp(con), newTemp(con)); + return tmp; +} + +inline void freeTemp(Context* con, const Assembler::Register& tmp) { + if (tmp.low != NoRegister) freeTemp(con, tmp.low); + if (tmp.high != NoRegister) freeTemp(con, tmp.high); +} inline void write4(uint8_t* dst, uint32_t v) @@ -549,14 +704,14 @@ void unsignedShiftRightC(Context* con, unsigned size UNUSED, Assembler::Constant class ConstantPoolEntry: public Promise { public: - ConstantPoolEntry(Context* c, Promise* constant, ConstantPoolEntry* next, + ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next, Promise* callOffset): - c(c), constant(constant), next(next), callOffset(callOffset), + con(con), constant(constant), next(next), callOffset(callOffset), address(0) { } virtual int64_t value() { - assert(c, resolved()); + assert(con, resolved()); return reinterpret_cast(address); } @@ -565,7 +720,7 @@ class ConstantPoolEntry: public Promise { return address != 0; } - Context* c; + Context* con; Promise* constant; ConstantPoolEntry* next; Promise* callOffset; @@ -622,42 +777,38 @@ class PoolEvent { }; void -appendConstantPoolEntry(Context* c, Promise* constant, Promise* callOffset) +appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset) { if (constant->resolved()) { // make a copy, since the original might be allocated on the // stack, and we need our copy to live until assembly is complete - constant = new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(constant->value()); + constant = new(con->zone) ResolvedPromise(constant->value()); } - c->constantPool = new (c->zone->allocate(sizeof(ConstantPoolEntry))) - ConstantPoolEntry(c, constant, c->constantPool, callOffset); + con->constantPool = new(con->zone) ConstantPoolEntry(con, constant, con->constantPool, callOffset); - ++ c->constantPoolCount; + ++ con->constantPoolCount; - PoolOffset* o = new (c->zone->allocate(sizeof(PoolOffset))) PoolOffset - (c->lastBlock, c->constantPool, c->code.length() - c->lastBlock->offset); + PoolOffset* o = new(con->zone) PoolOffset(con->lastBlock, con->constantPool, con->code.length() - con->lastBlock->offset); if (DebugPool) { fprintf(stderr, "add pool offset %p %d to block %p\n", - o, o->offset, c->lastBlock); + o, o->offset, con->lastBlock); } - if (c->lastBlock->poolOffsetTail) { - c->lastBlock->poolOffsetTail->next = o; + if (con->lastBlock->poolOffsetTail) { + con->lastBlock->poolOffsetTail->next = o; } else { - c->lastBlock->poolOffsetHead = o; + con->lastBlock->poolOffsetHead = o; } - c->lastBlock->poolOffsetTail = o; + con->lastBlock->poolOffsetTail = o; } void -appendPoolEvent(Context* c, MyBlock* b, unsigned offset, PoolOffset* head, +appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head, PoolOffset* tail) { - PoolEvent* e = new (c->zone->allocate(sizeof(PoolEvent))) PoolEvent - (head, tail, offset); + PoolEvent* e = new(con->zone) PoolEvent(head, tail, offset); if (b->poolEventTail) { b->poolEventTail->next = e; @@ -695,24 +846,24 @@ padding(MyBlock* b, unsigned offset) void resolve(MyBlock* b) { - Context* c = b->context; + Context* con = b->context; if (b->poolOffsetHead) { - if (c->poolOffsetTail) { - c->poolOffsetTail->next = b->poolOffsetHead; + if (con->poolOffsetTail) { + con->poolOffsetTail->next = b->poolOffsetHead; } else { - c->poolOffsetHead = b->poolOffsetHead; + con->poolOffsetHead = b->poolOffsetHead; } - c->poolOffsetTail = b->poolOffsetTail; + con->poolOffsetTail = b->poolOffsetTail; } - if (c->poolOffsetHead) { + if (con->poolOffsetHead) { bool append; if (b->next == 0 or b->next->poolEventHead) { append = true; } else { int32_t v = (b->start + b->size + b->next->size + TargetBytesPerWord - 8) - - (c->poolOffsetHead->offset + c->poolOffsetHead->block->start); + - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); append = (v != (v & PoolOffsetMask)); @@ -723,138 +874,170 @@ resolve(MyBlock* b) b->next->size); fprintf(stderr, "offset %p %d is of distance %d to next block; append? %d\n", - c->poolOffsetHead, c->poolOffsetHead->offset, v, append); + con->poolOffsetHead, con->poolOffsetHead->offset, v, append); } } if (append) { #ifndef NDEBUG int32_t v = (b->start + b->size - 8) - - (c->poolOffsetHead->offset + c->poolOffsetHead->block->start); + - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); - expect(c, v == (v & PoolOffsetMask)); + expect(con, v == (v & PoolOffsetMask)); #endif // not NDEBUG - appendPoolEvent(c, b, b->size, c->poolOffsetHead, c->poolOffsetTail); + appendPoolEvent(con, b, b->size, con->poolOffsetHead, con->poolOffsetTail); if (DebugPool) { - for (PoolOffset* o = c->poolOffsetHead; o; o = o->next) { + for (PoolOffset* o = con->poolOffsetHead; o; o = o->next) { fprintf(stderr, "include %p %d in pool event %p at offset %d in block %p\n", o, o->offset, b->poolEventTail, b->size, b); } } - c->poolOffsetHead = 0; - c->poolOffsetTail = 0; + con->poolOffsetHead = 0; + con->poolOffsetTail = 0; } } } void -jumpR(Context* c, unsigned size UNUSED, Assembler::Register* target) +jumpR(Context* con, unsigned size UNUSED, Assembler::Register* target) { - assert(c, size == TargetBytesPerWord); - emit(c, bx(target->low)); + assert(con, size == TargetBytesPerWord); + emit(con, bx(target->low)); } void -moveRR(Context* c, unsigned srcSize, Assembler::Register* src, +moveRR(Context* con, unsigned srcSize, Assembler::Register* src, unsigned dstSize, Assembler::Register* dst); void -swapRR(Context* c, unsigned aSize, Assembler::Register* a, +swapRR(Context* con, unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Register* b) { - assert(c, aSize == TargetBytesPerWord); - assert(c, bSize == TargetBytesPerWord); + assert(con, aSize == TargetBytesPerWord); + assert(con, bSize == TargetBytesPerWord); - Assembler::Register tmp(c->client->acquireTemporary()); - moveRR(c, aSize, a, bSize, &tmp); - moveRR(c, bSize, b, aSize, a); - moveRR(c, bSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveRR(con, aSize, a, bSize, &tmp); + moveRR(con, bSize, b, aSize, a); + moveRR(con, bSize, &tmp, bSize, b); + con->client->releaseTemporary(tmp.low); } void -moveRR(Context* c, unsigned srcSize, Assembler::Register* src, +moveRR(Context* con, unsigned srcSize, Assembler::Register* src, unsigned dstSize, Assembler::Register* dst) { + bool srcIsFpr = isFpr(src); + bool dstIsFpr = isFpr(dst); + if (srcIsFpr || dstIsFpr) { // FPR(s) involved + assert(con, srcSize == dstSize); + const bool dprec = srcSize == 8; + if (srcIsFpr && dstIsFpr) { // FPR to FPR + if (dprec) emit(con, fcpyd(fpr64(dst), fpr64(src))); // double + else emit(con, fcpys(fpr32(dst), fpr32(src))); // single + } else if (srcIsFpr) { // FPR to GPR + if (dprec) emit(con, fmrrd(dst->low, dst->high, fpr64(src))); + else emit(con, fmrs(dst->low, fpr32(src))); + } else { // GPR to FPR + if (dprec) emit(con, fmdrr(fpr64(dst->low), src->low, src->high)); + else emit(con, fmsr(fpr32(dst), src->low)); + } + return; + } + switch (srcSize) { case 1: - emit(c, lsli(dst->low, src->low, 24)); - emit(c, asri(dst->low, dst->low, 24)); + emit(con, lsli(dst->low, src->low, 24)); + emit(con, asri(dst->low, dst->low, 24)); break; - + case 2: - emit(c, lsli(dst->low, src->low, 16)); - emit(c, asri(dst->low, dst->low, 16)); + emit(con, lsli(dst->low, src->low, 16)); + emit(con, asri(dst->low, dst->low, 16)); break; - + case 4: case 8: if (srcSize == 4 and dstSize == 8) { - moveRR(c, 4, src, 4, dst); - emit(c, asri(dst->high, src->low, 31)); + moveRR(con, 4, src, 4, dst); + emit(con, asri(dst->high, src->low, 31)); } else if (srcSize == 8 and dstSize == 8) { Assembler::Register srcHigh(src->high); Assembler::Register dstHigh(dst->high); if (src->high == dst->low) { if (src->low == dst->high) { - swapRR(c, 4, src, 4, dst); + swapRR(con, 4, src, 4, dst); } else { - moveRR(c, 4, &srcHigh, 4, &dstHigh); - moveRR(c, 4, src, 4, dst); + moveRR(con, 4, &srcHigh, 4, &dstHigh); + moveRR(con, 4, src, 4, dst); } } else { - moveRR(c, 4, src, 4, dst); - moveRR(c, 4, &srcHigh, 4, &dstHigh); + moveRR(con, 4, src, 4, dst); + moveRR(con, 4, &srcHigh, 4, &dstHigh); } } else if (src->low != dst->low) { - emit(c, mov(dst->low, src->low)); + emit(con, mov(dst->low, src->low)); } break; - default: abort(c); + default: abort(con); } } void -moveZRR(Context* c, unsigned srcSize, Assembler::Register* src, +moveZRR(Context* con, unsigned srcSize, Assembler::Register* src, unsigned, Assembler::Register* dst) { switch (srcSize) { case 2: - emit(c, lsli(dst->low, src->low, 16)); - emit(c, lsri(dst->low, dst->low, 16)); + emit(con, lsli(dst->low, src->low, 16)); + emit(con, lsri(dst->low, dst->low, 16)); break; - default: abort(c); + default: abort(con); } } +void moveCR(Context* con, unsigned size, Assembler::Constant* src, + unsigned, Assembler::Register* dst); + void -moveCR2(Context* c, unsigned, Assembler::Constant* src, - unsigned dstSize, Assembler::Register* dst, Promise* callOffset) +moveCR2(Context* con, unsigned size, Assembler::Constant* src, + Assembler::Register* dst, Promise* callOffset) { - if (dstSize <= 4) { - if (src->value->resolved() and isOfWidth(getValue(src), 8)) { - emit(c, movi(dst->low, lo8(getValue(src)))); - } else { - appendConstantPoolEntry(c, src->value, callOffset); - emit(c, ldri(dst->low, ProgramCounter, 0)); - } + if (isFpr(dst)) { // floating-point + Assembler::Register tmp = size > 4 ? makeTemp64(con) : + makeTemp(con); + moveCR(con, size, src, size, &tmp); + moveRR(con, size, &tmp, size, dst); + freeTemp(con, tmp); + } else if (size > 4) { + uint64_t value = (uint64_t)src->value->value(); + ResolvedPromise loBits(value & MASK_LO32); + Assembler::Constant srcLo(&loBits); + ResolvedPromise hiBits(value >> 32); + Assembler::Constant srcHi(&hiBits); + Assembler::Register dstHi(dst->high); + moveCR(con, 4, &srcLo, 4, dst); + moveCR(con, 4, &srcHi, 4, &dstHi); + } else if (src->value->resolved() and isOfWidth(getValue(src), 8)) { + emit(con, movi(dst->low, lo8(getValue(src)))); // fits in immediate } else { - abort(c); // todo + appendConstantPoolEntry(con, src->value, callOffset); + emit(con, ldri(dst->low, ProgramCounter, 0)); // load 32 bits } } void -moveCR(Context* c, unsigned srcSize, Assembler::Constant* src, - unsigned dstSize, Assembler::Register* dst) +moveCR(Context* con, unsigned size, Assembler::Constant* src, + unsigned, Assembler::Register* dst) { - moveCR2(c, srcSize, src, dstSize, dst, 0); + moveCR2(con, size, src, dst, 0); } void addR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { @@ -876,52 +1059,52 @@ void subR(Context* con, unsigned size, Assembler::Register* a, Assembler::Regist } void -addC(Context* c, unsigned size, Assembler::Constant* a, +addC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* dst) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); int32_t v = a->value->value(); if (v) { if (v > 0 and v < 256) { - emit(c, addi(dst->low, b->low, v)); + emit(con, addi(dst->low, b->low, v)); } else if (v > 0 and v < 1024 and v % 4 == 0) { - emit(c, addi(dst->low, b->low, v >> 2, 15)); + emit(con, addi(dst->low, b->low, v >> 2, 15)); } else { // todo - abort(c); + abort(con); } } else { - moveRR(c, size, b, size, dst); + moveRR(con, size, b, size, dst); } } void -subC(Context* c, unsigned size, Assembler::Constant* a, +subC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* dst) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); int32_t v = a->value->value(); if (v) { if (v > 0 and v < 256) { - emit(c, subi(dst->low, b->low, v)); + emit(con, subi(dst->low, b->low, v)); } else if (v > 0 and v < 1024 and v % 4 == 0) { - emit(c, subi(dst->low, b->low, v >> 2, 15)); + emit(con, subi(dst->low, b->low, v >> 2, 15)); } else { // todo - abort(c); + abort(con); } } else { - moveRR(c, size, b, size, dst); + moveRR(con, size, b, size, dst); } } void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { bool useTemporaries = b->low == t->low; - int tmpLow = useTemporaries ? con->client->acquireTemporary() : t->low; - int tmpHigh = useTemporaries ? con->client->acquireTemporary() : t->high; + int tmpLow = useTemporaries ? con->client->acquireTemporary(GPR_MASK) : t->low; + int tmpHigh = useTemporaries ? con->client->acquireTemporary(GPR_MASK) : t->high; emit(con, umull(tmpLow, tmpHigh, a->low, b->low)); emit(con, mla(tmpHigh, a->low, b->high, tmpHigh)); @@ -938,13 +1121,98 @@ void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::R } } +void floatAbsoluteRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { + if (size == 8) { + emit(con, fabsd(fpr64(b), fpr64(a))); + } else { + emit(con, fabss(fpr32(b), fpr32(a))); + } +} + +void floatNegateRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { + if (size == 8) { + emit(con, fnegd(fpr64(b), fpr64(a))); + } else { + emit(con, fnegs(fpr32(b), fpr32(a))); + } +} + +void float2FloatRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { + if (size == 8) { + emit(con, fcvtsd(fpr32(b), fpr64(a))); + } else { + emit(con, fcvtds(fpr64(b), fpr32(a))); + } +} + +void float2IntRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { + int tmp = newTemp(con, FPR_MASK); + int ftmp = fpr32(tmp); + if (size == 8) { // double to int + emit(con, ftosizd(ftmp, fpr64(a))); + } else { // float to int + emit(con, ftosizs(ftmp, fpr32(a))); + } // else thunked + emit(con, fmrs(b->low, ftmp)); + freeTemp(con, tmp); +} + +void int2FloatRR(Context* con, unsigned, Assembler::Register* a, unsigned size, Assembler::Register* b) { + emit(con, fmsr(fpr32(b), a->low)); + if (size == 8) { // int to double + emit(con, fsitod(fpr64(b), fpr32(b))); + } else { // int to float + emit(con, fsitos(fpr32(b), fpr32(b))); + } // else thunked +} + +void floatSqrtRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { + if (size == 8) { + emit(con, fsqrtd(fpr64(b), fpr64(a))); + } else { + emit(con, fsqrts(fpr32(b), fpr32(a))); + } +} + +void floatAddR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { + if (size == 8) { + emit(con, faddd(fpr64(t), fpr64(a), fpr64(b))); + } else { + emit(con, fadds(fpr32(t), fpr32(a), fpr32(b))); + } +} + +void floatSubtractR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { + if (size == 8) { + emit(con, fsubd(fpr64(t), fpr64(b), fpr64(a))); + } else { + emit(con, fsubs(fpr32(t), fpr32(b), fpr32(a))); + } +} + +void floatMultiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { + if (size == 8) { + emit(con, fmuld(fpr64(t), fpr64(a), fpr64(b))); + } else { + emit(con, fmuls(fpr32(t), fpr32(a), fpr32(b))); + } +} + +void floatDivideR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { + if (size == 8) { + emit(con, fdivd(fpr64(t), fpr64(b), fpr64(a))); + } else { + emit(con, fdivs(fpr32(t), fpr32(b), fpr32(a))); + } +} + int -normalize(Context* c, int offset, int index, unsigned scale, +normalize(Context* con, int offset, int index, unsigned scale, bool* preserveIndex, bool* release) { if (offset != 0 or scale != 1) { Assembler::Register normalizedIndex - (*preserveIndex ? c->client->acquireTemporary() : index); + (*preserveIndex ? con->client->acquireTemporary(GPR_MASK) : index); if (*preserveIndex) { *release = true; @@ -961,7 +1229,7 @@ normalize(Context* c, int offset, int index, unsigned scale, ResolvedPromise scalePromise(log(scale)); Assembler::Constant scaleConstant(&scalePromise); - shiftLeftC(c, TargetBytesPerWord, &scaleConstant, + shiftLeftC(con, TargetBytesPerWord, &scaleConstant, &unscaledIndex, &normalizedIndex); scaled = normalizedIndex.low; @@ -975,10 +1243,10 @@ normalize(Context* c, int offset, int index, unsigned scale, ResolvedPromise offsetPromise(offset); Assembler::Constant offsetConstant(&offsetPromise); - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); - addR(c, TargetBytesPerWord, &tmp, &untranslatedIndex, &normalizedIndex); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); + addR(con, TargetBytesPerWord, &tmp, &untranslatedIndex, &normalizedIndex); + con->client->releaseTemporary(tmp.low); } return normalizedIndex.low; @@ -989,222 +1257,270 @@ normalize(Context* c, int offset, int index, unsigned scale, } void -store(Context* c, unsigned size, Assembler::Register* src, +store(Context* con, unsigned size, Assembler::Register* src, int base, int offset, int index, unsigned scale, bool preserveIndex) { if (index != NoRegister) { bool release; int normalized = normalize - (c, offset, index, scale, &preserveIndex, &release); + (con, offset, index, scale, &preserveIndex, &release); - switch (size) { - case 1: - emit(c, strb(src->low, base, normalized)); - break; + if (!isFpr(src)) { // GPR store + switch (size) { + case 1: + emit(con, strb(src->low, base, normalized)); + break; - case 2: - emit(c, strh(src->low, base, normalized)); - break; + case 2: + emit(con, strh(src->low, base, normalized)); + break; - case 4: - emit(c, str(src->low, base, normalized)); - break; + case 4: + emit(con, str(src->low, base, normalized)); + break; - case 8: { - Assembler::Register srcHigh(src->high); - store(c, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); - store(c, 4, src, base, 4, normalized, 1, preserveIndex); - } break; + case 8: { // split into 2 32-bit stores + Assembler::Register srcHigh(src->high); + store(con, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); + store(con, 4, src, base, 4, normalized, 1, preserveIndex); + } break; - default: abort(c); + default: abort(con); + } + } else { // FPR store + Assembler::Register base_(base), + normalized_(normalized), + absAddr = makeTemp(con); + // FPR stores have only bases, so we must add the index + addR(con, TargetBytesPerWord, &base_, &normalized_, &absAddr); + // double-precision + if (size == 8) emit(con, fstd(fpr64(src), absAddr.low)); + // single-precision + else emit(con, fsts(fpr32(src), absAddr.low)); + freeTemp(con, absAddr); } - if (release) c->client->releaseTemporary(normalized); + if (release) con->client->releaseTemporary(normalized); } else if (size == 8 or abs(offset) == (abs(offset) & 0xFF) or (size != 2 and abs(offset) == (abs(offset) & 0xFFF))) { - switch (size) { - case 1: - emit(c, strbi(src->low, base, offset)); - break; + if (!isFpr(src)) { // GPR store + switch (size) { + case 1: + emit(con, strbi(src->low, base, offset)); + break; - case 2: - emit(c, strhi(src->low, base, offset)); - break; + case 2: + emit(con, strhi(src->low, base, offset)); + break; - case 4: - emit(c, stri(src->low, base, offset)); - break; + case 4: + emit(con, stri(src->low, base, offset)); + break; - case 8: { - Assembler::Register srcHigh(src->high); - store(c, 4, &srcHigh, base, offset, NoRegister, 1, false); - store(c, 4, src, base, offset + 4, NoRegister, 1, false); - } break; + case 8: { // split into 2 32-bit stores + Assembler::Register srcHigh(src->high); + store(con, 4, &srcHigh, base, offset, NoRegister, 1, false); + store(con, 4, src, base, offset + 4, NoRegister, 1, false); + } break; - default: abort(c); + default: abort(con); + } + } else { // FPR store + // double-precision + if (size == 8) emit(con, fstd(fpr64(src), base, offset)); + // single-precision + else emit(con, fsts(fpr32(src), base, offset)); } } else { - Assembler::Register tmp(c->client->acquireTemporary()); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); ResolvedPromise offsetPromise(offset); Assembler::Constant offsetConstant(&offsetPromise); - moveCR(c, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); + moveCR(con, TargetBytesPerWord, &offsetConstant, + TargetBytesPerWord, &tmp); - store(c, size, src, base, 0, tmp.low, 1, false); + store(con, size, src, base, 0, tmp.low, 1, false); - c->client->releaseTemporary(tmp.low); + con->client->releaseTemporary(tmp.low); } } void -moveRM(Context* c, unsigned srcSize, Assembler::Register* src, +moveRM(Context* con, unsigned srcSize, Assembler::Register* src, unsigned dstSize UNUSED, Assembler::Memory* dst) { - assert(c, srcSize == dstSize); + assert(con, srcSize == dstSize); - store(c, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); + store(con, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); } void -moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, Assembler::Register* src, +moveAndUpdateRM(Context* con, unsigned srcSize UNUSED, Assembler::Register* src, unsigned dstSize UNUSED, Assembler::Memory* dst) { - assert(c, srcSize == TargetBytesPerWord); - assert(c, dstSize == TargetBytesPerWord); + assert(con, srcSize == TargetBytesPerWord); + assert(con, dstSize == TargetBytesPerWord); if (dst->index == NoRegister) { - emit(c, stri(src->low, dst->base, dst->offset, dst->offset ? 1 : 0)); + emit(con, stri(src->low, dst->base, dst->offset, dst->offset ? 1 : 0)); } else { - assert(c, dst->offset == 0); - assert(c, dst->scale == 1); + assert(con, dst->offset == 0); + assert(con, dst->scale == 1); - emit(c, str(src->low, dst->base, dst->index, 1)); + emit(con, str(src->low, dst->base, dst->index, 1)); } } void -load(Context* c, unsigned srcSize, int base, int offset, int index, +load(Context* con, unsigned srcSize, int base, int offset, int index, unsigned scale, unsigned dstSize, Assembler::Register* dst, bool preserveIndex, bool signExtend) { if (index != NoRegister) { bool release; int normalized = normalize - (c, offset, index, scale, &preserveIndex, &release); + (con, offset, index, scale, &preserveIndex, &release); - switch (srcSize) { - case 1: - if (signExtend) { - emit(c, ldrsb(dst->low, base, normalized)); - } else { - emit(c, ldrb(dst->low, base, normalized)); + if (!isFpr(dst)) { // GPR load + switch (srcSize) { + case 1: + if (signExtend) { + emit(con, ldrsb(dst->low, base, normalized)); + } else { + emit(con, ldrb(dst->low, base, normalized)); + } + break; + + case 2: + if (signExtend) { + emit(con, ldrsh(dst->low, base, normalized)); + } else { + emit(con, ldrh(dst->low, base, normalized)); + } + break; + + case 4: + case 8: { + if (srcSize == 4 and dstSize == 8) { + load(con, 4, base, 0, normalized, 1, 4, dst, preserveIndex, + false); + moveRR(con, 4, dst, 8, dst); + } else if (srcSize == 8 and dstSize == 8) { + Assembler::Register dstHigh(dst->high); + load(con, 4, base, 0, normalized, 1, 4, &dstHigh, + preserveIndex, false); + load(con, 4, base, 4, normalized, 1, 4, dst, preserveIndex, + false); + } else { + emit(con, ldr(dst->low, base, normalized)); + } + } break; + + default: abort(con); } - break; - - case 2: - if (signExtend) { - emit(c, ldrsh(dst->low, base, normalized)); - } else { - emit(c, ldrh(dst->low, base, normalized)); - } - break; - - case 4: - case 8: { - if (srcSize == 4 and dstSize == 8) { - load(c, 4, base, 0, normalized, 1, 4, dst, preserveIndex, false); - moveRR(c, 4, dst, 8, dst); - } else if (srcSize == 8 and dstSize == 8) { - Assembler::Register dstHigh(dst->high); - load(c, 4, base, 0, normalized, 1, 4, &dstHigh, preserveIndex, false); - load(c, 4, base, 4, normalized, 1, 4, dst, preserveIndex, false); - } else { - emit(c, ldr(dst->low, base, normalized)); - } - } break; - - default: abort(c); + } else { // FPR load + Assembler::Register base_(base), + normalized_(normalized), + absAddr = makeTemp(con); + // VFP loads only have bases, so we must add the index + addR(con, TargetBytesPerWord, &base_, &normalized_, &absAddr); + // double-precision + if (srcSize == 8) emit(con, fldd(fpr64(dst), absAddr.low)); + // single-precision + else emit(con, flds(fpr32(dst), absAddr.low)); + freeTemp(con, absAddr); } - if (release) c->client->releaseTemporary(normalized); + if (release) con->client->releaseTemporary(normalized); } else if ((srcSize == 8 and dstSize == 8) or abs(offset) == (abs(offset) & 0xFF) or (srcSize != 2 and (srcSize != 1 or not signExtend) and abs(offset) == (abs(offset) & 0xFFF))) { - switch (srcSize) { - case 1: - if (signExtend) { - emit(c, ldrsbi(dst->low, base, offset)); - } else { - emit(c, ldrbi(dst->low, base, offset)); + if (!isFpr(dst)) { // GPR load + switch (srcSize) { + case 1: + if (signExtend) { + emit(con, ldrsbi(dst->low, base, offset)); + } else { + emit(con, ldrbi(dst->low, base, offset)); + } + break; + + case 2: + if (signExtend) { + emit(con, ldrshi(dst->low, base, offset)); + } else { + emit(con, ldrhi(dst->low, base, offset)); + } + break; + + case 4: + emit(con, ldri(dst->low, base, offset)); + break; + + case 8: { + if (dstSize == 8) { + Assembler::Register dstHigh(dst->high); + load(con, 4, base, offset, NoRegister, 1, 4, &dstHigh, false, + false); + load(con, 4, base, offset + 4, NoRegister, 1, 4, dst, false, + false); + } else { + emit(con, ldri(dst->low, base, offset)); + } + } break; + + default: abort(con); } - break; - - case 2: - if (signExtend) { - emit(c, ldrshi(dst->low, base, offset)); - } else { - emit(c, ldrhi(dst->low, base, offset)); - } - break; - - case 4: - emit(c, ldri(dst->low, base, offset)); - break; - - case 8: { - if (dstSize == 8) { - Assembler::Register dstHigh(dst->high); - load(c, 4, base, offset, NoRegister, 1, 4, &dstHigh, false, false); - load(c, 4, base, offset + 4, NoRegister, 1, 4, dst, false, false); - } else { - emit(c, ldri(dst->low, base, offset)); - } - } break; - - default: abort(c); + } else { // FPR load + // double-precision + if (srcSize == 8) emit(con, fldd(fpr64(dst), base, offset)); + // single-precision + else emit(con, flds(fpr32(dst), base, offset)); } } else { - Assembler::Register tmp(c->client->acquireTemporary()); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); ResolvedPromise offsetPromise(offset); Assembler::Constant offsetConstant(&offsetPromise); - moveCR(c, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); + moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, + &tmp); - load(c, srcSize, base, 0, tmp.low, 1, dstSize, dst, false, signExtend); + load(con, srcSize, base, 0, tmp.low, 1, dstSize, dst, false, + signExtend); - c->client->releaseTemporary(tmp.low); + con->client->releaseTemporary(tmp.low); } } void -moveMR(Context* c, unsigned srcSize, Assembler::Memory* src, +moveMR(Context* con, unsigned srcSize, Assembler::Memory* src, unsigned dstSize, Assembler::Register* dst) { - load(c, srcSize, src->base, src->offset, src->index, src->scale, + load(con, srcSize, src->base, src->offset, src->index, src->scale, dstSize, dst, true, true); } void -moveZMR(Context* c, unsigned srcSize, Assembler::Memory* src, +moveZMR(Context* con, unsigned srcSize, Assembler::Memory* src, unsigned dstSize, Assembler::Register* dst) { - load(c, srcSize, src->base, src->offset, src->index, src->scale, + load(con, srcSize, src->base, src->offset, src->index, src->scale, dstSize, dst, true, false); } void -andR(Context* c, unsigned size, Assembler::Register* a, +andR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* dst) { - if (size == 8) emit(c, and_(dst->high, a->high, b->high)); - emit(c, and_(dst->low, a->low, b->low)); + if (size == 8) emit(con, and_(dst->high, a->high, b->high)); + emit(con, and_(dst->low, a->low, b->low)); } void -andC(Context* c, unsigned size, Assembler::Constant* a, +andC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* dst) { int64_t v = a->value->value(); @@ -1219,15 +1535,15 @@ andC(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register bh(b->high); Assembler::Register dh(dst->high); - andC(c, 4, &al, b, dst); - andC(c, 4, &ah, &bh, &dh); + andC(con, 4, &al, b, dst); + andC(con, 4, &ah, &bh, &dh); } else { uint32_t v32 = static_cast(v); if (v32 != 0xFFFFFFFF) { if ((v32 & 0xFFFFFF00) == 0xFFFFFF00) { - emit(c, bici(dst->low, b->low, (~(v32 & 0xFF)) & 0xFF)); + emit(con, bici(dst->low, b->low, (~(v32 & 0xFF)) & 0xFF)); } else if ((v32 & 0xFFFFFF00) == 0) { - emit(c, andi(dst->low, b->low, v32 & 0xFF)); + emit(con, andi(dst->low, b->low, v32 & 0xFF)); } else { // todo: there are other cases we can handle in one // instruction @@ -1235,28 +1551,28 @@ andC(Context* c, unsigned size, Assembler::Constant* a, bool useTemporary = b->low == dst->low; Assembler::Register tmp(dst->low); if (useTemporary) { - tmp.low = c->client->acquireTemporary(); + tmp.low = con->client->acquireTemporary(GPR_MASK); } - moveCR(c, 4, a, 4, &tmp); - andR(c, 4, b, &tmp, dst); + moveCR(con, 4, a, 4, &tmp); + andR(con, 4, b, &tmp, dst); if (useTemporary) { - c->client->releaseTemporary(tmp.low); + con->client->releaseTemporary(tmp.low); } } } else { - moveRR(c, size, b, size, dst); + moveRR(con, size, b, size, dst); } } } void -orR(Context* c, unsigned size, Assembler::Register* a, +orR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* dst) { - if (size == 8) emit(c, orr(dst->high, a->high, b->high)); - emit(c, orr(dst->low, a->low, b->low)); + if (size == 8) emit(con, orr(dst->high, a->high, b->high)); + emit(con, orr(dst->low, a->low, b->low)); } void @@ -1268,215 +1584,246 @@ xorR(Context* con, unsigned size, Assembler::Register* a, } void -moveAR2(Context* c, unsigned srcSize, Assembler::Address* src, +moveAR2(Context* con, unsigned srcSize, Assembler::Address* src, unsigned dstSize, Assembler::Register* dst) { - assert(c, srcSize == 4 and dstSize == 4); + assert(con, srcSize == 4 and dstSize == 4); Assembler::Constant constant(src->address); - moveCR(c, srcSize, &constant, dstSize, dst); + moveCR(con, srcSize, &constant, dstSize, dst); Assembler::Memory memory(dst->low, 0, -1, 0); - moveMR(c, dstSize, &memory, dstSize, dst); + moveMR(con, dstSize, &memory, dstSize, dst); } void -moveAR(Context* c, unsigned srcSize, Assembler::Address* src, +moveAR(Context* con, unsigned srcSize, Assembler::Address* src, unsigned dstSize, Assembler::Register* dst) { - moveAR2(c, srcSize, src, dstSize, dst); + moveAR2(con, srcSize, src, dstSize, dst); } void -compareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, +compareRR(Context* con, unsigned aSize, Assembler::Register* a, unsigned bSize UNUSED, Assembler::Register* b) { - assert(c, aSize == 4 and bSize == 4); - assert(c, b->low != a->low); + assert(con, !(isFpr(a) ^ isFpr(b))); // regs must be of the same type - emit(c, cmp(b->low, a->low)); -} - -void -compareCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) -{ - assert(c, aSize == 4 and bSize == 4); - - if (a->value->resolved() and isOfWidth(a->value->value(), 8)) { - emit(c, cmpi(b->low, a->value->value())); - } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, aSize, a, bSize, &tmp); - compareRR(c, bSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); + if (!isFpr(a)) { // GPR compare + assert(con, aSize == 4 && bSize == 4); + /**///assert(con, b->low != a->low); + emit(con, cmp(b->low, a->low)); + } else { // FPR compare + assert(con, aSize == bSize); + if (aSize == 8) emit(con, fcmpd(fpr64(b), fpr64(a))); // double + else emit(con, fcmps(fpr32(b), fpr32(a))); // single + emit(con, fmstat()); } } void -compareCM(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Memory* b) +compareCR(Context* con, unsigned aSize, Assembler::Constant* a, + unsigned bSize, Assembler::Register* b) { - assert(c, aSize == 4 and bSize == 4); + assert(con, aSize == 4 and bSize == 4); - Assembler::Register tmp(c->client->acquireTemporary()); - moveMR(c, bSize, b, bSize, &tmp); - compareCR(c, aSize, a, bSize, &tmp); - c->client->releaseTemporary(tmp.low); + if (!isFpr(b) && a->value->resolved() && + isOfWidth(a->value->value(), 8)) { + emit(con, cmpi(b->low, a->value->value())); + } else { + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, aSize, a, bSize, &tmp); + compareRR(con, bSize, &tmp, bSize, b); + con->client->releaseTemporary(tmp.low); + } } void -compareRM(Context* c, unsigned aSize, Assembler::Register* a, +compareCM(Context* con, unsigned aSize, Assembler::Constant* a, unsigned bSize, Assembler::Memory* b) { - assert(c, aSize == 4 and bSize == 4); + assert(con, aSize == 4 and bSize == 4); - Assembler::Register tmp(c->client->acquireTemporary()); - moveMR(c, bSize, b, bSize, &tmp); - compareRR(c, aSize, a, bSize, &tmp); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveMR(con, bSize, b, bSize, &tmp); + compareCR(con, aSize, a, bSize, &tmp); + con->client->releaseTemporary(tmp.low); +} + +void +compareRM(Context* con, unsigned aSize, Assembler::Register* a, + unsigned bSize, Assembler::Memory* b) +{ + assert(con, aSize == 4 and bSize == 4); + + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveMR(con, bSize, b, bSize, &tmp); + compareRR(con, aSize, a, bSize, &tmp); + con->client->releaseTemporary(tmp.low); } int32_t -branch(Context* c, TernaryOperation op) +branch(Context* con, TernaryOperation op) { switch (op) { case JumpIfEqual: + case JumpIfFloatEqual: return beq(0); - + case JumpIfNotEqual: + case JumpIfFloatNotEqual: return bne(0); - + case JumpIfLess: + case JumpIfFloatLess: + case JumpIfFloatLessOrUnordered: return blt(0); - + case JumpIfGreater: + case JumpIfFloatGreater: return bgt(0); - + case JumpIfLessOrEqual: + case JumpIfFloatLessOrEqual: + case JumpIfFloatLessOrEqualOrUnordered: return ble(0); - + case JumpIfGreaterOrEqual: + case JumpIfFloatGreaterOrEqual: return bge(0); - + + case JumpIfFloatGreaterOrUnordered: + return bhi(0); + + case JumpIfFloatGreaterOrEqualOrUnordered: + return bpl(0); + default: - abort(c); + abort(con); } } void -conditional(Context* c, int32_t branch, Assembler::Constant* target) +conditional(Context* con, int32_t branch, Assembler::Constant* target) { - appendOffsetTask(c, target->value, offset(c)); - emit(c, branch); + appendOffsetTask(con, target->value, offset(con)); + emit(con, branch); } void -branch(Context* c, TernaryOperation op, Assembler::Constant* target) +branch(Context* con, TernaryOperation op, Assembler::Constant* target) { - conditional(c, branch(c, op), target); + conditional(con, branch(con, op), target); } void -branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, +branchLong(Context* con, TernaryOperation op, Assembler::Operand* al, Assembler::Operand* ah, Assembler::Operand* bl, Assembler::Operand* bh, Assembler::Constant* target, BinaryOperationType compareSigned, BinaryOperationType compareUnsigned) { - compareSigned(c, 4, ah, 4, bh); + compareSigned(con, 4, ah, 4, bh); unsigned next = 0; switch (op) { case JumpIfEqual: - next = c->code.length(); - emit(c, bne(0)); + case JumpIfFloatEqual: + next = con->code.length(); + emit(con, bne(0)); - compareSigned(c, 4, al, 4, bl); - conditional(c, beq(0), target); + compareSigned(con, 4, al, 4, bl); + conditional(con, beq(0), target); break; case JumpIfNotEqual: - conditional(c, bne(0), target); + case JumpIfFloatNotEqual: + conditional(con, bne(0), target); - compareSigned(c, 4, al, 4, bl); - conditional(c, bne(0), target); + compareSigned(con, 4, al, 4, bl); + conditional(con, bne(0), target); break; case JumpIfLess: - conditional(c, blt(0), target); + case JumpIfFloatLess: + conditional(con, blt(0), target); - next = c->code.length(); - emit(c, bgt(0)); + next = con->code.length(); + emit(con, bgt(0)); - compareUnsigned(c, 4, al, 4, bl); - conditional(c, blo(0), target); + compareUnsigned(con, 4, al, 4, bl); + conditional(con, blo(0), target); break; case JumpIfGreater: - conditional(c, bgt(0), target); + case JumpIfFloatGreater: + conditional(con, bgt(0), target); - next = c->code.length(); - emit(c, blt(0)); + next = con->code.length(); + emit(con, blt(0)); - compareUnsigned(c, 4, al, 4, bl); - conditional(c, bhi(0), target); + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bhi(0), target); break; case JumpIfLessOrEqual: - conditional(c, blt(0), target); + case JumpIfFloatLessOrEqual: + conditional(con, blt(0), target); - next = c->code.length(); - emit(c, bgt(0)); + next = con->code.length(); + emit(con, bgt(0)); - compareUnsigned(c, 4, al, 4, bl); - conditional(c, bls(0), target); + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bls(0), target); break; case JumpIfGreaterOrEqual: - conditional(c, bgt(0), target); + case JumpIfFloatGreaterOrEqual: + conditional(con, bgt(0), target); - next = c->code.length(); - emit(c, blt(0)); + next = con->code.length(); + emit(con, blt(0)); - compareUnsigned(c, 4, al, 4, bl); - conditional(c, bhs(0), target); + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bhs(0), target); break; default: - abort(c); + abort(con); } if (next) { updateOffset - (c->s, c->code.data + next, reinterpret_cast - (c->code.data + c->code.length())); + (con->s, con->code.data + next, reinterpret_cast + (con->code.data + con->code.length())); } } void -branchRR(Context* c, TernaryOperation op, unsigned size, +branchRR(Context* con, TernaryOperation op, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Constant* target) { - if (size > TargetBytesPerWord) { + if (!isFpr(a) && size > TargetBytesPerWord) { Assembler::Register ah(a->high); Assembler::Register bh(b->high); - branchLong(c, op, a, &ah, b, &bh, target, CAST2(compareRR), + branchLong(con, op, a, &ah, b, &bh, target, CAST2(compareRR), CAST2(compareRR)); } else { - compareRR(c, size, a, size, b); - branch(c, op, target); + compareRR(con, size, a, size, b); + branch(con, op, target); } } void -branchCR(Context* c, TernaryOperation op, unsigned size, +branchCR(Context* con, TernaryOperation op, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Constant* target) { + assert(con, !isFloatBranch(op)); + if (size > TargetBytesPerWord) { int64_t v = a->value->value(); @@ -1488,132 +1835,139 @@ branchCR(Context* c, TernaryOperation op, unsigned size, Assembler::Register bh(b->high); - branchLong(c, op, &al, &ah, b, &bh, target, CAST2(compareCR), + branchLong(con, op, &al, &ah, b, &bh, target, CAST2(compareCR), CAST2(compareCR)); } else { - compareCR(c, size, a, size, b); - branch(c, op, target); + compareCR(con, size, a, size, b); + branch(con, op, target); } } void -branchRM(Context* c, TernaryOperation op, unsigned size, +branchRM(Context* con, TernaryOperation op, unsigned size, Assembler::Register* a, Assembler::Memory* b, Assembler::Constant* target) { - assert(c, size <= TargetBytesPerWord); + assert(con, !isFloatBranch(op)); + assert(con, size <= TargetBytesPerWord); - compareRM(c, size, a, size, b); - branch(c, op, target); + compareRM(con, size, a, size, b); + branch(con, op, target); } void -branchCM(Context* c, TernaryOperation op, unsigned size, +branchCM(Context* con, TernaryOperation op, unsigned size, Assembler::Constant* a, Assembler::Memory* b, Assembler::Constant* target) { - assert(c, size <= TargetBytesPerWord); + assert(con, !isFloatBranch(op)); + assert(con, size <= TargetBytesPerWord); - compareCM(c, size, a, size, b); - branch(c, op, target); + compareCM(con, size, a, size, b); + branch(con, op, target); } ShiftMaskPromise* -shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) +shiftMaskPromise(Context* con, Promise* base, unsigned shift, int64_t mask) { - return new (c->zone->allocate(sizeof(ShiftMaskPromise))) - ShiftMaskPromise(base, shift, mask); + return new(con->zone) ShiftMaskPromise(base, shift, mask); } void -moveCM(Context* c, unsigned srcSize, Assembler::Constant* src, +moveCM(Context* con, unsigned srcSize, Assembler::Constant* src, unsigned dstSize, Assembler::Memory* dst) { switch (dstSize) { case 8: { Assembler::Constant srcHigh - (shiftMaskPromise(c, src->value, 32, 0xFFFFFFFF)); + (shiftMaskPromise(con, src->value, 32, 0xFFFFFFFF)); Assembler::Constant srcLow - (shiftMaskPromise(c, src->value, 0, 0xFFFFFFFF)); + (shiftMaskPromise(con, src->value, 0, 0xFFFFFFFF)); Assembler::Memory dstLow (dst->base, dst->offset + 4, dst->index, dst->scale); - moveCM(c, 4, &srcLow, 4, &dstLow); - moveCM(c, 4, &srcHigh, 4, dst); + moveCM(con, 4, &srcLow, 4, &dstLow); + moveCM(con, 4, &srcHigh, 4, dst); } break; default: - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, srcSize, src, dstSize, &tmp); - moveRM(c, dstSize, &tmp, dstSize, dst); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, srcSize, src, dstSize, &tmp); + moveRM(con, dstSize, &tmp, dstSize, dst); + con->client->releaseTemporary(tmp.low); } } void -negateRR(Context* c, unsigned srcSize, Assembler::Register* src, +negateRR(Context* con, unsigned srcSize, Assembler::Register* src, unsigned dstSize UNUSED, Assembler::Register* dst) { - assert(c, srcSize == dstSize); + assert(con, srcSize == dstSize); - emit(c, mvn(dst->low, src->low)); - emit(c, SETS(addi(dst->low, dst->low, 1))); + emit(con, mvn(dst->low, src->low)); + emit(con, SETS(addi(dst->low, dst->low, 1))); if (srcSize == 8) { - emit(c, mvn(dst->high, src->high)); - emit(c, adci(dst->high, dst->high, 0)); + emit(con, mvn(dst->high, src->high)); + emit(con, adci(dst->high, dst->high, 0)); } } void -callR(Context* c, unsigned size UNUSED, Assembler::Register* target) +callR(Context* con, unsigned size UNUSED, Assembler::Register* target) { - assert(c, size == TargetBytesPerWord); - emit(c, blx(target->low)); + assert(con, size == TargetBytesPerWord); + emit(con, blx(target->low)); } void -callC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +callC(Context* con, unsigned size UNUSED, Assembler::Constant* target) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); - appendOffsetTask(c, target->value, offset(c)); - emit(c, bl(0)); + appendOffsetTask(con, target->value, offset(con)); + emit(con, bl(0)); } void -longCallC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +longCallC(Context* con, unsigned size UNUSED, Assembler::Constant* target) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); Assembler::Register tmp(4); - moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, offset(c)); - callR(c, TargetBytesPerWord, &tmp); + moveCR2(con, TargetBytesPerWord, target, &tmp, offset(con)); + callR(con, TargetBytesPerWord, &tmp); } void -longJumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +longJumpC(Context* con, unsigned size UNUSED, Assembler::Constant* target) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); Assembler::Register tmp(4); // a non-arg reg that we don't mind clobbering - moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, offset(c)); - jumpR(c, TargetBytesPerWord, &tmp); + moveCR2(con, TargetBytesPerWord, target, &tmp, offset(con)); + jumpR(con, TargetBytesPerWord, &tmp); } void -jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +jumpC(Context* con, unsigned size UNUSED, Assembler::Constant* target) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); - appendOffsetTask(c, target->value, offset(c)); - emit(c, b(0)); + appendOffsetTask(con, target->value, offset(con)); + emit(con, b(0)); } void -return_(Context* c) +return_(Context* con) { - emit(c, bx(LinkRegister)); + emit(con, bx(LinkRegister)); +} + +void +trap(Context* con) +{ + emit(con, bkpt(0)); } void @@ -1628,12 +1982,12 @@ argumentFootprint(unsigned footprint) } void -nextFrame(ArchitectureContext* c, uint32_t* start, unsigned size UNUSED, - unsigned footprint, void* link, void*, +nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED, + unsigned footprint, void* link, bool, unsigned targetParameterFootprint UNUSED, void** ip, void** stack) { - assert(c, *ip >= start); - assert(c, *ip <= start + (size / TargetBytesPerWord)); + assert(con, *ip >= start); + assert(con, *ip <= start + (size / TargetBytesPerWord)); uint32_t* instruction = static_cast(*ip); @@ -1674,7 +2028,7 @@ nextFrame(ArchitectureContext* c, uint32_t* start, unsigned size UNUSED, switch (rotation) { case 0: offset -= value / TargetBytesPerWord; break; case 15: offset -= value; break; - default: abort(c); + default: abort(con); } } @@ -1686,101 +2040,114 @@ nextFrame(ArchitectureContext* c, uint32_t* start, unsigned size UNUSED, } void -populateTables(ArchitectureContext* c) +populateTables(ArchitectureContext* con) { const OperandType C = ConstantOperand; const OperandType A = AddressOperand; const OperandType R = RegisterOperand; const OperandType M = MemoryOperand; - OperationType* zo = c->operations; - UnaryOperationType* uo = c->unaryOperations; - BinaryOperationType* bo = c->binaryOperations; - TernaryOperationType* to = c->ternaryOperations; - BranchOperationType* bro = c->branchOperations; + OperationType* zo = con->operations; + UnaryOperationType* uo = con->unaryOperations; + BinaryOperationType* bo = con->binaryOperations; + TernaryOperationType* to = con->ternaryOperations; + BranchOperationType* bro = con->branchOperations; zo[Return] = return_; zo[LoadBarrier] = memoryBarrier; zo[StoreStoreBarrier] = memoryBarrier; zo[StoreLoadBarrier] = memoryBarrier; + zo[Trap] = trap; - uo[index(c, LongCall, C)] = CAST1(longCallC); + uo[index(con, LongCall, C)] = CAST1(longCallC); - uo[index(c, AlignedLongCall, C)] = CAST1(longCallC); + uo[index(con, AlignedLongCall, C)] = CAST1(longCallC); - uo[index(c, LongJump, C)] = CAST1(longJumpC); + uo[index(con, LongJump, C)] = CAST1(longJumpC); - uo[index(c, AlignedLongJump, C)] = CAST1(longJumpC); + uo[index(con, AlignedLongJump, C)] = CAST1(longJumpC); - uo[index(c, Jump, R)] = CAST1(jumpR); - uo[index(c, Jump, C)] = CAST1(jumpC); + uo[index(con, Jump, R)] = CAST1(jumpR); + uo[index(con, Jump, C)] = CAST1(jumpC); - uo[index(c, AlignedJump, R)] = CAST1(jumpR); - uo[index(c, AlignedJump, C)] = CAST1(jumpC); + uo[index(con, AlignedJump, R)] = CAST1(jumpR); + uo[index(con, AlignedJump, C)] = CAST1(jumpC); - uo[index(c, Call, C)] = CAST1(callC); - uo[index(c, Call, R)] = CAST1(callR); + uo[index(con, Call, C)] = CAST1(callC); + uo[index(con, Call, R)] = CAST1(callR); - uo[index(c, AlignedCall, C)] = CAST1(callC); - uo[index(c, AlignedCall, R)] = CAST1(callR); + uo[index(con, AlignedCall, C)] = CAST1(callC); + uo[index(con, AlignedCall, R)] = CAST1(callR); - bo[index(c, Move, R, R)] = CAST2(moveRR); - bo[index(c, Move, C, R)] = CAST2(moveCR); - bo[index(c, Move, C, M)] = CAST2(moveCM); - bo[index(c, Move, M, R)] = CAST2(moveMR); - bo[index(c, Move, R, M)] = CAST2(moveRM); - bo[index(c, Move, A, R)] = CAST2(moveAR); + bo[index(con, Move, R, R)] = CAST2(moveRR); + bo[index(con, Move, C, R)] = CAST2(moveCR); + bo[index(con, Move, C, M)] = CAST2(moveCM); + bo[index(con, Move, M, R)] = CAST2(moveMR); + bo[index(con, Move, R, M)] = CAST2(moveRM); + bo[index(con, Move, A, R)] = CAST2(moveAR); - bo[index(c, MoveZ, R, R)] = CAST2(moveZRR); - bo[index(c, MoveZ, M, R)] = CAST2(moveZMR); - bo[index(c, MoveZ, C, R)] = CAST2(moveCR); + bo[index(con, MoveZ, R, R)] = CAST2(moveZRR); + bo[index(con, MoveZ, M, R)] = CAST2(moveZMR); + bo[index(con, MoveZ, C, R)] = CAST2(moveCR); - bo[index(c, Negate, R, R)] = CAST2(negateRR); + bo[index(con, Negate, R, R)] = CAST2(negateRR); - to[index(c, Add, R)] = CAST3(addR); + bo[index(con, FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); + bo[index(con, FloatNegate, R, R)] = CAST2(floatNegateRR); + bo[index(con, Float2Float, R, R)] = CAST2(float2FloatRR); + bo[index(con, Float2Int, R, R)] = CAST2(float2IntRR); + bo[index(con, Int2Float, R, R)] = CAST2(int2FloatRR); + bo[index(con, FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); - to[index(c, Subtract, R)] = CAST3(subR); + to[index(con, Add, R)] = CAST3(addR); - to[index(c, Multiply, R)] = CAST3(multiplyR); + to[index(con, Subtract, R)] = CAST3(subR); - to[index(c, ShiftLeft, R)] = CAST3(shiftLeftR); - to[index(c, ShiftLeft, C)] = CAST3(shiftLeftC); + to[index(con, Multiply, R)] = CAST3(multiplyR); - to[index(c, ShiftRight, R)] = CAST3(shiftRightR); - to[index(c, ShiftRight, C)] = CAST3(shiftRightC); + to[index(con, FloatAdd, R)] = CAST3(floatAddR); + to[index(con, FloatSubtract, R)] = CAST3(floatSubtractR); + to[index(con, FloatMultiply, R)] = CAST3(floatMultiplyR); + to[index(con, FloatDivide, R)] = CAST3(floatDivideR); - to[index(c, UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); - to[index(c, UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); + to[index(con, ShiftLeft, R)] = CAST3(shiftLeftR); + to[index(con, ShiftLeft, C)] = CAST3(shiftLeftC); - to[index(c, And, R)] = CAST3(andR); - to[index(c, And, C)] = CAST3(andC); + to[index(con, ShiftRight, R)] = CAST3(shiftRightR); + to[index(con, ShiftRight, C)] = CAST3(shiftRightC); - to[index(c, Or, R)] = CAST3(orR); + to[index(con, UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); + to[index(con, UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); - to[index(c, Xor, R)] = CAST3(xorR); + to[index(con, And, R)] = CAST3(andR); + to[index(con, And, C)] = CAST3(andC); - bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); - bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); - bro[branchIndex(c, C, M)] = CAST_BRANCH(branchCM); - bro[branchIndex(c, R, M)] = CAST_BRANCH(branchRM); + to[index(con, Or, R)] = CAST3(orR); + + to[index(con, Xor, R)] = CAST3(xorR); + + bro[branchIndex(con, R, R)] = CAST_BRANCH(branchRR); + bro[branchIndex(con, C, R)] = CAST_BRANCH(branchCR); + bro[branchIndex(con, C, M)] = CAST_BRANCH(branchCM); + bro[branchIndex(con, R, M)] = CAST_BRANCH(branchRM); } class MyArchitecture: public Assembler::Architecture { public: - MyArchitecture(System* system): c(system), referenceCount(0) { - populateTables(&c); + MyArchitecture(System* system): con(system), referenceCount(0) { + populateTables(&con); } virtual unsigned floatRegisterSize() { - return 0; + return vfpSupported() ? 8 : 0; } virtual uint32_t generalRegisterMask() { - return 0xFFFF; + return GPR_MASK; } virtual uint32_t floatRegisterMask() { - return 0; + return vfpSupported() ? FPR_MASK : 0; } virtual int scratch() { @@ -1861,7 +2228,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual int argumentRegister(unsigned index) { - assert(&c, index < argumentRegisterCount()); + assert(&con, index < argumentRegisterCount()); return index; } @@ -1891,7 +2258,7 @@ class MyArchitecture: public Assembler::Architecture { case Jump: case AlignedCall: case AlignedJump: { - updateOffset(c.s, static_cast(returnAddress) - 4, + updateOffset(con.s, static_cast(returnAddress) - 4, reinterpret_cast(newTarget)); } break; @@ -1904,7 +2271,7 @@ class MyArchitecture: public Assembler::Architecture { = newTarget; } break; - default: abort(&c); + default: abort(&con); } } @@ -1922,12 +2289,12 @@ class MyArchitecture: public Assembler::Architecture { } virtual void nextFrame(void* start, unsigned size, unsigned footprint, - void* link, void* stackLimit, + void* link, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) { - ::nextFrame(&c, static_cast(start), size, footprint, link, - stackLimit, targetParameterFootprint, ip, stack); + ::nextFrame(&con, static_cast(start), size, footprint, link, + mostRecent, targetParameterFootprint, ip, stack); } virtual void* frameIp(void* stack) { @@ -1982,27 +2349,51 @@ class MyArchitecture: public Assembler::Architecture { virtual void planSource (BinaryOperation op, - unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, - unsigned, bool* thunk) + unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned bSize, bool* thunk) { + *thunk = false; *aTypeMask = ~0; *aRegisterMask = ~static_cast(0); - *thunk = false; - switch (op) { case Negate: *aTypeMask = (1 << RegisterOperand); + *aRegisterMask = GPR_MASK64; break; case Absolute: + *thunk = true; + break; + case FloatAbsolute: case FloatSquareRoot: case FloatNegate: case Float2Float: + if (vfpSupported()) { + *aTypeMask = (1 << RegisterOperand); + *aRegisterMask = FPR_MASK64; + } else { + *thunk = true; + } + break; + case Float2Int: + if (vfpSupported() && bSize == 4) { + *aTypeMask = (1 << RegisterOperand); + *aRegisterMask = FPR_MASK64; + } else { + *thunk = true; + } + break; + case Int2Float: - *thunk = true; + if (vfpSupported() && aSize == 4) { + *aTypeMask = (1 << RegisterOperand); + *aRegisterMask = GPR_MASK64; + } else { + *thunk = true; + } break; default: @@ -2012,8 +2403,8 @@ class MyArchitecture: public Assembler::Architecture { virtual void planDestination (BinaryOperation op, - unsigned, uint8_t, uint64_t, - unsigned, uint8_t* bTypeMask, uint64_t* bRegisterMask) + unsigned, uint8_t aTypeMask, uint64_t, + unsigned , uint8_t* bTypeMask, uint64_t* bRegisterMask) { *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); *bRegisterMask = ~static_cast(0); @@ -2021,6 +2412,27 @@ class MyArchitecture: public Assembler::Architecture { switch (op) { case Negate: *bTypeMask = (1 << RegisterOperand); + *bRegisterMask = GPR_MASK64; + break; + + case FloatAbsolute: + case FloatSquareRoot: + case FloatNegate: + case Float2Float: + case Int2Float: + *bTypeMask = (1 << RegisterOperand); + *bRegisterMask = FPR_MASK64; + break; + + case Float2Int: + *bTypeMask = (1 << RegisterOperand); + *bRegisterMask = GPR_MASK64; + break; + + case Move: + if (!(aTypeMask & 1 << RegisterOperand)) { + *bTypeMask = 1 << RegisterOperand; + } break; default: @@ -2031,7 +2443,7 @@ class MyArchitecture: public Assembler::Architecture { virtual void planMove (unsigned, uint8_t* srcTypeMask, uint64_t* srcRegisterMask, uint8_t* tmpTypeMask, uint64_t* tmpRegisterMask, - uint8_t dstTypeMask, uint64_t) + uint8_t dstTypeMask, uint64_t dstRegisterMask) { *srcTypeMask = ~0; *srcRegisterMask = ~static_cast(0); @@ -2043,6 +2455,12 @@ class MyArchitecture: public Assembler::Architecture { // can't move directly from memory or constant to memory *srcTypeMask = 1 << RegisterOperand; *tmpTypeMask = 1 << RegisterOperand; + *tmpRegisterMask = GPR_MASK64; + } else if (vfpSupported() && + dstTypeMask & 1 << RegisterOperand && + dstRegisterMask & FPR_MASK) { + *srcTypeMask = *tmpTypeMask = 1 << RegisterOperand | + 1 << MemoryOperand; *tmpRegisterMask = ~static_cast(0); } } @@ -2054,10 +2472,10 @@ class MyArchitecture: public Assembler::Architecture { unsigned, bool* thunk) { *aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); - *aRegisterMask = ~static_cast(0); + *aRegisterMask = GPR_MASK64; *bTypeMask = (1 << RegisterOperand); - *bRegisterMask = ~static_cast(0); + *bRegisterMask = GPR_MASK64; *thunk = false; @@ -2078,11 +2496,22 @@ class MyArchitecture: public Assembler::Architecture { case Divide: case Remainder: + case FloatRemainder: + *thunk = true; + break; + case FloatAdd: case FloatSubtract: case FloatMultiply: case FloatDivide: - case FloatRemainder: + if (vfpSupported()) { + *aTypeMask = *bTypeMask = (1 << RegisterOperand); + *aRegisterMask = *bRegisterMask = FPR_MASK64; + } else { + *thunk = true; + } + break; + case JumpIfFloatEqual: case JumpIfFloatNotEqual: case JumpIfFloatLess: @@ -2093,7 +2522,12 @@ class MyArchitecture: public Assembler::Architecture { case JumpIfFloatGreaterOrUnordered: case JumpIfFloatLessOrEqualOrUnordered: case JumpIfFloatGreaterOrEqualOrUnordered: - *thunk = true; + if (vfpSupported()) { + *aTypeMask = *bTypeMask = (1 << RegisterOperand); + *aRegisterMask = *bRegisterMask = FPR_MASK64; + } else { + *thunk = true; + } break; default: @@ -2122,23 +2556,23 @@ class MyArchitecture: public Assembler::Architecture { virtual void release() { if (-- referenceCount == 0) { - c.s->free(this); + con.s->free(this); } } - ArchitectureContext c; + ArchitectureContext con; unsigned referenceCount; }; class MyAssembler: public Assembler { public: MyAssembler(System* s, Allocator* a, Zone* zone, MyArchitecture* arch): - c(s, a, zone), arch_(arch) + con(s, a, zone), arch_(arch) { } virtual void setClient(Client* client) { - assert(&c, c.client == 0); - c.client = client; + assert(&con, con.client == 0); + con.client = client; } virtual Architecture* arch() { @@ -2150,21 +2584,19 @@ class MyAssembler: public Assembler { { Register stack(StackRegister); Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); - Constant handlerConstant - (new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(handler)); - branchRM(&c, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, + Constant handlerConstant(new(con.zone) ResolvedPromise(handler)); + branchRM(&con, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, &handlerConstant); } virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) { Register link(LinkRegister); Memory linkDst(ThreadRegister, ipOffset); - moveRM(&c, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst); + moveRM(&con, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst); Register stack(StackRegister); Memory stackDst(ThreadRegister, stackOffset); - moveRM(&c, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst); + moveRM(&con, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst); } virtual void pushFrame(unsigned argumentCount, ...) { @@ -2215,17 +2647,17 @@ class MyAssembler: public Assembler { // larger frames may require multiple subtract/add instructions // to allocate/deallocate, and nextFrame will need to be taught // how to handle them: - assert(&c, footprint < 256); + assert(&con, footprint < 256); Register stack(StackRegister); ResolvedPromise footprintPromise(footprint * TargetBytesPerWord); Constant footprintConstant(&footprintPromise); - subC(&c, TargetBytesPerWord, &footprintConstant, &stack, &stack); + subC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); Register returnAddress(LinkRegister); Memory returnAddressDst (StackRegister, (footprint - 1) * TargetBytesPerWord); - moveRM(&c, TargetBytesPerWord, &returnAddress, TargetBytesPerWord, + moveRM(&con, TargetBytesPerWord, &returnAddress, TargetBytesPerWord, &returnAddressDst); } @@ -2233,7 +2665,7 @@ class MyAssembler: public Assembler { Register stack(StackRegister); ResolvedPromise differencePromise(difference * TargetBytesPerWord); Constant differenceConstant(&differencePromise); - subC(&c, TargetBytesPerWord, &differenceConstant, &stack, &stack); + subC(&con, TargetBytesPerWord, &differenceConstant, &stack, &stack); } virtual void popFrame(unsigned footprint) { @@ -2242,13 +2674,13 @@ class MyAssembler: public Assembler { Register returnAddress(LinkRegister); Memory returnAddressSrc (StackRegister, (footprint - 1) * TargetBytesPerWord); - moveMR(&c, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, + moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, &returnAddress); Register stack(StackRegister); ResolvedPromise footprintPromise(footprint * TargetBytesPerWord); Constant footprintConstant(&footprintPromise); - addC(&c, TargetBytesPerWord, &footprintConstant, &stack, &stack); + addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); } virtual void popFrameForTailCall(unsigned footprint, @@ -2256,7 +2688,7 @@ class MyAssembler: public Assembler { int returnAddressSurrogate, int framePointerSurrogate UNUSED) { - assert(&c, framePointerSurrogate == NoRegister); + assert(&con, framePointerSurrogate == NoRegister); if (TailCalls) { if (offset) { @@ -2265,27 +2697,27 @@ class MyAssembler: public Assembler { Register link(LinkRegister); Memory returnAddressSrc (StackRegister, (footprint - 1) * TargetBytesPerWord); - moveMR(&c, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, + moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, &link); Register stack(StackRegister); ResolvedPromise footprintPromise ((footprint - offset) * TargetBytesPerWord); Constant footprintConstant(&footprintPromise); - addC(&c, TargetBytesPerWord, &footprintConstant, &stack, &stack); + addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); if (returnAddressSurrogate != NoRegister) { - assert(&c, offset > 0); + assert(&con, offset > 0); Register ras(returnAddressSurrogate); Memory dst(StackRegister, (offset - 1) * TargetBytesPerWord); - moveRM(&c, TargetBytesPerWord, &ras, TargetBytesPerWord, &dst); + moveRM(&con, TargetBytesPerWord, &ras, TargetBytesPerWord, &dst); } } else { popFrame(footprint); } } else { - abort(&c); + abort(&con); } } @@ -2294,8 +2726,8 @@ class MyAssembler: public Assembler { { popFrame(frameFootprint); - assert(&c, argumentFootprint >= StackAlignmentInWords); - assert(&c, (argumentFootprint % StackAlignmentInWords) == 0); + assert(&con, argumentFootprint >= StackAlignmentInWords); + assert(&con, (argumentFootprint % StackAlignmentInWords) == 0); unsigned offset; if (TailCalls and argumentFootprint > StackAlignmentInWords) { @@ -2304,12 +2736,12 @@ class MyAssembler: public Assembler { Register stack(StackRegister); ResolvedPromise adjustmentPromise(offset * TargetBytesPerWord); Constant adjustment(&adjustmentPromise); - addC(&c, TargetBytesPerWord, &adjustment, &stack, &stack); + addC(&con, TargetBytesPerWord, &adjustment, &stack, &stack); } else { offset = 0; } - return_(&c); + return_(&con); } virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint, @@ -2319,28 +2751,28 @@ class MyAssembler: public Assembler { Register stack(StackRegister); Memory newStackSrc(ThreadRegister, stackOffsetFromThread); - moveMR(&c, TargetBytesPerWord, &newStackSrc, TargetBytesPerWord, &stack); + moveMR(&con, TargetBytesPerWord, &newStackSrc, TargetBytesPerWord, &stack); - return_(&c); + return_(&con); } virtual void apply(Operation op) { - arch_->c.operations[op](&c); + arch_->con.operations[op](&con); } virtual void apply(UnaryOperation op, unsigned aSize, OperandType aType, Operand* aOperand) { - arch_->c.unaryOperations[index(&(arch_->c), op, aType)] - (&c, aSize, aOperand); + arch_->con.unaryOperations[index(&(arch_->con), op, aType)] + (&con, aSize, aOperand); } virtual void apply(BinaryOperation op, unsigned aSize, OperandType aType, Operand* aOperand, unsigned bSize, OperandType bType, Operand* bOperand) { - arch_->c.binaryOperations[index(&(arch_->c), op, aType, bType)] - (&c, aSize, aOperand, bSize, bOperand); + arch_->con.binaryOperations[index(&(arch_->con), op, aType, bType)] + (&con, aSize, aOperand, bSize, bOperand); } virtual void apply(TernaryOperation op, @@ -2351,30 +2783,30 @@ class MyAssembler: public Assembler { Operand* cOperand) { if (isBranch(op)) { - assert(&c, aSize == bSize); - assert(&c, cSize == TargetBytesPerWord); - assert(&c, cType == ConstantOperand); + assert(&con, aSize == bSize); + assert(&con, cSize == TargetBytesPerWord); + assert(&con, cType == ConstantOperand); - arch_->c.branchOperations[branchIndex(&(arch_->c), aType, bType)] - (&c, op, aSize, aOperand, bOperand, cOperand); + arch_->con.branchOperations[branchIndex(&(arch_->con), aType, bType)] + (&con, op, aSize, aOperand, bOperand, cOperand); } else { - assert(&c, bSize == cSize); - assert(&c, bType == RegisterOperand); - assert(&c, cType == RegisterOperand); + assert(&con, bSize == cSize); + assert(&con, bType == RegisterOperand); + assert(&con, cType == RegisterOperand); - arch_->c.ternaryOperations[index(&(arch_->c), op, aType)] - (&c, bSize, aOperand, bOperand, cOperand); + arch_->con.ternaryOperations[index(&(arch_->con), op, aType)] + (&con, bSize, aOperand, bOperand, cOperand); } } virtual void setDestination(uint8_t* dst) { - c.result = dst; + con.result = dst; } virtual void write() { - uint8_t* dst = c.result; + uint8_t* dst = con.result; unsigned dstOffset = 0; - for (MyBlock* b = c.firstBlock; b; b = b->next) { + for (MyBlock* b = con.firstBlock; b; b = b->next) { if (DebugPool) { fprintf(stderr, "write block %p\n", b); } @@ -2382,7 +2814,7 @@ class MyAssembler: public Assembler { unsigned blockOffset = 0; for (PoolEvent* e = b->poolEventHead; e; e = e->next) { unsigned size = e->offset - blockOffset; - memcpy(dst + dstOffset, c.code.data + b->offset + blockOffset, size); + memcpy(dst + dstOffset, con.code.data + b->offset + blockOffset, size); blockOffset = e->offset; dstOffset += size; @@ -2405,7 +2837,7 @@ class MyAssembler: public Assembler { + padding(o->block, o->offset) + o->offset; int32_t v = (entry - 8) - instruction; - expect(&c, v == (v & PoolOffsetMask)); + expect(&con, v == (v & PoolOffsetMask)); int32_t* p = reinterpret_cast(dst + instruction); *p = (v & PoolOffsetMask) | ((~PoolOffsetMask) & *p); @@ -2425,22 +2857,22 @@ class MyAssembler: public Assembler { unsigned size = b->size - blockOffset; memcpy(dst + dstOffset, - c.code.data + b->offset + blockOffset, + con.code.data + b->offset + blockOffset, size); dstOffset += size; } - for (Task* t = c.tasks; t; t = t->next) { - t->run(&c); + for (Task* t = con.tasks; t; t = t->next) { + t->run(&con); } - for (ConstantPoolEntry* e = c.constantPool; e; e = e->next) { + for (ConstantPoolEntry* e = con.constantPool; e; e = e->next) { if (e->constant->resolved()) { *static_cast(e->address) = e->constant->value(); } else { new (e->constant->listen(sizeof(ConstantPoolListener))) - ConstantPoolListener(c.s, static_cast(e->address), + ConstantPoolListener(con.s, static_cast(e->address), e->callOffset ? dst + e->callOffset->value() + 8 : 0); @@ -2450,31 +2882,30 @@ class MyAssembler: public Assembler { } virtual Promise* offset(bool forTrace) { - return ::offset(&c, forTrace); + return ::offset(&con, forTrace); } virtual Block* endBlock(bool startNew) { - MyBlock* b = c.lastBlock; - b->size = c.code.length() - b->offset; + MyBlock* b = con.lastBlock; + b->size = con.code.length() - b->offset; if (startNew) { - c.lastBlock = new (c.zone->allocate(sizeof(MyBlock))) - MyBlock(&c, c.code.length()); + con.lastBlock = new (con.zone) MyBlock(&con, con.code.length()); } else { - c.lastBlock = 0; + con.lastBlock = 0; } return b; } virtual void endEvent() { - MyBlock* b = c.lastBlock; - unsigned thisEventOffset = c.code.length() - b->offset; + MyBlock* b = con.lastBlock; + unsigned thisEventOffset = con.code.length() - b->offset; if (b->poolOffsetHead) { int32_t v = (thisEventOffset + TargetBytesPerWord - 8) - b->poolOffsetHead->offset; if (v > 0 and v != (v & PoolOffsetMask)) { appendPoolEvent - (&c, b, b->lastEventOffset, b->poolOffsetHead, + (&con, b, b->lastEventOffset, b->poolOffsetHead, b->lastPoolOffsetTail); if (DebugPool) { @@ -2500,7 +2931,7 @@ class MyAssembler: public Assembler { } virtual unsigned length() { - return c.code.length(); + return con.code.length(); } virtual unsigned footerSize() { @@ -2508,10 +2939,10 @@ class MyAssembler: public Assembler { } virtual void dispose() { - c.code.dispose(); + con.code.dispose(); } - Context c; + Context con; MyArchitecture* arch_; }; @@ -2529,8 +2960,7 @@ Assembler* makeAssembler(System* system, Allocator* allocator, Zone* zone, Assembler::Architecture* architecture) { - return new (zone->allocate(sizeof(MyAssembler))) - MyAssembler(system, allocator, zone, + return new(zone) MyAssembler(system, allocator, zone, static_cast(architecture)); } diff --git a/src/assembler.h b/src/assembler.h index 1566df6cd7..d2ba2caf5d 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -32,10 +32,11 @@ enum Operation { Return, LoadBarrier, StoreStoreBarrier, - StoreLoadBarrier + StoreLoadBarrier, + Trap }; -const unsigned OperationCount = StoreLoadBarrier + 1; +const unsigned OperationCount = Trap + 1; enum UnaryOperation { Call, @@ -367,7 +368,7 @@ class Assembler { virtual unsigned alignFrameSize(unsigned sizeInWords) = 0; virtual void nextFrame(void* start, unsigned size, unsigned footprint, - void* link, void* stackLimit, + void* link, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) = 0; virtual void* frameIp(void* stack) = 0; diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index bdfdce51c3..b4e0025b02 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2011, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -8,12 +8,15 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "string.h" +#include +#include +#include +#include #include "endianness.h" +#include "tools.h" + #define EI_NIDENT 16 #define EI_MAG0 0 @@ -62,344 +65,317 @@ #define STV_DEFAULT 0 -#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) -#define ELF32_ST_INFO(bind, type) ELF64_ST_INFO((bind), (type)) - -#if (BITS_PER_WORD == 64) -# define FileHeader Elf64_Ehdr -# define SectionHeader Elf64_Shdr -# define Symbol Elf64_Sym -# define Class ELFCLASS64 -# define SYMBOL_INFO ELF64_ST_INFO -#elif (BITS_PER_WORD == 32) -# define FileHeader Elf32_Ehdr -# define SectionHeader Elf32_Shdr -# define Symbol Elf32_Sym -# define Class ELFCLASS32 -# define SYMBOL_INFO ELF32_ST_INFO -#else -# error -#endif +#define SYMBOL_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) #define OSABI ELFOSABI_SYSV namespace { -typedef uint16_t Elf64_Half; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Addr; -typedef uint64_t Elf64_Xword; -typedef uint16_t Elf64_Section; -typedef uint64_t Elf64_Off; +using namespace avian::tools; -struct Elf64_Ehdr { - unsigned char e_ident[EI_NIDENT]; - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; - Elf64_Off e_phoff; - Elf64_Off e_shoff; - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; +template +struct ElfTypes { + typedef uint16_t Half; + typedef uint32_t Word; + typedef AddrTy Addr; + typedef uint64_t Xword; + typedef uint16_t Section; + typedef AddrTy Off; + typedef AddrTy XFlags; + static const unsigned BytesPerWord = sizeof(AddrTy); }; -struct Elf64_Shdr { - Elf64_Word sh_name; - Elf64_Word sh_type; - Elf64_Xword sh_flags; - Elf64_Addr sh_addr; - Elf64_Off sh_offset; - Elf64_Xword sh_size; - Elf64_Word sh_link; - Elf64_Word sh_info; - Elf64_Xword sh_addralign; - Elf64_Xword sh_entsize; -}; +template +struct Symbol_Ty; -struct Elf64_Sym { - Elf64_Word st_name; +template<> +struct Symbol_Ty { + typedef ElfTypes Elf; + + Elf::Word st_name; unsigned char st_info; unsigned char st_other; - Elf64_Section st_shndx; - Elf64_Addr st_value; - Elf64_Xword st_size; + Elf::Section st_shndx; + Elf::Addr st_value; + Elf::Xword st_size; }; -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Word; -typedef uint32_t Elf32_Addr; -typedef uint64_t Elf32_Xword; -typedef uint16_t Elf32_Section; -typedef uint32_t Elf32_Off; +template<> +struct Symbol_Ty { + typedef ElfTypes Elf; -struct Elf32_Ehdr { - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -}; - -struct Elf32_Shdr { - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -}; - -struct Elf32_Sym { - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; + Elf::Word st_name; + Elf::Addr st_value; + Elf::Word st_size; unsigned char st_info; unsigned char st_other; - Elf32_Section st_shndx; + Elf::Section st_shndx; }; -void -writeObject(const uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* sectionName, unsigned sectionFlags, - unsigned alignment, int machine, int encoding) -{ - const unsigned sectionCount = 5; - const unsigned symbolCount = 2; +using avian::endian::Endianness; - const unsigned sectionNameLength = strlen(sectionName) + 1; - const unsigned startNameLength = strlen(startName) + 1; - const unsigned endNameLength = strlen(endName) + 1; +#define V1 Endianness::v1 +#define V2 Endianness::v2 +#define V3 Endianness::v3 +#define V4 Endianness::v4 +#define VANY Endianness::vAny - const char* const sectionStringTableName = ".shstrtab"; - const char* const stringTableName = ".strtab"; - const char* const symbolTableName = ".symtab"; - const unsigned sectionStringTableNameLength - = strlen(sectionStringTableName) + 1; - const unsigned stringTableNameLength = strlen(stringTableName) + 1; - const unsigned symbolTableNameLength = strlen(symbolTableName) + 1; - - const unsigned nullStringOffset = 0; - - const unsigned sectionStringTableNameOffset = nullStringOffset + 1; - const unsigned stringTableNameOffset - = sectionStringTableNameOffset + sectionStringTableNameLength; - const unsigned symbolTableNameOffset - = stringTableNameOffset + stringTableNameLength; - const unsigned sectionNameOffset - = symbolTableNameOffset + symbolTableNameLength; - const unsigned sectionStringTableLength - = sectionNameOffset + sectionNameLength; - - const unsigned startNameOffset = nullStringOffset + 1; - const unsigned endNameOffset = startNameOffset + startNameLength; - const unsigned stringTableLength = endNameOffset + endNameLength; - - const unsigned bodySectionNumber = 1; - const unsigned sectionStringTableSectionNumber = 2; - const unsigned stringTableSectionNumber = 3; - - FileHeader fileHeader; - memset(&fileHeader, 0, sizeof(FileHeader)); - fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0); - fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1); - fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2); - fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3); - fileHeader.e_ident[EI_CLASS] = V1(Class); - fileHeader.e_ident[EI_DATA] = V1(encoding); - fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT); - fileHeader.e_ident[EI_OSABI] = V1(OSABI); - fileHeader.e_ident[EI_ABIVERSION] = V1(0); - fileHeader.e_type = V2(ET_REL); - fileHeader.e_machine = V2(machine); - fileHeader.e_version = V4(EV_CURRENT); - fileHeader.e_entry = VW(0); - fileHeader.e_phoff = VW(0); - fileHeader.e_shoff = VW(sizeof(FileHeader)); - fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); - fileHeader.e_ehsize = V2(sizeof(FileHeader)); - fileHeader.e_phentsize = V2(0); - fileHeader.e_phnum = V2(0); - fileHeader.e_shentsize = V2(sizeof(SectionHeader)); - fileHeader.e_shnum = V2(sectionCount); - fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber); - - SectionHeader nullSection; - memset(&nullSection, 0, sizeof(SectionHeader)); - - SectionHeader bodySection; - bodySection.sh_name = V4(sectionNameOffset); - bodySection.sh_type = V4(SHT_PROGBITS); - bodySection.sh_flags = VW(sectionFlags); - bodySection.sh_addr = VW(0); - unsigned bodySectionOffset - = sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount); - bodySection.sh_offset = VW(bodySectionOffset); - unsigned bodySectionSize = size; - bodySection.sh_size = VW(bodySectionSize); - bodySection.sh_link = V4(0); - bodySection.sh_info = V4(0); - bodySection.sh_addralign = VW(alignment); - bodySection.sh_entsize = VW(0); - - SectionHeader sectionStringTableSection; - sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset); - sectionStringTableSection.sh_type = V4(SHT_STRTAB); - sectionStringTableSection.sh_flags = VW(0); - sectionStringTableSection.sh_addr = VW(0); - unsigned sectionStringTableSectionOffset - = bodySectionOffset + bodySectionSize; - sectionStringTableSection.sh_offset = VW(sectionStringTableSectionOffset); - unsigned sectionStringTableSectionSize = sectionStringTableLength; - sectionStringTableSection.sh_size = VW(sectionStringTableSectionSize); - sectionStringTableSection.sh_link = V4(0); - sectionStringTableSection.sh_info = V4(0); - sectionStringTableSection.sh_addralign = VW(1); - sectionStringTableSection.sh_entsize = VW(0); - - SectionHeader stringTableSection; - stringTableSection.sh_name = V4(stringTableNameOffset); - stringTableSection.sh_type = V4(SHT_STRTAB); - stringTableSection.sh_flags = VW(0); - stringTableSection.sh_addr = VW(0); - unsigned stringTableSectionOffset - = sectionStringTableSectionOffset + sectionStringTableSectionSize; - stringTableSection.sh_offset = VW(stringTableSectionOffset); - unsigned stringTableSectionSize = stringTableLength; - stringTableSection.sh_size = VW(stringTableSectionSize); - stringTableSection.sh_link = V4(0); - stringTableSection.sh_info = V4(0); - stringTableSection.sh_addralign = VW(1); - stringTableSection.sh_entsize = VW(0); - - SectionHeader symbolTableSection; - symbolTableSection.sh_name = V4(symbolTableNameOffset); - symbolTableSection.sh_type = V4(SHT_SYMTAB); - symbolTableSection.sh_flags = VW(0); - symbolTableSection.sh_addr = VW(0); - unsigned symbolTableSectionOffset - = stringTableSectionOffset + stringTableSectionSize; - symbolTableSection.sh_offset = VW(symbolTableSectionOffset); - unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount; - symbolTableSection.sh_size = VW(symbolTableSectionSize); - symbolTableSection.sh_link = V4(stringTableSectionNumber); - symbolTableSection.sh_info = V4(0); - symbolTableSection.sh_addralign = VW(BITS_PER_WORD / 8); - symbolTableSection.sh_entsize = VW(sizeof(Symbol)); - - Symbol startSymbol; - startSymbol.st_name = V4(startNameOffset); - startSymbol.st_value = VW(0); - startSymbol.st_size = VW(0); - startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - startSymbol.st_other = V1(STV_DEFAULT); - startSymbol.st_shndx = V2(bodySectionNumber); - - Symbol endSymbol; - endSymbol.st_name = V4(endNameOffset); - endSymbol.st_value = VW(size); - endSymbol.st_size = VW(0); - endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - endSymbol.st_other = V1(STV_DEFAULT); - endSymbol.st_shndx = V2(bodySectionNumber); - - fwrite(&fileHeader, 1, sizeof(fileHeader), out); - fwrite(&nullSection, 1, sizeof(nullSection), out); - fwrite(&bodySection, 1, sizeof(bodySection), out); - fwrite(§ionStringTableSection, 1, sizeof(sectionStringTableSection), - out); - fwrite(&stringTableSection, 1, sizeof(stringTableSection), out); - fwrite(&symbolTableSection, 1, sizeof(symbolTableSection), out); - - fwrite(data, 1, size, out); - - fputc(0, out); - fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out); - fwrite(stringTableName, 1, stringTableNameLength, out); - fwrite(symbolTableName, 1, symbolTableNameLength, out); - fwrite(sectionName, 1, sectionNameLength, out); - - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); - - fwrite(&startSymbol, 1, sizeof(startSymbol), out); - fwrite(&endSymbol, 1, sizeof(endSymbol), out); +unsigned getElfPlatform(PlatformInfo::Architecture arch) { + switch(arch) { + case PlatformInfo::x86_64: + return EM_X86_64; + case PlatformInfo::x86: + return EM_386; + case PlatformInfo::Arm: + return EM_ARM; + case PlatformInfo::PowerPC: + return EM_PPC; + default: + return ~0; + } } +const char* getSectionName(unsigned accessFlags, unsigned& sectionFlags) { + sectionFlags = SHF_ALLOC; + if (accessFlags & Platform::Writable) { + if (accessFlags & Platform::Executable) { + sectionFlags |= SHF_WRITE | SHF_EXECINSTR; + return ".rwx"; + } else { + sectionFlags |= SHF_WRITE; + return ".data"; + } + } else if (accessFlags & Platform::Executable) { + sectionFlags |= SHF_EXECINSTR; + return ".text"; + } else { + return ".rodata"; + } +} + +template +class ElfPlatform : public Platform { +public: + + typedef ElfTypes Elf; + static const unsigned Class = Elf::BytesPerWord / 4; + + struct FileHeader { + unsigned char e_ident[EI_NIDENT]; + typename Elf::Half e_type; + typename Elf::Half e_machine; + typename Elf::Word e_version; + typename Elf::Addr e_entry; + typename Elf::Off e_phoff; + typename Elf::Off e_shoff; + typename Elf::Word e_flags; + typename Elf::Half e_ehsize; + typename Elf::Half e_phentsize; + typename Elf::Half e_phnum; + typename Elf::Half e_shentsize; + typename Elf::Half e_shnum; + typename Elf::Half e_shstrndx; + }; + + struct SectionHeader { + typename Elf::Word sh_name; + typename Elf::Word sh_type; + typename Elf::XFlags sh_flags; + typename Elf::Addr sh_addr; + typename Elf::Off sh_offset; + typename Elf::Off sh_size; + typename Elf::Word sh_link; + typename Elf::Word sh_info; + typename Elf::Addr sh_addralign; + typename Elf::Off sh_entsize; + }; + + typedef Symbol_Ty Symbol; + + static const unsigned Encoding = TargetLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; + + const unsigned machine; + + ElfPlatform(PlatformInfo::Architecture arch): + Platform(PlatformInfo(PlatformInfo::Linux, arch)), + machine(getElfPlatform(arch)) {} + + class FileWriter { + public: + unsigned sectionCount; + unsigned sectionStringTableSectionNumber; + + AddrTy dataOffset; + + FileHeader header; + StringTable strings; + + FileWriter(unsigned machine): + sectionCount(0), + dataOffset(sizeof(FileHeader)) + { + memset(&header, 0, sizeof(FileHeader)); + header.e_ident[EI_MAG0] = V1(ELFMAG0); + header.e_ident[EI_MAG1] = V1(ELFMAG1); + header.e_ident[EI_MAG2] = V1(ELFMAG2); + header.e_ident[EI_MAG3] = V1(ELFMAG3); + header.e_ident[EI_CLASS] = V1(Class); + header.e_ident[EI_DATA] = V1(Encoding); + header.e_ident[EI_VERSION] = V1(EV_CURRENT); + header.e_ident[EI_OSABI] = V1(OSABI); + header.e_ident[EI_ABIVERSION] = V1(0); + header.e_type = V2(ET_REL); + header.e_machine = V2(machine); + header.e_version = V4(EV_CURRENT); + header.e_entry = VANY(static_cast(0)); + header.e_phoff = VANY(static_cast(0)); + header.e_shoff = VANY(static_cast(sizeof(FileHeader))); + header.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); + header.e_ehsize = V2(sizeof(FileHeader)); + header.e_phentsize = V2(0); + header.e_phnum = V2(0); + header.e_shentsize = V2(sizeof(SectionHeader)); + } + + void writeHeader(OutputStream* out) { + header.e_shnum = V2(sectionCount); + header.e_shstrndx = V2(sectionStringTableSectionNumber); + out->writeChunk(&header, sizeof(FileHeader)); + } + }; + + class SectionWriter { + public: + FileWriter& file; + String name; + SectionHeader header; + const size_t* dataSize; + const uint8_t* const* data; + + SectionWriter(FileWriter& file): + file(file), + name(""), + dataSize(0), + data(0) + { + memset(&header, 0, sizeof(SectionHeader)); + file.sectionCount++; + file.dataOffset += sizeof(SectionHeader); + size_t nameOffset = file.strings.add(name); + header.sh_name = V4(nameOffset); + } + + SectionWriter( + FileWriter& file, + const char* chname, + unsigned type, + AddrTy flags, + unsigned alignment, + AddrTy addr, + const uint8_t* const* data, + size_t* dataSize, + size_t entsize = 0, + unsigned link = 0): + + file(file), + name(chname), + dataSize(dataSize), + data(data) + { + if(strcmp(chname, ".shstrtab") == 0) { + file.sectionStringTableSectionNumber = file.sectionCount; + } + file.sectionCount++; + file.dataOffset += sizeof(SectionHeader); + size_t nameOffset = file.strings.add(name); + + header.sh_name = V4(nameOffset); + header.sh_type = V4(type); + header.sh_flags = VANY(flags); + header.sh_addr = VANY(addr); + // header.sh_offset = VANY(static_cast(bodySectionOffset)); + // header.sh_size = VANY(static_cast(*dataSize)); + header.sh_link = V4(link); + header.sh_info = V4(0); + header.sh_addralign = VANY(static_cast(alignment)); + header.sh_entsize = VANY(static_cast(entsize)); + } + + void writeHeader(OutputStream* out) { + if(dataSize) { + header.sh_offset = VANY(file.dataOffset); + header.sh_size = VANY(static_cast(*dataSize)); + file.dataOffset += *dataSize; + } + + out->writeChunk(&header, sizeof(SectionHeader)); + } + + void writeData(OutputStream* out) { + if(data) { + out->writeChunk(*data, *dataSize); + } + } + + + }; + + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) { + + unsigned sectionFlags; + const char* sectionName = getSectionName(accessFlags, sectionFlags); + + StringTable symbolStringTable; + Buffer symbolTable; + + FileWriter file(machine); + + const int bodySectionNumber = 1; + const int stringTableSectionNumber = 3; + + SectionWriter sections[] = { + SectionWriter(file), // null section + SectionWriter(file, sectionName, SHT_PROGBITS, sectionFlags, alignment, 0, &data.items, &data.count), // body section + SectionWriter(file, ".shstrtab", SHT_STRTAB, 0, 1, 0, &file.strings.data, &file.strings.length), + SectionWriter(file, ".strtab", SHT_STRTAB, 0, 1, 0, &symbolStringTable.data, &symbolStringTable.length), + SectionWriter(file, ".symtab", SHT_SYMTAB, 0, 8, 0, &symbolTable.data, &symbolTable.length, sizeof(Symbol), stringTableSectionNumber) + }; + + // for some reason, string tables require a null first element... + symbolStringTable.add(""); + + for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + size_t nameOffset = symbolStringTable.add(sym->name); + + Symbol symbolStruct; + symbolStruct.st_name = V4(nameOffset); + symbolStruct.st_value = VANY(static_cast(sym->addr)); + symbolStruct.st_size = VANY(static_cast(0)); + symbolStruct.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); + symbolStruct.st_other = V1(STV_DEFAULT); + symbolStruct.st_shndx = V2(bodySectionNumber); + symbolTable.write(&symbolStruct, sizeof(Symbol)); + } + + file.writeHeader(out); + + for(unsigned i = 0; i < file.sectionCount; i++) { + sections[i].writeHeader(out); + } + + for(unsigned i = 0; i < file.sectionCount; i++) { + sections[i].writeData(out); + } + + return true; + } +}; + +ElfPlatform elfx86Platform(PlatformInfo::x86); +ElfPlatform elfArmPlatform(PlatformInfo::Arm); +ElfPlatform elfPowerPCPlatform(PlatformInfo::PowerPC); +ElfPlatform elfx86_64Platform(PlatformInfo::x86_64); + + } // namespace - -#define MACRO_MAKE_NAME(a, b, c) a##b##c -#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c) - -namespace binaryToObject { - -bool -MAKE_NAME(writeElf, BITS_PER_WORD, Object) - (uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, unsigned alignment, - bool writable, bool executable) -{ - int machine; - int encoding; - if (strcmp(architecture, "x86_64") == 0) { - machine = EM_X86_64; - encoding = ELFDATA2LSB; - } else if (strcmp(architecture, "i386") == 0) { - machine = EM_386; - encoding = ELFDATA2LSB; - } else if (strcmp(architecture, "arm") == 0) { - machine = EM_ARM; - encoding = ELFDATA2LSB; - } else if (strcmp(architecture, "powerpc") == 0) { - machine = EM_PPC; - encoding = ELFDATA2MSB; - } else { - fprintf(stderr, "unsupported architecture: %s\n", architecture); - return false; - } - - const char* sectionName; - unsigned sectionFlags = SHF_ALLOC; - if (writable) { - if (executable) { - sectionName = ".rwx"; - sectionFlags |= SHF_WRITE | SHF_EXECINSTR; - } else { - sectionName = ".data"; - sectionFlags |= SHF_WRITE; - } - } else if (executable) { - sectionName = ".text"; - sectionFlags |= SHF_EXECINSTR; - } else { - sectionName = ".rodata"; - } - - writeObject(data, size, out, startName, endName, sectionName, sectionFlags, - alignment, machine, encoding); - - return true; -} - -} // namespace binaryToObject diff --git a/src/binaryToObject/endianness.h b/src/binaryToObject/endianness.h index 46cfcd8b46..d1501a3926 100644 --- a/src/binaryToObject/endianness.h +++ b/src/binaryToObject/endianness.h @@ -1,38 +1,81 @@ -#ifndef ENDIANNESS_H -#define ENDIANNESS_H +/* Copyright (c) 2008-2012, Avian Contributors -#define V1(v) (v) + 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. -#ifdef OPPOSITE_ENDIAN -# define V2(v) \ - ((((v) >> 8) & 0xFF) | \ - (((v) << 8))) -# define V4(v) \ - ((((v) >> 24) & 0x000000FF) | \ - (((v) >> 8) & 0x0000FF00) | \ - (((v) << 8) & 0x00FF0000) | \ - (((v) << 24))) -# define V8(v) \ - (((static_cast(v) >> 56) & UINT64_C(0x00000000000000FF)) | \ - ((static_cast(v) >> 40) & UINT64_C(0x000000000000FF00)) | \ - ((static_cast(v) >> 24) & UINT64_C(0x0000000000FF0000)) | \ - ((static_cast(v) >> 8) & UINT64_C(0x00000000FF000000)) | \ - ((static_cast(v) << 8) & UINT64_C(0x000000FF00000000)) | \ - ((static_cast(v) << 24) & UINT64_C(0x0000FF0000000000)) | \ - ((static_cast(v) << 40) & UINT64_C(0x00FF000000000000)) | \ - ((static_cast(v) << 56))) -#else -# define V2(v) (v) -# define V4(v) (v) -# define V8(v) (v) -#endif + There is NO WARRANTY for this software. See license.txt for + details. */ -#if (BITS_PER_WORD == 64) -# define VW(v) V8(v) -#elif (BITS_PER_WORD == 32) -# define VW(v) V4(v) -#else -# error -#endif +#ifndef AVIAN_ENDIANNESS_H +#define AVIAN_ENDIANNESS_H -#endif//ENDIANNESS_H +namespace avian { + +namespace endian { + +static union { + uint32_t i; + char c[4]; +} _DetectEndianness = {1}; + +const bool LittleEndian = _DetectEndianness.c[0] == 1; + +template +class Endianness { +public: + static inline uint8_t v1(uint8_t v) { + return v; + } + + static inline uint16_t v2(uint16_t v) { + if(LittleEndian == TargetLittleEndian) { + return v; + } else { + return ((v >> 8) & 0xFF) | (v << 8); + } + } + + static inline uint32_t v4(uint32_t v) { + if(LittleEndian == TargetLittleEndian) { + return v; + } else { + return + ((v >> 24) & 0x000000FF) | + ((v >> 8) & 0x0000FF00) | + ((v << 8) & 0x00FF0000) | + ((v << 24)); + } + } + + static inline uint32_t vAny(uint32_t v) { + return v4(v); + } + + static inline uint64_t v8(uint64_t v) { + if(LittleEndian == TargetLittleEndian) { + return v; + } else { + return + ((static_cast(v) >> 56) & (static_cast(0xff) << 0)) | + ((static_cast(v) >> 40) & (static_cast(0xff) << 8)) | + ((static_cast(v) >> 24) & (static_cast(0xff) << 16)) | + ((static_cast(v) >> 8) & (static_cast(0xff) << 24)) | + ((static_cast(v) << 8) & (static_cast(0xff) << 32)) | + ((static_cast(v) << 24) & (static_cast(0xff) << 40)) | + ((static_cast(v) << 40) & (static_cast(0xff) << 48)) | + ((static_cast(v) << 56)); + } + } + + static inline uint64_t vAny(uint64_t v) { + return v8(v); + } +}; + +} // namespace endian + +} // namespace avian + +#endif // AVIAN_ENDIANNESS_H diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 8b37e85aaf..dd89ddb304 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -8,19 +8,19 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "string.h" +#include +#include +#include #include "endianness.h" +#include "tools.h" + #define MH_MAGIC_64 0xfeedfacf #define MH_MAGIC 0xfeedface #define MH_OBJECT 1 -#define LC_SEGMENT_64 0x19 -#define LC_SEGMENT 1 #define LC_SYMTAB 2 #define S_REGULAR 0 @@ -40,142 +40,21 @@ #define CPU_SUBTYPE_POWERPC_ALL 0 #define CPU_SUBTYPE_ARM_V7 9 -#if (BITS_PER_WORD == 64) -# define Magic MH_MAGIC_64 -# define Segment LC_SEGMENT_64 -# define FileHeader mach_header_64 -# define SegmentCommand segment_command_64 -# define Section section_64 -# define NList struct nlist_64 -#elif (BITS_PER_WORD == 32) -# define Magic MH_MAGIC -# define Segment LC_SEGMENT -# define FileHeader mach_header -# define SegmentCommand segment_command -# define Section section -# define NList struct nlist -#else -# error -#endif - namespace { +using namespace avian::tools; + typedef int cpu_type_t; typedef int cpu_subtype_t; typedef int vm_prot_t; -struct mach_header_64 { - uint32_t magic; - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint32_t filetype; - uint32_t ncmds; - uint32_t sizeofcmds; - uint32_t flags; - uint32_t reserved; -}; +using avian::endian::Endianness; -struct segment_command_64 { - uint32_t cmd; - uint32_t cmdsize; - char segname[16]; - uint64_t vmaddr; - uint64_t vmsize; - uint64_t fileoff; - uint64_t filesize; - vm_prot_t maxprot; - vm_prot_t initprot; - uint32_t nsects; - uint32_t flags; -}; - -struct section_64 { - char sectname[16]; - char segname[16]; - uint64_t addr; - uint64_t size; - uint32_t offset; - uint32_t align; - uint32_t reloff; - uint32_t nreloc; - uint32_t flags; - uint32_t reserved1; - uint32_t reserved2; - uint32_t reserved3; -}; - -struct nlist_64 { - union { - uint32_t n_strx; - } n_un; - uint8_t n_type; - uint8_t n_sect; - uint16_t n_desc; - uint64_t n_value; -}; - -struct mach_header { - uint32_t magic; - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint32_t filetype; - uint32_t ncmds; - uint32_t sizeofcmds; - uint32_t flags; -}; - -struct segment_command { - uint32_t cmd; - uint32_t cmdsize; - char segname[16]; - uint32_t vmaddr; - uint32_t vmsize; - uint32_t fileoff; - uint32_t filesize; - vm_prot_t maxprot; - vm_prot_t initprot; - uint32_t nsects; - uint32_t flags; -}; - -struct section { - char sectname[16]; - char segname[16]; - uint32_t addr; - uint32_t size; - uint32_t offset; - uint32_t align; - uint32_t reloff; - uint32_t nreloc; - uint32_t flags; - uint32_t reserved1; - uint32_t reserved2; -}; - -struct symtab_command { - uint32_t cmd; - uint32_t cmdsize; - uint32_t symoff; - uint32_t nsyms; - uint32_t stroff; - uint32_t strsize; -}; - -struct nlist { - union { - int32_t n_strx; - } n_un; - uint8_t n_type; - uint8_t n_sect; - int16_t n_desc; - uint32_t n_value; -}; - -inline unsigned -pad(unsigned n) -{ - return (n + ((BITS_PER_WORD / 8) - 1)) & ~((BITS_PER_WORD / 8) - 1); -} +#define V1 Endianness::v1 +#define V2 Endianness::v2 +#define V3 Endianness::v3 +#define V4 Endianness::v4 +#define VANY Endianness::vAny inline unsigned log(unsigned n) @@ -185,177 +64,235 @@ log(unsigned n) return r; } -void -writeObject(const uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* segmentName, const char* sectionName, - unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) -{ - unsigned startNameLength = strlen(startName) + 1; - unsigned endNameLength = strlen(endName) + 1; +template +class MachOPlatform : public Platform { +public: - FileHeader header = { - V4(Magic), // magic - V4(cpuType), - V4(cpuSubType), - V4(MH_OBJECT), // filetype, - V4(2), // ncmds - V4(sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command)), // sizeofcmds - V4(0) // flags + struct FileHeader { + uint32_t magic; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + + union { + uint32_t flags; + AddrTy flagsAndMaybeReserved; + }; }; - SegmentCommand segment = { - V4(Segment), // cmd - V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize - "", // segname - VW(0), // vmaddr - VW(pad(size)), // vmsize - VW(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command)), // fileoff - VW(pad(size)), // filesize - V4(7), // maxprot - V4(7), // initprot - V4(1), // nsects - V4(0) // flags + + struct SegmentCommand { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + AddrTy vmaddr; + AddrTy vmsize; + AddrTy fileoff; + AddrTy filesize; + vm_prot_t maxprot; + vm_prot_t initprot; + uint32_t nsects; + uint32_t flags; }; - strncpy(segment.segname, segmentName, sizeof(segment.segname)); - - Section sect = { - "", // sectname - "", // segname - VW(0), // addr - VW(pad(size)), // size - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command)), // offset - V4(log(alignment)), // align - V4(0), // reloff - V4(0), // nreloc - V4(S_REGULAR), // flags - V4(0), // reserved1 - V4(0), // reserved2 + struct Section { + char sectname[16]; + char segname[16]; + AddrTy addr; + AddrTy size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + AddrTy reserved2AndMaybe3; }; - strncpy(sect.segname, segmentName, sizeof(sect.segname)); - strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); - - symtab_command symbolTable = { - V4(LC_SYMTAB), // cmd - V4(sizeof(symtab_command)), // cmdsize - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command) - + pad(size)), // symoff - V4(2), // nsyms - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command) - + pad(size) - + (sizeof(NList) * 2)), // stroff - V4(1 + startNameLength + endNameLength), // strsize + struct NList { + union { + uint32_t n_strx; + } n_un; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + AddrTy n_value; }; - NList symbolList[] = { - { - V4(1), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VW(0) // n_value - }, - { - V4(1 + startNameLength), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VW(size) // n_value + struct SymtabCommand { + uint32_t cmd; + uint32_t cmdsize; + uint32_t symoff; + uint32_t nsyms; + uint32_t stroff; + uint32_t strsize; + }; + + static const unsigned BytesPerWord = sizeof(AddrTy); + static const unsigned Segment = BytesPerWord == 8 ? 0x19 : 1; + static const unsigned Magic = BytesPerWord == 8 ? 0xfeedfacf : 0xfeedface; + + static inline unsigned + pad(unsigned n) + { + return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1); + } + + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) { + cpu_type_t cpuType; + cpu_subtype_t cpuSubType; + switch(info.arch) { + case PlatformInfo::x86_64: + cpuType = CPU_TYPE_X86_64; + cpuSubType = CPU_SUBTYPE_X86_64_ALL; + break; + case PlatformInfo::x86: + cpuType = CPU_TYPE_I386; + cpuSubType = CPU_SUBTYPE_I386_ALL; + break; + case PlatformInfo::PowerPC: + cpuType = CPU_TYPE_POWERPC; + cpuSubType = CPU_SUBTYPE_POWERPC_ALL; + break; + case PlatformInfo::Arm: + cpuType = CPU_TYPE_ARM; + cpuSubType = CPU_SUBTYPE_ARM_V7; + break; + default: + // should never happen (see MachOPlatform declarations at bottom) + fprintf(stderr, "unsupported architecture: %d\n", info.arch); + return false; } - }; - fwrite(&header, 1, sizeof(header), out); - fwrite(&segment, 1, sizeof(segment), out); - fwrite(§, 1, sizeof(sect), out); - fwrite(&symbolTable, 1, sizeof(symbolTable), out); + const char* segmentName; + const char* sectionName; + if (accessFlags & Writable) { + if (accessFlags & Executable) { + segmentName = "__RWX"; + sectionName = "__rwx"; + } else { + segmentName = "__DATA"; + sectionName = "__data"; + } + } else { + segmentName = "__TEXT"; + sectionName = "__text"; + } - fwrite(data, 1, size, out); - for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); + FileHeader header = { + V4(Magic), // magic + static_cast(V4(cpuType)), + static_cast(V4(cpuSubType)), + V4(MH_OBJECT), // filetype, + V4(2), // ncmds + V4(sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // sizeofcmds + { V4(0) } // flags + }; - fwrite(&symbolList, 1, sizeof(symbolList), out); + AddrTy finalSize = pad(data.count); - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); -} + SegmentCommand segment = { + V4(Segment), // cmd + V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize + "", // segname + VANY(static_cast(0)), // vmaddr + VANY(static_cast(finalSize)), // vmsize + VANY(static_cast(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand))), // fileoff + VANY(static_cast(finalSize)), // filesize + static_cast(V4(7)), // maxprot + static_cast(V4(7)), // initprot + V4(1), // nsects + V4(0) // flags + }; + + strncpy(segment.segname, segmentName, sizeof(segment.segname)); + + Section sect = { + "", // sectname + "", // segname + VANY(static_cast(0)), // addr + VANY(static_cast(finalSize)), // size + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // offset + V4(log(alignment)), // align + V4(0), // reloff + V4(0), // nreloc + V4(S_REGULAR), // flags + V4(0), // reserved1 + V4(0), // reserved2 + }; + + strncpy(sect.segname, segmentName, sizeof(sect.segname)); + strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); + + StringTable strings; + strings.add(""); + Buffer symbolList; + + for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + unsigned offset = strings.length; + strings.write("_", 1); + strings.add(sym->name); + NList symbol = { + { V4(offset) }, // n_un + V1(N_SECT | N_EXT), // n_type + V1(1), // n_sect + V2(0), // n_desc + VANY(static_cast(sym->addr)) // n_value + }; + symbolList.write(&symbol, sizeof(NList)); + } + + SymtabCommand symbolTable = { + V4(LC_SYMTAB), // cmd + V4(sizeof(SymtabCommand)), // cmdsize + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + finalSize), // symoff + V4(symbols.count), // nsyms + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + finalSize + + (sizeof(NList) * symbols.count)), // stroff + V4(strings.length), // strsize + }; + + out->writeChunk(&header, sizeof(header)); + out->writeChunk(&segment, sizeof(segment)); + out->writeChunk(§, sizeof(sect)); + out->writeChunk(&symbolTable, sizeof(symbolTable)); + + out->writeChunk(data.items, data.count); + out->writeRepeat(0, finalSize - data.count); + + out->writeChunk(symbolList.data, symbolList.length); + + out->writeChunk(strings.data, strings.length); + + return true; + } + + MachOPlatform(PlatformInfo::Architecture arch): + Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {} + +}; + +MachOPlatform darwinx86Platform(PlatformInfo::x86); +MachOPlatform darwinArmPlatform(PlatformInfo::Arm); +MachOPlatform darwinPowerPCPlatform(PlatformInfo::PowerPC); +MachOPlatform darwinx86_64Platform(PlatformInfo::x86_64); } // namespace - -#define MACRO_MAKE_NAME(a, b, c) a##b##c -#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c) - -namespace binaryToObject { - -bool -MAKE_NAME(writeMachO, BITS_PER_WORD, Object) - (uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, unsigned alignment, - bool writable, bool executable) -{ - cpu_type_t cpuType; - cpu_subtype_t cpuSubType; - if (strcmp(architecture, "x86_64") == 0) { - cpuType = CPU_TYPE_X86_64; - cpuSubType = CPU_SUBTYPE_X86_64_ALL; - } else if (strcmp(architecture, "i386") == 0) { - cpuType = CPU_TYPE_I386; - cpuSubType = CPU_SUBTYPE_I386_ALL; - } else if (strcmp(architecture, "powerpc") == 0) { - cpuType = CPU_TYPE_POWERPC; - cpuSubType = CPU_SUBTYPE_POWERPC_ALL; - } else if (strcmp(architecture, "arm") == 0) { - cpuType = CPU_TYPE_ARM; - cpuSubType = CPU_SUBTYPE_ARM_V7; - } else { - fprintf(stderr, "unsupported architecture: %s\n", architecture); - return false; - } - - const char* segmentName; - const char* sectionName; - if (writable) { - if (executable) { - segmentName = "__RWX"; - sectionName = "__rwx"; - } else { - segmentName = "__DATA"; - sectionName = "__data"; - } - } else { - segmentName = "__TEXT"; - sectionName = "__text"; - } - - unsigned startNameLength = strlen(startName); - char myStartName[startNameLength + 2]; - myStartName[0] = '_'; - memcpy(myStartName + 1, startName, startNameLength + 1); - - unsigned endNameLength = strlen(endName); - char myEndName[endNameLength + 2]; - myEndName[0] = '_'; - memcpy(myEndName + 1, endName, endNameLength + 1); - - writeObject(data, size, out, myStartName, myEndName, segmentName, - sectionName, alignment, cpuType, cpuSubType); - - return true; -} - -} // namespace binaryToObject diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index ffc6f1e017..851a805bec 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -8,111 +8,59 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "stdlib.h" -#include "string.h" +#include +#include +#include +#include -#include "sys/stat.h" +#include #ifdef WIN32 #include #else -#include "sys/mman.h" +#include +#include #endif -#include "fcntl.h" -#include "unistd.h" +#include -namespace binaryToObject { +#include "tools.h" -bool -writeElf64Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); +extern "C" +void __cxa_pure_virtual() { + abort(); +} -bool -writeElf32Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); +void* operator new(size_t size) { + return malloc(size); +} -bool -writeMachO64Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); - -bool -writeMachO32Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); - -bool -writePEObject(uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, - unsigned alignment, bool writable, bool executable); - -} // namespace binaryToObject +void operator delete(void*) { abort(); } namespace { +using namespace avian::tools; + bool -writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* platform, +writeObject(uint8_t* data, size_t size, OutputStream* out, const char* startName, + const char* endName, const char* os, const char* architecture, unsigned alignment, bool writable, bool executable) { - using namespace binaryToObject; + Platform* platform = Platform::getPlatform(PlatformInfo(PlatformInfo::osFromString(os), PlatformInfo::archFromString(architecture))); - bool found = false; - bool success = false; - if (strcmp("linux", platform) == 0) { - if (strcmp("x86_64", architecture) == 0) { - found = true; - success = writeElf64Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } else if (strcmp("i386", architecture) == 0 - or strcmp("arm", architecture) == 0 - or strcmp("powerpc", architecture) == 0) - { - found = true; - success = writeElf32Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } - } else if (strcmp("darwin", platform) == 0) { - if (strcmp("x86_64", architecture) == 0) { - found = true; - success = writeMachO64Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } else if (strcmp("i386", architecture) == 0 - or strcmp("powerpc", architecture) == 0 - or strcmp("arm", architecture) == 0) - { - found = true; - success = writeMachO32Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } - } else if (strcmp("windows", platform) == 0 - and ((strcmp("x86_64", architecture) == 0 - or strcmp("i386", architecture) == 0))) - { - found = true; - success = writePEObject - (data, size, out, startName, endName, architecture, alignment, writable, - executable); - } - - if (not found) { - fprintf(stderr, "unsupported platform: %s/%s\n", platform, architecture); + if(!platform) { + fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture); return false; } - return success; + SymbolInfo symbols[] = { + SymbolInfo(0, startName), + SymbolInfo(size, endName) + }; + + unsigned accessFlags = (writable ? Platform::Writable : 0) | (executable ? Platform::Executable : 0); + + return platform->writeObject(out, Slice(symbols, 2), Slice(data, size), accessFlags, alignment); + } void @@ -191,13 +139,11 @@ main(int argc, const char** argv) bool success = false; if (data) { - FILE* out = fopen(argv[2], "wb"); - if (out) { + FileOutputStream out(argv[2]); + if (out.isValid()) { success = writeObject - (data, size, out, argv[3], argv[4], argv[5], argv[6], alignment, + (data, size, &out, argv[3], argv[4], argv[5], argv[6], alignment, writable, executable); - - fclose(out); } else { fprintf(stderr, "unable to open %s\n", argv[2]); } diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 45cc9556a9..69ca719bc1 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -8,16 +8,21 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "string.h" +#include +#include +#include +#include + +#include "tools.h" + +namespace { #define IMAGE_SIZEOF_SHORT_NAME 8 #define IMAGE_FILE_RELOCS_STRIPPED 1 #define IMAGE_FILE_LINE_NUMS_STRIPPED 4 #define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_I386 0x014c #define IMAGE_FILE_32BIT_MACHINE 256 #define IMAGE_SCN_ALIGN_1BYTES 0x100000 @@ -29,8 +34,6 @@ #define IMAGE_SCN_MEM_WRITE 0x80000000 #define IMAGE_SCN_CNT_CODE 32 -namespace { - struct IMAGE_FILE_HEADER { uint16_t Machine; uint16_t NumberOfSections; @@ -77,155 +80,199 @@ pad(unsigned n) return (n + (4 - 1)) & ~(4 - 1); } -void -writeObject(const uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* sectionName, int machine, int machineMask, - int sectionMask) -{ - const unsigned sectionCount = 1; - const unsigned symbolCount = 2; +using namespace avian::tools; - const unsigned sectionNumber = 1; +template +class WindowsPlatform : public Platform { +public: - const unsigned startNameLength = strlen(startName) + 1; - const unsigned endNameLength = strlen(endName) + 1; - const unsigned startNameOffset = 4; - const unsigned endNameOffset = startNameOffset + startNameLength; + class FileWriter { + public: + unsigned sectionCount; + unsigned symbolCount; + unsigned dataStart; + unsigned dataOffset; - IMAGE_FILE_HEADER fileHeader = { - machine, // Machine - sectionCount, // NumberOfSections - 0, // TimeDateStamp - sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER) - + pad(size), // PointerToSymbolTable - symbolCount, // NumberOfSymbols - 0, // SizeOfOptionalHeader - IMAGE_FILE_RELOCS_STRIPPED - | IMAGE_FILE_LINE_NUMS_STRIPPED - | machineMask // Characteristics + IMAGE_FILE_HEADER header; + + StringTable strings; + Buffer symbols; + + FileWriter(unsigned machine, unsigned machineMask, unsigned symbolCount): + sectionCount(0), + symbolCount(symbolCount), + dataStart(sizeof(IMAGE_FILE_HEADER)), + dataOffset(0) + { + header.Machine = machine; + // header.NumberOfSections = sectionCount; + header.TimeDateStamp = 0; + // header.PointerToSymbolTable = sizeof(IMAGE_FILE_HEADER) + // + sizeof(IMAGE_SECTION_HEADER) + // + pad(size); + // header.NumberOfSymbols = symbolCount; + header.SizeOfOptionalHeader = 0; + header.Characteristics = IMAGE_FILE_RELOCS_STRIPPED + | IMAGE_FILE_LINE_NUMS_STRIPPED + | machineMask; + } + + void writeHeader(OutputStream* out) { + header.NumberOfSections = sectionCount; + header.PointerToSymbolTable = dataStart + dataOffset; + dataOffset = pad(dataOffset + symbolCount * sizeof(IMAGE_SYMBOL)); + header.NumberOfSymbols = symbolCount; + out->writeChunk(&header, sizeof(IMAGE_FILE_HEADER)); + } + + void addSymbol(String name, unsigned addr, unsigned sectionNumber, unsigned type, unsigned storageClass) { + unsigned nameOffset = strings.add(name); + IMAGE_SYMBOL symbol = { + { { 0, 0 } }, // Name + addr, // Value + static_cast(sectionNumber), // SectionNumber + static_cast(type), // Type + static_cast(storageClass), // StorageClass + 0, // NumberOfAuxSymbols + }; + symbol.N.Name.Long = nameOffset+4; + symbols.write(&symbol, sizeof(IMAGE_SYMBOL)); + } + + void writeData(OutputStream* out) { + out->writeChunk(symbols.data, symbols.length); + uint32_t size = strings.length + 4; + out->writeChunk(&size, 4); + out->writeChunk(strings.data, strings.length); + } }; - IMAGE_SECTION_HEADER sectionHeader = { - "", // Name - 0, // PhysicalAddress - 0, // VirtualAddress - pad(size), // SizeOfRawData - sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER), // PointerToRawData - 0, // PointerToRelocations - 0, // PointerToLinenumbers - 0, // NumberOfRelocations - 0, // NumberOfLinenumbers - sectionMask // Characteristics + class SectionWriter { + public: + FileWriter& file; + IMAGE_SECTION_HEADER header; + size_t dataSize; + size_t finalSize; + const uint8_t* data; + unsigned dataOffset; + + SectionWriter( + FileWriter& file, + const char* name, + unsigned sectionMask, + const uint8_t* data, + size_t dataSize): + + file(file), + dataSize(dataSize), + finalSize(pad(dataSize)), + data(data) + { + file.sectionCount++; + file.dataStart += sizeof(IMAGE_SECTION_HEADER); + strcpy(reinterpret_cast(header.Name), name); + header.Misc.VirtualSize = 0; + header.SizeOfRawData = finalSize; + // header.PointerToRawData = file.dataOffset; + dataOffset = file.dataOffset; + file.dataOffset += finalSize; + header.PointerToRelocations = 0; + header.PointerToLinenumbers = 0; + header.NumberOfRelocations = 0; + header.NumberOfLinenumbers = 0; + header.Characteristics = sectionMask; + } + + void writeHeader(OutputStream* out) { + header.PointerToRawData = dataOffset + file.dataStart; + out->writeChunk(&header, sizeof(IMAGE_SECTION_HEADER)); + } + + void writeData(OutputStream* out) { + out->writeChunk(data, dataSize); + out->writeRepeat(0, finalSize - dataSize); + } + + }; - strncpy(reinterpret_cast(sectionHeader.Name), sectionName, - sizeof(sectionHeader.Name)); + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) { - IMAGE_SYMBOL startSymbol = { - { 0 }, // Name - 0, // Value - sectionNumber, // SectionNumber - 0, // Type - 2, // StorageClass - 0, // NumberOfAuxSymbols - }; - startSymbol.N.Name.Long = startNameOffset; + int machine; + int machineMask; - IMAGE_SYMBOL endSymbol = { - { 0 }, // Name - size, // Value - sectionNumber, // SectionNumber - 0, // Type - 2, // StorageClass - 0, // NumberOfAuxSymbols - }; - endSymbol.N.Name.Long = endNameOffset; + if (BytesPerWord == 8) { + machine = IMAGE_FILE_MACHINE_AMD64; + machineMask = 0; + } else { // if (BytesPerWord == 8) + machine = IMAGE_FILE_MACHINE_I386; + machineMask = IMAGE_FILE_32BIT_MACHINE; + } - fwrite(&fileHeader, 1, sizeof(fileHeader), out); - fwrite(§ionHeader, 1, sizeof(sectionHeader), out); + int sectionMask; + switch (alignment) { + case 0: + case 1: + sectionMask = IMAGE_SCN_ALIGN_1BYTES; + break; + case 2: + sectionMask = IMAGE_SCN_ALIGN_2BYTES; + break; + case 4: + sectionMask = IMAGE_SCN_ALIGN_4BYTES; + break; + case 8: + sectionMask = IMAGE_SCN_ALIGN_8BYTES; + break; + default: + fprintf(stderr, "unsupported alignment: %d\n", alignment); + return false; + } - fwrite(data, 1, size, out); - for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); + sectionMask |= IMAGE_SCN_MEM_READ; - fwrite(&startSymbol, 1, sizeof(startSymbol), out); - fwrite(&endSymbol, 1, sizeof(endSymbol), out); + const char* sectionName; + if (accessFlags & Platform::Writable) { + if (accessFlags & Platform::Executable) { + sectionName = ".rwx"; + sectionMask |= IMAGE_SCN_MEM_WRITE + | IMAGE_SCN_MEM_EXECUTE + | IMAGE_SCN_CNT_CODE; + } else { + sectionName = ".data"; + sectionMask |= IMAGE_SCN_MEM_WRITE; + } + } else { + sectionName = ".text"; + sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; + } - uint32_t symbolTableSize = endNameOffset + endNameLength; - fwrite(&symbolTableSize, 1, 4, out); + FileWriter file(machine, machineMask, symbols.count); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); -} + SectionWriter section(file, sectionName, sectionMask, data.items, data.count); + + file.writeHeader(out); + + for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + file.addSymbol(sym->name, sym->addr, 1, 0, 2); + } + + section.writeHeader(out); + + section.writeData(out); + + file.writeData(out); + + return true; + + } + + WindowsPlatform(): + Platform(PlatformInfo(PlatformInfo::Windows, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {} +}; + +WindowsPlatform<4> windows32Platform; +WindowsPlatform<8> windows64Platform; } // namespace - -namespace binaryToObject { - -bool -writePEObject -(uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, unsigned alignment, - bool writable, bool executable) -{ - int machine; - int machineMask; - if (strcmp(architecture, "x86_64") == 0) { - machine = IMAGE_FILE_MACHINE_AMD64; - machineMask = 0; - } else if (strcmp(architecture, "i386") == 0) { - machine = IMAGE_FILE_MACHINE_I386; - machineMask = IMAGE_FILE_32BIT_MACHINE; - } else { - fprintf(stderr, "unsupported architecture: %s\n", architecture); - return false; - } - - int sectionMask; - switch (alignment) { - case 0: - case 1: - sectionMask = IMAGE_SCN_ALIGN_1BYTES; - break; - case 2: - sectionMask = IMAGE_SCN_ALIGN_2BYTES; - break; - case 4: - sectionMask = IMAGE_SCN_ALIGN_4BYTES; - break; - case 8: - sectionMask = IMAGE_SCN_ALIGN_8BYTES; - break; - default: - fprintf(stderr, "unsupported alignment: %d\n", alignment); - return false; - } - - sectionMask |= IMAGE_SCN_MEM_READ; - - const char* sectionName; - if (writable) { - if (executable) { - sectionName = ".rwx"; - sectionMask |= IMAGE_SCN_MEM_WRITE - | IMAGE_SCN_MEM_EXECUTE - | IMAGE_SCN_CNT_CODE; - } else { - sectionName = ".data"; - sectionMask |= IMAGE_SCN_MEM_WRITE; - } - } else { - sectionName = ".text"; - sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; - } - - writeObject(data, size, out, startName, endName, sectionName, machine, - machineMask, sectionMask); - - return true; -} - -} // namespace binaryToObject diff --git a/src/binaryToObject/tools.cpp b/src/binaryToObject/tools.cpp new file mode 100644 index 0000000000..3181474b94 --- /dev/null +++ b/src/binaryToObject/tools.cpp @@ -0,0 +1,125 @@ +/* Copyright (c) 2009-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. */ + +#include +#include +#include +#include + +#include "tools.h" + +namespace avian { + +namespace tools { + +String::String(const char* text): + text(text), + length(strlen(text)) {} + +Buffer::Buffer(): + capacity(100), + length(0), + data((uint8_t*)malloc(capacity)) {} + +Buffer::~Buffer() { + free(data); +} + +void Buffer::ensure(size_t more) { + if(length + more > capacity) { + capacity = capacity * 2 + more; + data = (uint8_t*)realloc(data, capacity); + } +} + +void Buffer::write(const void* d, size_t size) { + ensure(size); + memcpy(data + length, d, size); + length += size; +} + +unsigned StringTable::add(String str) { + unsigned offset = Buffer::length; + Buffer::write(str.text, str.length + 1); + return offset; +} + +void OutputStream::write(uint8_t byte) { + writeChunk(&byte, 1); +} + +void OutputStream::writeRepeat(uint8_t byte, size_t size) { + for(size_t i = 0; i < size; i++) { + write(byte); + } +} + +FileOutputStream::FileOutputStream(const char* name): + file(fopen(name, "wb")) {} + +FileOutputStream::~FileOutputStream() { + if(file) { + fclose(file); + } +} + +bool FileOutputStream::isValid() { + return file; +} + +void FileOutputStream::writeChunk(const void* data, size_t size) { + fwrite(data, size, 1, file); +} + +void FileOutputStream::write(uint8_t byte) { + fputc(byte, file); +} + + +Platform* Platform::first = 0; + +PlatformInfo::OperatingSystem PlatformInfo::osFromString(const char* os) { + if(strcmp(os, "linux") == 0) { + return Linux; + } else if(strcmp(os, "windows") == 0) { + return Windows; + } else if(strcmp(os, "darwin") == 0) { + return Darwin; + } else { + return UnknownOS; + } +} + +PlatformInfo::Architecture PlatformInfo::archFromString(const char* arch) { + if(strcmp(arch, "i386") == 0) { + return x86; + } else if(strcmp(arch, "x86_64") == 0) { + return x86_64; + } else if(strcmp(arch, "powerpc") == 0) { + return PowerPC; + } else if(strcmp(arch, "arm") == 0) { + return Arm; + } else { + return UnknownArch; + } +} + +Platform* Platform::getPlatform(PlatformInfo info) { + for(Platform* p = first; p; p = p->next) { + if(p->info == info) { + return p; + } + } + return 0; +} + +} // namespace tools + +} // namespace avian \ No newline at end of file diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h new file mode 100644 index 0000000000..c95d22ae89 --- /dev/null +++ b/src/binaryToObject/tools.h @@ -0,0 +1,196 @@ +/* Copyright (c) 2009-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. */ + +#ifndef AVIAN_TOOLS_H_ +#define AVIAN_TOOLS_H_ + +#include +#include "environment.h" + +namespace avian { + +namespace tools { + +class OutputStream { +public: + virtual void writeChunk(const void* data, size_t size) = 0; + virtual void write(uint8_t byte); + virtual void writeRepeat(uint8_t byte, size_t size); +}; + +class FileOutputStream : public OutputStream { +private: + FILE* file; +public: + FileOutputStream(const char* name); + ~FileOutputStream(); + + bool isValid(); + + virtual void writeChunk(const void* data, size_t size); + virtual void write(uint8_t byte); +}; + +class String { +public: + const char* text; + size_t length; + + String(const char* text); + + inline String(const char* text, size_t length): + text(text), + length(length) {} +}; + +class SymbolInfo { +public: + unsigned addr; + String name; + + inline SymbolInfo(uint64_t addr, const String& name): + addr(addr), + name(name) {} + + inline SymbolInfo(): + name("") {} +}; + +class Buffer { +public: + size_t capacity; + size_t length; + uint8_t* data; + + Buffer(); + ~Buffer(); + + void ensure(size_t more); + void write(const void* d, size_t size); +}; + +class StringTable : public Buffer { +public: + unsigned add(String str); +}; + +template +class Slice { +public: + T* items; + size_t count; + + inline Slice(T* items, size_t count): + items(items), + count(count) {} + + inline Slice(const Slice& copy): + items(copy.items), + count(copy.count) {} + + inline T* begin() { + return items; + } + + inline T* end() { + return items + count; + } +}; + +template +class DynamicArray : public Slice { +public: + size_t capacity; + + DynamicArray(): + Slice((T*)malloc(10 * sizeof(T)), 0), + capacity(10) {} + ~DynamicArray() { + free(Slice::items); + } + + void ensure(size_t more) { + if(Slice::count + more > capacity) { + capacity = capacity * 2 + more; + Slice::items = (T*)realloc(Slice::items, capacity * sizeof(T)); + } +} + + void add(const T& item) { + ensure(1); + Slice::items[Slice::count++] = item; + } +}; + +class PlatformInfo { +public: + enum OperatingSystem { + Linux = AVIAN_PLATFORM_LINUX, + Windows = AVIAN_PLATFORM_WINDOWS, + Darwin = AVIAN_PLATFORM_DARWIN, + UnknownOS = AVIAN_PLATFORM_UNKNOWN + }; + + enum Architecture { + x86 = AVIAN_ARCH_X86, + x86_64 = AVIAN_ARCH_X86_64, + PowerPC = AVIAN_ARCH_POWERPC, + Arm = AVIAN_ARCH_ARM, + UnknownArch = AVIAN_ARCH_UNKNOWN + }; + + const OperatingSystem os; + const Architecture arch; + + static OperatingSystem osFromString(const char* os); + static Architecture archFromString(const char* arch); + + inline PlatformInfo(OperatingSystem os, Architecture arch): + os(os), + arch(arch) {} + + inline bool operator == (const PlatformInfo& other) { + return os == other.os && arch == other.arch; + } + + inline bool isLittleEndian() { + return arch != PowerPC; + } +}; + +class Platform { +private: + Platform* next; + static Platform* first; +public: + PlatformInfo info; + + inline Platform(PlatformInfo info): + next(first), + info(info) + { + first = this; + } + + enum AccessFlags { + Writable = 1 << 0, + Executable = 1 << 1 + }; + + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) = 0; + + static Platform* getPlatform(PlatformInfo info); +}; + +} // namespace tools + +} // namespace avian + +#endif \ No newline at end of file diff --git a/src/boot-javahome.cpp b/src/boot-javahome.cpp index 4ef2efd896..bb965cdc3a 100644 --- a/src/boot-javahome.cpp +++ b/src/boot-javahome.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/boot.cpp b/src/boot.cpp index c78667f5af..4f3d8edbb0 100644 --- a/src/boot.cpp +++ b/src/boot.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/bootimage-fields.cpp b/src/bootimage-fields.cpp index 7638830585..a090268de2 100644 --- a/src/bootimage-fields.cpp +++ b/src/bootimage-fields.cpp @@ -5,6 +5,8 @@ FIELD(magic) +FIELD(initialized) + FIELD(heapSize) FIELD(codeSize) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 3d75f4401c..8d403d0745 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -16,16 +16,19 @@ #include "stream.h" #include "assembler.h" #include "target.h" +#include "binaryToObject/tools.h" +#include "lzma.h" // since we aren't linking against libstdc++, we must implement this // ourselves: extern "C" void __cxa_pure_virtual(void) { abort(); } using namespace vm; +using namespace avian::tools; namespace { -const unsigned HeapCapacity = 256 * 1024 * 1024; +const unsigned HeapCapacity = 512 * 1024 * 1024; const unsigned TargetFixieSizeInBytes = 8 + (TargetBytesPerWord * 2); const unsigned TargetFixieSizeInWords = ceiling @@ -60,14 +63,6 @@ enum Type { class Field { public: - Field() { } - - Field(Type type, unsigned buildOffset, unsigned buildSize, - unsigned targetOffset, unsigned targetSize): - type(type), buildOffset(buildOffset), buildSize(buildSize), - targetOffset(targetOffset), targetSize(targetSize) - { } - Type type; unsigned buildOffset; unsigned buildSize; @@ -75,6 +70,17 @@ class Field { unsigned targetSize; }; +void +init(Field* f, Type type, unsigned buildOffset, unsigned buildSize, + unsigned targetOffset, unsigned targetSize) +{ + f->type = type; + f->buildOffset = buildOffset; + f->buildSize = buildSize; + f->targetOffset = targetOffset; + f->targetSize = targetSize; +} + class TypeMap { public: enum Kind { @@ -395,9 +401,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, map->targetFixedOffsets()[i * BytesPerWord] = i * TargetBytesPerWord; - new (map->fixedFields() + i) Field - (types[i], i * BytesPerWord, BytesPerWord, - i * TargetBytesPerWord, TargetBytesPerWord); + init(new (map->fixedFields() + i) Field, types[i], + i * BytesPerWord, BytesPerWord, i * TargetBytesPerWord, + TargetBytesPerWord); } hashMapInsert @@ -444,8 +450,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, ++ memberIndex; } } else { - new (memberFields) Field - (Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); + init(new (memberFields) Field, Type_object, 0, BytesPerWord, 0, + TargetBytesPerWord); memberIndex = 1; buildMemberOffset = BytesPerWord; @@ -454,12 +460,11 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, Field staticFields[count + 2]; - new (staticFields) Field - (Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); + init(new (staticFields) Field, Type_object, 0, BytesPerWord, 0, + TargetBytesPerWord); - new (staticFields + 1) Field - (Type_intptr_t, BytesPerWord, BytesPerWord, TargetBytesPerWord, - TargetBytesPerWord); + init(new (staticFields + 1) Field, Type_intptr_t, BytesPerWord, + BytesPerWord, TargetBytesPerWord, TargetBytesPerWord); unsigned staticIndex = 2; unsigned buildStaticOffset = BytesPerWord * 2; @@ -502,17 +507,15 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, } if (fieldFlags(t, field) & ACC_STATIC) { - unsigned excess = (targetStaticOffset % targetSize) - % TargetBytesPerWord; - if (excess) { - targetStaticOffset += TargetBytesPerWord - excess; + while (targetStaticOffset % targetSize) { + ++ targetStaticOffset; } buildStaticOffset = fieldOffset(t, field); - new (staticFields + staticIndex) Field - (type, buildStaticOffset, buildSize, targetStaticOffset, - targetSize); + init(new (staticFields + staticIndex) Field, type, + buildStaticOffset, buildSize, targetStaticOffset, + targetSize); targetStaticOffset += targetSize; @@ -524,9 +527,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildMemberOffset = fieldOffset(t, field); - new (memberFields + memberIndex) Field - (type, buildMemberOffset, buildSize, targetMemberOffset, - targetSize); + init(new (memberFields + memberIndex) Field, type, + buildMemberOffset, buildSize, targetMemberOffset, + targetSize); targetMemberOffset += targetSize; @@ -684,10 +687,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, } for (; methods; methods = pairSecond(t, methods)) { - intptr_t address = codeCompiled(t, methodCode(t, pairFirst(t, methods))); - reinterpret_cast(address)[-1] - = targetVW(reinterpret_cast(address)[-1]); - codeCompiled(t, methodCode(t, pairFirst(t, methods))) -= reinterpret_cast(code); } @@ -697,12 +696,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, return constants; } -unsigned -objectSize(Thread* t, object o) -{ - return baseSize(t, o, objectClass(t, o)); -} - void visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants) { @@ -1271,12 +1264,6 @@ updateConstants(Thread* t, object constants, HeapMap* heapTable) } } -unsigned -offset(object a, uintptr_t* b) -{ - return reinterpret_cast(b) - reinterpret_cast(a); -} - BootImage::Thunk targetThunk(BootImage::Thunk t) { @@ -1285,12 +1272,49 @@ targetThunk(BootImage::Thunk t) } void -writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, +writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutput, BootImage* image, uint8_t* code, const char* className, - const char* methodName, const char* methodSpec) + const char* methodName, const char* methodSpec, + const char* bootimageStart, const char* bootimageEnd, + const char* codeimageStart, const char* codeimageEnd, + bool useLZMA) { + setRoot(t, Machine::OutOfMemoryError, + make(t, type(t, Machine::OutOfMemoryErrorType))); + Zone zone(t->m->system, t->m->heap, 64 * 1024); + class MyCompilationHandler : public Processor::CompilationHandler { + public: + + String heapDup(const char* name) { + String ret(name); + char* n = (char*)heap->allocate(ret.length + 1); + memcpy(n, ret.text, ret.length + 1); + ret.text = n; + return ret; + } + + virtual void compiled(const void* code, unsigned size UNUSED, unsigned frameSize UNUSED, const char* name) { + uint64_t offset = reinterpret_cast(code) - codeOffset; + symbols.add(SymbolInfo(offset, heapDup(name))); + // printf("%ld %ld %s.%s%s\n", offset, offset + size, class_, name, spec); + } + + virtual void dispose() {} + + DynamicArray symbols; + uint64_t codeOffset; + Heap* heap; + + MyCompilationHandler(uint64_t codeOffset, Heap* heap): + codeOffset(codeOffset), + heap(heap) {} + + } compilationHandler(reinterpret_cast(code), t->m->heap); + + t->m->processor->addCompilationHandler(&compilationHandler); + object classPoolMap; object typeMaps; object constants; @@ -1315,7 +1339,8 @@ writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, Field fields[count]; - new (fields) Field(Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); + init(new (fields) Field, Type_object, 0, BytesPerWord, 0, + TargetBytesPerWord); unsigned buildOffset = BytesPerWord; unsigned targetOffset = TargetBytesPerWord; @@ -1392,8 +1417,8 @@ writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, ++ targetOffset; } - new (fields + j) Field - (type, buildOffset, buildSize, targetOffset, targetSize); + init(new (fields + j) Field, type, buildOffset, buildSize, + targetOffset, targetSize); buildOffset += buildSize; targetOffset += targetSize; @@ -1571,12 +1596,15 @@ writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, heapWalker->dispose(); image->magic = BootImage::Magic; + image->initialized = 0; fprintf(stderr, "class count %d string count %d call count %d\n" "heap size %d code size %d\n", image->bootClassCount, image->stringCount, image->callCount, image->heapSize, image->codeSize); + Buffer bootimageData; + if (true) { { BootImage targetImage; @@ -1593,19 +1621,15 @@ writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, #include "bootimage-fields.cpp" #undef THUNK_FIELD - fwrite(&targetImage, sizeof(BootImage), 1, bootimageOutput); + bootimageData.write(&targetImage, sizeof(BootImage)); } - fwrite(bootClassTable, image->bootClassCount * sizeof(unsigned), 1, - bootimageOutput); - fwrite(appClassTable, image->appClassCount * sizeof(unsigned), 1, - bootimageOutput); - fwrite(stringTable, image->stringCount * sizeof(unsigned), 1, - bootimageOutput); - fwrite(callTable, image->callCount * sizeof(unsigned) * 2, 1, - bootimageOutput); + bootimageData.write(bootClassTable, image->bootClassCount * sizeof(unsigned)); + bootimageData.write(appClassTable, image->appClassCount * sizeof(unsigned)); + bootimageData.write(stringTable, image->stringCount * sizeof(unsigned)); + bootimageData.write(callTable, image->callCount * sizeof(unsigned) * 2); - unsigned offset = sizeof(BootImage) + unsigned offset = sizeof(BootImage) + (image->bootClassCount * sizeof(unsigned)) + (image->appClassCount * sizeof(unsigned)) + (image->stringCount * sizeof(unsigned)) @@ -1613,52 +1637,347 @@ writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, while (offset % TargetBytesPerWord) { uint8_t c = 0; - fwrite(&c, 1, 1, bootimageOutput); + bootimageData.write(&c, 1); ++ offset; } - fwrite(heapMap, pad(heapMapSize(image->heapSize), TargetBytesPerWord), 1, - bootimageOutput); + bootimageData.write(heapMap, pad(heapMapSize(image->heapSize), TargetBytesPerWord)); - fwrite(heap, pad(image->heapSize, TargetBytesPerWord), 1, bootimageOutput); + bootimageData.write(heap, pad(image->heapSize, TargetBytesPerWord)); - fwrite(code, pad(image->codeSize, TargetBytesPerWord), 1, codeOutput); + // fwrite(code, pad(image->codeSize, TargetBytesPerWord), 1, codeOutput); + + Platform* platform = Platform::getPlatform(PlatformInfo((PlatformInfo::OperatingSystem)AVIAN_TARGET_PLATFORM, (PlatformInfo::Architecture)AVIAN_TARGET_ARCH)); + + // if(!platform) { + // fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture); + // return false; + // } + + SymbolInfo bootimageSymbols[] = { + SymbolInfo(0, bootimageStart), + SymbolInfo(bootimageData.length, bootimageEnd) + }; + + uint8_t* bootimage; + unsigned bootimageLength; + if (useLZMA) { +#ifdef AVIAN_USE_LZMA + bootimage = encodeLZMA(t->m->system, t->m->heap, bootimageData.data, + bootimageData.length, &bootimageLength); + + fprintf(stderr, "compressed heap size %d\n", bootimageLength); +#else + abort(t); +#endif + } else { + bootimage = bootimageData.data; + bootimageLength = bootimageData.length; + } + + platform->writeObject(bootimageOutput, Slice(bootimageSymbols, 2), Slice(bootimage, bootimageLength), Platform::Writable, TargetBytesPerWord); + + if (useLZMA) { + t->m->heap->free(bootimage, bootimageLength); + } + + compilationHandler.symbols.add(SymbolInfo(0, codeimageStart)); + compilationHandler.symbols.add(SymbolInfo(image->codeSize, codeimageEnd)); + + platform->writeObject(codeOutput, Slice(compilationHandler.symbols), Slice(code, image->codeSize), Platform::Executable, TargetBytesPerWord); + + for(SymbolInfo* sym = compilationHandler.symbols.begin(); sym != compilationHandler.symbols.end() - 2; sym++) { + t->m->heap->free(const_cast((const void*)sym->name.text), sym->name.length + 1); + } } } uint64_t writeBootImage(Thread* t, uintptr_t* arguments) { - FILE* bootimageOutput = reinterpret_cast(arguments[0]); - FILE* codeOutput = reinterpret_cast(arguments[1]); + OutputStream* bootimageOutput = reinterpret_cast(arguments[0]); + OutputStream* codeOutput = reinterpret_cast(arguments[1]); BootImage* image = reinterpret_cast(arguments[2]); uint8_t* code = reinterpret_cast(arguments[3]); const char* className = reinterpret_cast(arguments[4]); const char* methodName = reinterpret_cast(arguments[5]); const char* methodSpec = reinterpret_cast(arguments[6]); + const char* bootimageStart = reinterpret_cast(arguments[7]); + const char* bootimageEnd = reinterpret_cast(arguments[8]); + const char* codeimageStart = reinterpret_cast(arguments[9]); + const char* codeimageEnd = reinterpret_cast(arguments[10]); + bool useLZMA = arguments[11]; + writeBootImage2 (t, bootimageOutput, codeOutput, image, code, className, methodName, - methodSpec); + methodSpec, bootimageStart, bootimageEnd, codeimageStart, codeimageEnd, + useLZMA); return 1; } +class Arg; + +class ArgParser { +public: + Arg* first; + Arg** last; + + ArgParser(): + first(0), + last(&first) {} + + bool parse(int ac, const char** av); + void printUsage(const char* exe); +}; + +class Arg { +public: + Arg* next; + bool required; + const char* name; + const char* desc; + + const char* value; + + Arg(ArgParser& parser, bool required, const char* name, const char* desc): + next(0), + required(required), + name(name), + desc(desc), + value(0) + { + *parser.last = this; + parser.last = &next; + } +}; + +bool ArgParser::parse(int ac, const char** av) { + Arg* state = 0; + + for(int i = 1; i < ac; i++) { + if(state) { + if(state->value) { + fprintf(stderr, "duplicate parameter %s: '%s' and '%s'\n", state->name, state->value, av[i]); + return false; + } + state->value = av[i]; + state = 0; + } else { + if(av[i][0] != '-') { + fprintf(stderr, "expected -parameter\n"); + return false; + } + bool found = false; + for(Arg* arg = first; arg; arg = arg->next) { + if(strcmp(arg->name, &av[i][1]) == 0) { + found = true; + if (arg->desc == 0) { + arg->value = "true"; + } else { + state = arg; + } + } + } + if (not found) { + fprintf(stderr, "unrecognized parameter %s\n", av[i]); + return false; + } + } + } + + if(state) { + fprintf(stderr, "expected argument after -%s\n", state->name); + return false; + } + + for(Arg* arg = first; arg; arg = arg->next) { + if(arg->required && !arg->value) { + fprintf(stderr, "expected value for %s\n", arg->name); + return false; + } + } + + return true; +} + +void ArgParser::printUsage(const char* exe) { + fprintf(stderr, "usage:\n%s \\\n", exe); + for(Arg* arg = first; arg; arg = arg->next) { + const char* lineEnd = arg->next ? " \\" : ""; + if(arg->required) { + fprintf(stderr, " -%s\t%s%s\n", arg->name, arg->desc, lineEnd); + } else if (arg->desc) { + fprintf(stderr, " [-%s\t%s]%s\n", arg->name, arg->desc, lineEnd); + } else { + fprintf(stderr, " [-%s]%s\n", arg->name, lineEnd); + } + } +} + +class Arguments { +public: + + const char* classpath; + + const char* bootimage; + const char* codeimage; + + char* entryClass; + char* entryMethod; + char* entrySpec; + + char* bootimageStart; + char* bootimageEnd; + + char* codeimageStart; + char* codeimageEnd; + + bool useLZMA; + + bool maybeSplit(const char* src, char*& destA, char*& destB) { + if(src) { + const char* split = strchr(src, ':'); + if(!split) { + return false; + } + + destA = strndup(src, split - src); + destB = strdup(split + 1); + } + return true; + } + + Arguments(int ac, const char** av): + entryClass(0), + entryMethod(0), + entrySpec(0), + bootimageStart(0), + bootimageEnd(0), + codeimageStart(0), + codeimageEnd(0) + { + ArgParser parser; + Arg classpath(parser, true, "cp", ""); + Arg bootimage(parser, true, "bootimage", ""); + Arg codeimage(parser, true, "codeimage", ""); + Arg entry(parser, false, "entry", "[.[]]"); + Arg bootimageSymbols(parser, false, "bootimage-symbols", ":"); + Arg codeimageSymbols(parser, false, "codeimage-symbols", ":"); + Arg useLZMA(parser, false, "use-lzma", 0); + + if(!parser.parse(ac, av)) { + parser.printUsage(av[0]); + exit(1); + } + + this->classpath = classpath.value; + this->bootimage = bootimage.value; + this->codeimage = codeimage.value; + this->useLZMA = useLZMA.value != 0; + + if(entry.value) { + if(const char* entryClassEnd = strchr(entry.value, '.')) { + entryClass = strndup(entry.value, entryClassEnd - entry.value); + if(const char* entryMethodEnd = strchr(entryClassEnd, '(')) { + entryMethod = strndup(entryClassEnd + 1, entryMethodEnd - entryClassEnd - 1); + entrySpec = strdup(entryMethodEnd); + } else { + entryMethod = strdup(entryClassEnd + 1); + } + } else { + entryClass = strdup(entry.value); + } + } + + if(!maybeSplit(bootimageSymbols.value, bootimageStart, bootimageEnd) || + !maybeSplit(codeimageSymbols.value, codeimageStart, codeimageEnd)) + { + fprintf(stderr, "wrong format for symbols\n"); + parser.printUsage(av[0]); + exit(1); + } + + if(!bootimageStart) { + bootimageStart = strdup("_binary_bootimage_bin_start"); + } + + if(!bootimageEnd) { + bootimageEnd = strdup("_binary_bootimage_bin_end"); + } + + if(!codeimageStart) { + codeimageStart = strdup("_binary_codeimage_bin_start"); + } + + if(!codeimageEnd) { + codeimageEnd = strdup("_binary_codeimage_bin_end"); + } + + } + + ~Arguments() { + if(entryClass) { + free(entryClass); + } + if(entryMethod) { + free(entryMethod); + } + if(entrySpec) { + free(entrySpec); + } + if(bootimageStart) { + free(bootimageStart); + } + if(bootimageEnd) { + free(bootimageEnd); + } + if(codeimageStart) { + free(codeimageStart); + } + if(codeimageEnd) { + free(codeimageEnd); + } + } + + void dump() { + printf( + "classpath = %s\n" + "bootimage = %s\n" + "codeimage = %s\n" + "entryClass = %s\n" + "entryMethod = %s\n" + "entrySpec = %s\n" + "bootimageStart = %s\n" + "bootimageEnd = %s\n" + "codeimageStart = %s\n" + "codeimageEnd = %s\n", + classpath, + bootimage, + codeimage, + entryClass, + entryMethod, + entrySpec, + bootimageStart, + bootimageEnd, + codeimageStart, + codeimageEnd); + } +}; + } // namespace int main(int ac, const char** av) { - if (ac < 4 or ac > 7) { - fprintf(stderr, "usage: %s " - " [ [ []]]\n", av[0]); - return -1; - } + Arguments args(ac, av); + // args.dump(); System* s = makeSystem(0); Heap* h = makeHeap(s, HeapCapacity * 2); Classpath* c = makeClasspath(s, h, AVIAN_JAVA_HOME, AVIAN_EMBED_PREFIX); - Finder* f = makeFinder(s, h, av[1], 0); + Finder* f = makeFinder(s, h, args.classpath, 0); Processor* p = makeProcessor(s, h, false); // todo: currently, the compiler cannot compile code with jumps or @@ -1666,44 +1985,52 @@ 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); enter(t, Thread::IdleState); - FILE* bootimageOutput = vm::fopen(av[2], "wb"); - if (bootimageOutput == 0) { - fprintf(stderr, "unable to open %s\n", av[2]); + FileOutputStream bootimageOutput(args.bootimage); + if (!bootimageOutput.isValid()) { + fprintf(stderr, "unable to open %s\n", args.bootimage); return -1; } - FILE* codeOutput = vm::fopen(av[3], "wb"); - if (codeOutput == 0) { - fprintf(stderr, "unable to open %s\n", av[3]); + FileOutputStream codeOutput(args.codeimage); + if (!codeOutput.isValid()) { + fprintf(stderr, "unable to open %s\n", args.codeimage); return -1; } - uintptr_t arguments[] = { reinterpret_cast(bootimageOutput), - reinterpret_cast(codeOutput), - reinterpret_cast(&image), - reinterpret_cast(code), - reinterpret_cast(ac > 4 ? av[4] : 0), - reinterpret_cast(ac > 5 ? av[5] : 0), - reinterpret_cast(ac > 6 ? av[6] : 0) }; + uintptr_t arguments[] = { + reinterpret_cast(&bootimageOutput), + reinterpret_cast(&codeOutput), + reinterpret_cast(&image), + reinterpret_cast(code), + reinterpret_cast(args.entryClass), + reinterpret_cast(args.entryMethod), + reinterpret_cast(args.entrySpec), + reinterpret_cast(args.bootimageStart), + reinterpret_cast(args.bootimageEnd), + reinterpret_cast(args.codeimageStart), + reinterpret_cast(args.codeimageEnd), + static_cast(args.useLZMA) + }; run(t, writeBootImage, arguments); - fclose(codeOutput); - fclose(bootimageOutput); - if (t->exception) { printTrace(t, t->exception); return -1; diff --git a/src/bootimage.h b/src/bootimage.h index a7e178524a..16f11ab379 100644 --- a/src/bootimage.h +++ b/src/bootimage.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/builtin.cpp b/src/builtin.cpp index f7f2c12d29..9c3dca8508 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -332,7 +332,8 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_allocateMemory (Thread* t, object, uintptr_t* arguments) { - void* p = malloc(arguments[1]); + int64_t size; memcpy(&size, arguments + 1, 8); + void* p = malloc(size); if (p) { return reinterpret_cast(p); } else { @@ -344,21 +345,30 @@ extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_freeMemory (Thread*, object, uintptr_t* arguments) { - void* p = reinterpret_cast(arguments[1]); + int64_t p; memcpy(&p, arguments + 1, 8); if (p) { - free(p); + free(reinterpret_cast(p)); } } 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..5e68d2ed14 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -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..d8105b9cd7 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -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 977d466c6d..bbdb4a547e 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -42,7 +42,6 @@ # define S_IWUSR _S_IWRITE # else # define OPEN _open -# define CREAT _creat # endif # define O_RDONLY _O_RDONLY @@ -82,6 +81,8 @@ typedef int socklen_t; #endif // not PLATFORM_WINDOWS +#define JVM_EEXIST -100 + using namespace vm; namespace { @@ -97,12 +98,6 @@ OPEN(string_t path, int mask, int mode) return -1; } } - -inline int -CREAT(string_t path, int mode) -{ - return OPEN(path, _O_CREAT, mode); -} #endif namespace local { @@ -349,6 +344,9 @@ makeClassNameString(Thread* t, object name) void interceptFileOperations(Thread*); +void +clearInterrupted(Thread*); + class MyClasspath : public Classpath { public: static const unsigned BufferSize = 1024; @@ -415,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 @@ -440,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 @@ -504,6 +509,12 @@ class MyClasspath : public Classpath { return thread; } + virtual void + clearInterrupted(Thread* t) + { + local::clearInterrupted(t); + } + virtual void runThread(Thread* t) { @@ -551,31 +562,61 @@ class MyClasspath : public Classpath { expect(t, loadLibrary(t, libraryPath, "java", true, true)); #endif // not AVIAN_OPENJDK_SRC - object constructor = resolveMethod + { object assertionLock = resolveField + (t, type(t, Machine::ClassLoaderType), "assertionLock", + "Ljava/lang/Object;"); + + set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock), + root(t, Machine::BootLoader)); + } + + { 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 scl = resolveField + (t, type(t, Machine::ClassLoaderType), "scl", + "Ljava/lang/ClassLoader;"); - PROTECT(t, scl); + PROTECT(t, scl); - object sclSet = resolveField - (t, type(t, Machine::ClassLoaderType), "sclSet", "Z"); + 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)); + 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; + cast(classStaticTable(t, type(t, Machine::ClassLoaderType)), + fieldOffset(t, sclSet)) = true; + } t->m->processor->invoke (t, root(t, Machine::BootLoader), "java/lang/System", @@ -1318,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 @@ -1340,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) { @@ -1467,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 @@ -1674,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 @@ -1703,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); } } @@ -1770,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); @@ -1836,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", @@ -1857,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;", @@ -2181,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) { @@ -2207,19 +2255,40 @@ pipeAvailable(int fd, int* available) } object -fieldForOffset(Thread* t, object o, unsigned offset) +fieldForOffsetInClass(Thread* t, object c, unsigned offset) { - object table = classFieldTable(t, objectClass(t, o)); - for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { - object field = objectArrayBody(t, table, i); - if ((fieldFlags(t, field) & ACC_STATIC) == 0 - and fieldOffset(t, field) == offset) - { + object super = classSuper(t, c); + if (super) { + object field = fieldForOffsetInClass(t, super, offset); + if (field) { return field; } } - - abort(t); + + object table = classFieldTable(t, c); + if (table) { + for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { + object field = objectArrayBody(t, table, i); + if ((fieldFlags(t, field) & ACC_STATIC) == 0 + and fieldOffset(t, field) == offset) + { + return field; + } + } + } + + return 0; +} + +object +fieldForOffset(Thread* t, object o, unsigned offset) +{ + object field = fieldForOffsetInClass(t, objectClass(t, o), offset); + if (field) { + return field; + } else { + abort(t); + } } } // namespace local @@ -2255,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*) @@ -2504,17 +2591,25 @@ 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__Ljava_lang_Object_2J (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__Ljava_lang_Object_2J +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J + (t, method, arguments); } extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_putBoolean +Avian_sun_misc_Unsafe_putBoolean__Ljava_lang_Object_2JZ (Thread*, object, uintptr_t* arguments) { object o = reinterpret_cast(arguments[1]); @@ -2560,6 +2655,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) @@ -2655,12 +2757,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)))) @@ -2668,11 +2773,55 @@ 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) +{ + acquire(t, reinterpret_cast(arguments[1])); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_monitorExit +(Thread* t, object, uintptr_t* arguments) +{ + release(t, reinterpret_cast(arguments[1])); +} + namespace { namespace local { @@ -2811,10 +2960,10 @@ EXPORT(JVM_ArrayCopy)(Thread* t, jclass, jobject src, jint srcOffset, jobject dst, jint dstOffset, jint length) { uintptr_t arguments[] = { reinterpret_cast(src), - srcOffset, + static_cast(srcOffset), reinterpret_cast(dst), - dstOffset, - length }; + static_cast(dstOffset), + static_cast(length) }; run(t, jvmArrayCopy, arguments); } @@ -2847,22 +2996,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"); @@ -2878,6 +3027,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"); @@ -3044,7 +3198,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; @@ -3084,7 +3238,8 @@ jvmGetStackTraceElement(Thread* t, uintptr_t* arguments) extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_GetStackTraceElement)(Thread* t, jobject throwable, jint index) { - uintptr_t arguments[] = { reinterpret_cast(throwable), index }; + uintptr_t arguments[] = { reinterpret_cast(throwable), + static_cast(index) }; return reinterpret_cast(run(t, jvmGetStackTraceElement, arguments)); } @@ -3214,9 +3369,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; @@ -3254,8 +3408,21 @@ EXPORT(JVM_IsInterrupted)(Thread* t, jobject thread, jboolean clear) return run(t, jvmIsInterrupted, arguments); } +uint64_t +jvmHoldsLock(Thread* t, uintptr_t* arguments) +{ + object m = objectMonitor(t, *reinterpret_cast(arguments[0]), false); + + return m and monitorOwner(t, m) == t; +} + extern "C" JNIEXPORT jboolean JNICALL -EXPORT(JVM_HoldsLock)(Thread*, jclass, jobject) { abort(); } +EXPORT(JVM_HoldsLock)(Thread* t, jclass, jobject o) +{ + uintptr_t arguments[] = { reinterpret_cast(o) }; + + return run(t, jvmHoldsLock, arguments); +} extern "C" JNIEXPORT void JNICALL EXPORT(JVM_DumpAllStacks)(Thread*, jclass) { abort(); } @@ -3480,7 +3647,7 @@ extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_GetArrayElement)(Thread* t, jobject array, jint index) { uintptr_t arguments[] = { reinterpret_cast(array), - index }; + static_cast(index) }; return reinterpret_cast(run(t, jvmGetArrayElement, arguments)); } @@ -3574,7 +3741,7 @@ extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_NewArray)(Thread* t, jclass elementClass, jint length) { uintptr_t arguments[] = { reinterpret_cast(elementClass), - length }; + static_cast(length) }; return reinterpret_cast(run(t, jvmNewArray, arguments)); } @@ -3725,10 +3892,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 @@ -3781,7 +3947,7 @@ EXPORT(JVM_DefineClass)(Thread* t, const char*, jobject loader, { uintptr_t arguments[] = { reinterpret_cast(loader), reinterpret_cast(data), - length }; + static_cast(length) }; return reinterpret_cast(run(t, jvmDefineClass, arguments)); } @@ -4156,9 +4322,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)); @@ -4245,8 +4411,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)); @@ -4336,8 +4502,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)); @@ -4545,7 +4711,8 @@ jvmConstantPoolGetUTF8At(Thread* t, uintptr_t* arguments) extern "C" JNIEXPORT jstring JNICALL EXPORT(JVM_ConstantPoolGetUTF8At)(Thread* t, jobject, jobject pool, jint index) { - uintptr_t arguments[] = { reinterpret_cast(pool), index }; + uintptr_t arguments[] = { reinterpret_cast(pool), + static_cast(index) }; return reinterpret_cast (run(t, jvmConstantPoolGetUTF8At, arguments)); @@ -4771,7 +4938,12 @@ EXPORT(JVM_NativePath)(char* path) extern "C" JNIEXPORT jint JNICALL EXPORT(JVM_Open)(const char* path, jint flags, jint mode) { - return OPEN(path, flags, mode); + int r = OPEN(path, flags, mode); + if (r == -1) { + return errno == EEXIST ? JVM_EEXIST : -1; + } else { + return r; + } } extern "C" JNIEXPORT jint JNICALL @@ -5104,9 +5276,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: @@ -5189,13 +5363,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 @@ -5215,7 +5395,17 @@ jio_vfprintf(FILE* stream, const char* format, va_list a) #ifdef PLATFORM_WINDOWS extern "C" JNIEXPORT void* JNICALL EXPORT(JVM_GetThreadInterruptEvent)() -{ abort(); } +{ + // hack: We don't want to expose thread interruption implementation + // details, so we give the class library a fake event to play with. + // This means that threads won't be interruptable when blocked in + // Process.waitFor. + static HANDLE fake = 0; + if (fake == 0) { + fake = CreateEvent(0, true, false, 0); + } + return fake; +} namespace { HMODULE jvmHandle = 0; } diff --git a/src/common.h b/src/common.h index 8c762f6c70..3bb319f767 100644 --- a/src/common.h +++ b/src/common.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -562,6 +562,50 @@ struct Object { }; typedef Object* object; +typedef uint8_t jboolean; +typedef int8_t jbyte; +typedef uint16_t jchar; +typedef int16_t jshort; +typedef int32_t jint; +typedef int64_t jlong; +typedef float jfloat; +typedef double jdouble; + +typedef jint jsize; + +typedef object* jobject; + +typedef jobject jclass; +typedef jobject jthrowable; +typedef jobject jstring; +typedef jobject jweak; + +typedef jobject jarray; +typedef jarray jbooleanArray; +typedef jarray jbyteArray; +typedef jarray jcharArray; +typedef jarray jshortArray; +typedef jarray jintArray; +typedef jarray jlongArray; +typedef jarray jfloatArray; +typedef jarray jdoubleArray; +typedef jarray jobjectArray; + +typedef uintptr_t jfieldID; +typedef uintptr_t jmethodID; + +union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +}; + } // namespace vm #endif//COMMON_H diff --git a/src/compile-arm.S b/src/compile-arm.S index 0f69903934..427378c1f8 100644 --- a/src/compile-arm.S +++ b/src/compile-arm.S @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -9,6 +9,7 @@ details. */ #include "types.h" +#include "target-fields.h" .text @@ -22,14 +23,6 @@ # define GLOBAL(x) x #endif -#define THREAD_STACK 2148 -#define THREAD_SCRATCH 2152 -#define THREAD_CONTINUATION 2156 -#define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2160 -#define THREAD_EXCEPTION_OFFSET 2164 -#define THREAD_EXCEPTION_HANDLER 2168 - #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 #define CONTINUATION_RETURN_ADDRESS_OFFSET 20 @@ -57,7 +50,7 @@ GLOBAL(vmInvoke): ldr r4, [sp, #4] str r4, [sp, #-4]! - str sp, [r0, #THREAD_SCRATCH] + str sp, [r0, #TARGET_THREAD_SCRATCH] // align stack, if necessary eor r4, sp, r3 @@ -88,7 +81,7 @@ LOCAL(vmInvoke_argumentTest): .align 2 GLOBAL(vmInvoke_returnAddress): // restore stack pointer - ldr sp, [r8, #THREAD_SCRATCH] + ldr sp, [r8, #TARGET_THREAD_SCRATCH] // clear MyThread::stack to avoid confusing another thread calling // java.lang.Thread.getStackTrace on this one. See @@ -96,7 +89,7 @@ GLOBAL(vmInvoke_returnAddress): // a reliable stack trace from a thread that might be interrupted at // any point in its execution. mov r5, #0 - str r5, [r8, #THREAD_STACK] + str r5, [r8, #TARGET_THREAD_STACK] .globl GLOBAL(vmInvoke_safeStack) .align 2 @@ -104,7 +97,7 @@ GLOBAL(vmInvoke_safeStack): #ifdef AVIAN_CONTINUATIONS // call the next continuation, if any - ldr r5,[r8,#THREAD_CONTINUATION] + ldr r5,[r8,#TARGET_THREAD_CONTINUATION] cmp r5,#0 beq LOCAL(vmInvoke_exit) @@ -138,10 +131,10 @@ LOCAL(vmInvoke_getAddress): str r11,[sp,r7] ldr r7,[r5,#CONTINUATION_NEXT] - str r7,[r8,#THREAD_CONTINUATION] + str r7,[r8,#TARGET_THREAD_CONTINUATION] // call the continuation unless we're handling an exception - ldr r7,[r8,#THREAD_EXCEPTION] + ldr r7,[r8,#TARGET_THREAD_EXCEPTION] cmp r7,#0 bne LOCAL(vmInvoke_handleException) ldr r7,[r5,#CONTINUATION_ADDRESS] @@ -150,22 +143,22 @@ LOCAL(vmInvoke_getAddress): LOCAL(vmInvoke_handleException): // we're handling an exception - call the exception handler instead mov r11,#0 - str r11,[r8,#THREAD_EXCEPTION] - ldr r11,[r8,#THREAD_EXCEPTION_STACK_ADJUSTMENT] + str r11,[r8,#TARGET_THREAD_EXCEPTION] + ldr r11,[r8,#TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT] ldr r9,[sp] neg r11,r11 str r9,[sp,r11]! - ldr r11,[r8,#THREAD_EXCEPTION_OFFSET] + ldr r11,[r8,#TARGET_THREAD_EXCEPTIONOFFSET] str r7,[sp,r11] - ldr r7,[r8,#THREAD_EXCEPTION_HANDLER] + ldr r7,[r8,#TARGET_THREAD_EXCEPTIONHANDLER] bx r7 LOCAL(vmInvoke_exit): #endif // AVIAN_CONTINUATIONS mov ip, #0 - str ip, [r8, #THREAD_STACK] + str ip, [r8, #TARGET_THREAD_STACK] // restore return type ldr ip, [sp], #4 diff --git a/src/compile-powerpc.S b/src/compile-powerpc.S index bd178c9117..667ae40ed7 100644 --- a/src/compile-powerpc.S +++ b/src/compile-powerpc.S @@ -9,6 +9,7 @@ details. */ #include "types.h" +#include "target-fields.h" .text @@ -28,13 +29,6 @@ #endif #define ARGUMENT_BASE BYTES_PER_WORD * LINKAGE_AREA - -#define THREAD_STACK 2148 -#define THREAD_CONTINUATION 2156 -#define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2160 -#define THREAD_EXCEPTION_OFFSET 2164 -#define THREAD_EXCEPTION_HANDLER 2168 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 @@ -121,14 +115,14 @@ GLOBAL(vmInvoke_returnAddress): // a reliable stack trace from a thread that might be interrupted at // any point in its execution. li r5,0 - stw r5,THREAD_STACK(r13) + stw r5,TARGET_THREAD_STACK(r13) .globl GLOBAL(vmInvoke_safeStack) GLOBAL(vmInvoke_safeStack): #ifdef AVIAN_CONTINUATIONS // call the next continuation, if any - lwz r5,THREAD_CONTINUATION(r13) + lwz r5,TARGET_THREAD_CONTINUATION(r13) cmplwi r5,0 beq LOCAL(vmInvoke_exit) @@ -171,10 +165,10 @@ LOCAL(vmInvoke_getPC): stw r7,0(r1) lwz r7,CONTINUATION_NEXT(r5) - stw r7,THREAD_CONTINUATION(r13) + stw r7,TARGET_THREAD_CONTINUATION(r13) // call the continuation unless we're handling an exception - lwz r7,THREAD_EXCEPTION(r13) + lwz r7,TARGET_THREAD_EXCEPTION(r13) cmpwi r7,0 bne LOCAL(vmInvoke_handleException) lwz r7,CONTINUATION_ADDRESS(r5) @@ -184,15 +178,15 @@ LOCAL(vmInvoke_getPC): LOCAL(vmInvoke_handleException): // we're handling an exception - call the exception handler instead li r8,0 - stw r8,THREAD_EXCEPTION(r13) - lwz r8,THREAD_EXCEPTION_STACK_ADJUSTMENT(r13) + stw r8,TARGET_THREAD_EXCEPTION(r13) + lwz r8,TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT(r13) lwz r9,0(r1) subfic r8,r8,0 stwux r9,r1,r8 - lwz r8,THREAD_EXCEPTION_OFFSET(r13) + lwz r8,TARGET_THREAD_EXCEPTIONOFFSET(r13) stwx r7,r1,r8 - lwz r7,THREAD_EXCEPTION_HANDLER(r13) + lwz r7,TARGET_THREAD_EXCEPTIONHANDLER(r13) mtctr r7 bctr diff --git a/src/compile-x86.S b/src/compile-x86.S index 52bf411355..a5d0e1930f 100644 --- a/src/compile-x86.S +++ b/src/compile-x86.S @@ -9,6 +9,7 @@ details. */ #include "types.h" +#include "target-fields.h" #define LOCAL(x) .L##x @@ -23,9 +24,6 @@ #ifdef __x86_64__ -#define THREAD_STACK 2224 -#define THREAD_SCRATCH 2232 - #ifdef AVIAN_USE_FRAME_POINTER # define ALIGNMENT_ADJUSTMENT 0 #else @@ -53,7 +51,7 @@ GLOBAL(vmInvoke): // remember this stack position, since we won't be able to rely on // %rbp being restored when the call returns - movq %rsp,THREAD_SCRATCH(%rcx) + movq %rsp,TARGET_THREAD_SCRATCH(%rcx) // save callee-saved registers movq %rbx,0(%rsp) @@ -90,14 +88,14 @@ LOCAL(vmInvoke_argumentTest): .globl GLOBAL(vmInvoke_returnAddress) GLOBAL(vmInvoke_returnAddress): // restore stack pointer - movq THREAD_SCRATCH(%rbx),%rsp + movq TARGET_THREAD_SCRATCH(%rbx),%rsp // clear MyThread::stack to avoid confusing another thread calling // java.lang.Thread.getStackTrace on this one. See // MyProcess::getStackTrace in compile.cpp for details on how we get // a reliable stack trace from a thread that might be interrupted at // any point in its execution. - movq $0,THREAD_STACK(%rbx) + movq $0,TARGET_THREAD_STACK(%rbx) .globl GLOBAL(vmInvoke_safeStack) GLOBAL(vmInvoke_safeStack): @@ -188,7 +186,7 @@ GLOBAL(vmInvoke): // remember this stack position, since we won't be able to rely on // %rbp being restored when the call returns - movq %rsp,THREAD_SCRATCH(%rdi) + movq %rsp,TARGET_THREAD_SCRATCH(%rdi) // save callee-saved registers movq %rbx,0(%rsp) @@ -222,14 +220,14 @@ LOCAL(vmInvoke_argumentTest): .globl GLOBAL(vmInvoke_returnAddress) GLOBAL(vmInvoke_returnAddress): // restore stack pointer - movq THREAD_SCRATCH(%rbx),%rsp + movq TARGET_THREAD_SCRATCH(%rbx),%rsp // clear MyThread::stack to avoid confusing another thread calling // java.lang.Thread.getStackTrace on this one. See // MyProcess::getStackTrace in compile.cpp for details on how we get // a reliable stack trace from a thread that might be interrupted at // any point in its execution. - movq $0,THREAD_STACK(%rbx) + movq $0,TARGET_THREAD_STACK(%rbx) .globl GLOBAL(vmInvoke_safeStack) GLOBAL(vmInvoke_safeStack): @@ -299,9 +297,6 @@ LOCAL(vmJumpAndInvoke_argumentTest): #elif defined __i386__ -#define THREAD_STACK 2148 -#define THREAD_SCRATCH 2152 - #ifdef AVIAN_USE_FRAME_POINTER # define ALIGNMENT_ADJUSTMENT 0 #else @@ -328,7 +323,7 @@ GLOBAL(vmInvoke): // remember this stack position, since we won't be able to rely on // %rbp being restored when the call returns movl 8(%ebp),%eax - movl %esp,THREAD_SCRATCH(%eax) + movl %esp,TARGET_THREAD_SCRATCH(%eax) movl %ebx,0(%esp) movl %esi,4(%esp) @@ -360,14 +355,14 @@ LOCAL(vmInvoke_argumentTest): .globl GLOBAL(vmInvoke_returnAddress) GLOBAL(vmInvoke_returnAddress): // restore stack pointer - movl THREAD_SCRATCH(%ebx),%esp + movl TARGET_THREAD_SCRATCH(%ebx),%esp // clear MyThread::stack to avoid confusing another thread calling // java.lang.Thread.getStackTrace on this one. See // MyProcess::getStackTrace in compile.cpp for details on how we get // a reliable stack trace from a thread that might be interrupted at // any point in its execution. - movl $0,THREAD_STACK(%ebx) + movl $0,TARGET_THREAD_STACK(%ebx) .globl GLOBAL(vmInvoke_safeStack) GLOBAL(vmInvoke_safeStack): diff --git a/src/compile.cpp b/src/compile.cpp index 4963212feb..d1518871d3 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -176,8 +176,8 @@ class MyThread: public Thread { Context(t, ip, stack, continuation, trace), t(t), link(0), - javaStackLimit(0), - next(t->traceContext) + next(t->traceContext), + methodIsMostRecent(false) { t->traceContext = this; } @@ -186,8 +186,8 @@ class MyThread: public Thread { Context(t, t->ip, t->stack, t->continuation, t->trace), t(t), link(link), - javaStackLimit(0), - next(t->traceContext) + next(t->traceContext), + methodIsMostRecent(false) { t->traceContext = this; } @@ -198,8 +198,8 @@ class MyThread: public Thread { MyThread* t; void* link; - void* javaStackLimit; TraceContext* next; + bool methodIsMostRecent; }; static void doTransition(MyThread* t, void* ip, void* stack, @@ -235,6 +235,7 @@ class MyThread: public Thread { Thread(m, javaThread, parent), ip(0), stack(0), + newStack(0), scratch(0), continuation(0), exceptionStackAdjustment(0), @@ -261,6 +262,7 @@ class MyThread: public Thread { void* ip; void* stack; + void* newStack; void* scratch; object continuation; uintptr_t exceptionStackAdjustment; @@ -288,14 +290,6 @@ transition(MyThread* t, void* ip, void* stack, object continuation, MyThread::doTransition(t, ip, stack, continuation, trace); } -unsigned -parameterOffset(MyThread* t, object method) -{ - return methodParameterFootprint(t, method) - + t->arch->frameFooterSize() - + t->arch->frameReturnAddressSize() - 1; -} - object resolveThisPointer(MyThread* t, void* stack) { @@ -353,18 +347,18 @@ root(Thread* t, Root root); void setRoot(Thread* t, Root root, object value); -unsigned -compiledSize(intptr_t address) -{ - return reinterpret_cast(address)[-1]; -} - intptr_t methodCompiled(Thread* t, object method) { return codeCompiled(t, methodCode(t, method)); } +unsigned +methodCompiledSize(Thread* t, object method) +{ + return codeCompiledSize(t, methodCode(t, method)); +} + intptr_t compareIpToMethodBounds(Thread* t, intptr_t ip, object method) { @@ -374,13 +368,13 @@ compareIpToMethodBounds(Thread* t, intptr_t ip, object method) fprintf(stderr, "find %p in (%p,%p)\n", reinterpret_cast(ip), reinterpret_cast(start), - reinterpret_cast(start + compiledSize(start))); + reinterpret_cast(start + methodCompiledSize(t, method))); } if (ip < start) { return -1; } else if (ip < start + static_cast - (compiledSize(start) + TargetBytesPerWord)) + (methodCompiledSize(t, method))) { return 0; } else { @@ -427,19 +421,20 @@ alignedFrameSize(MyThread* t, object method) } void -nextFrame(MyThread* t, void** ip, void** sp, object method, object target) +nextFrame(MyThread* t, void** ip, void** sp, object method, object target, + bool mostRecent) { object code = methodCode(t, method); intptr_t start = codeCompiled(t, code); void* link; - void* javaStackLimit; + bool methodIsMostRecent; if (t->traceContext) { link = t->traceContext->link; - javaStackLimit = t->traceContext->javaStackLimit; + methodIsMostRecent = mostRecent and t->traceContext->methodIsMostRecent; } else { link = 0; - javaStackLimit = 0; + methodIsMostRecent = false; } // fprintf(stderr, "nextFrame %s.%s%s target %s.%s%s ip %p sp %p\n", @@ -458,8 +453,8 @@ nextFrame(MyThread* t, void** ip, void** sp, object method, object target) // *ip, *sp); t->arch->nextFrame - (reinterpret_cast(start), compiledSize(start), - alignedFrameSize(t, method), link, javaStackLimit, + (reinterpret_cast(start), codeCompiledSize(t, code), + alignedFrameSize(t, method), link, methodIsMostRecent, target ? methodParameterFootprint(t, target) : -1, ip, sp); // fprintf(stderr, "next frame ip %p sp %p\n", *ip, *sp); @@ -514,6 +509,7 @@ class MyStackWalker: public Processor::StackWalker { state(Start), method_(0), target(0), + count_(0), protector(this) { if (t->traceContext) { @@ -538,6 +534,7 @@ class MyStackWalker: public Processor::StackWalker { method_(w->method_), target(w->target), continuation(w->continuation), + count_(w->count_), protector(this) { } @@ -609,13 +606,15 @@ class MyStackWalker: public Processor::StackWalker { } void next() { + expect(t, count_ <= stackSizeInWords(t)); + switch (state) { case Continuation: continuation = continuationNext(t, continuation); break; case Method: - nextFrame(t, &ip_, &stack, method_, target); + nextFrame(t, &ip_, &stack, method_, target, count_ == 0); break; case NativeMethod: @@ -625,6 +624,8 @@ class MyStackWalker: public Processor::StackWalker { abort(t); } + ++ count_; + state = Next; } @@ -671,6 +672,7 @@ class MyStackWalker: public Processor::StackWalker { object method_; object target; object continuation; + unsigned count_; MyProtector protector; }; @@ -1381,8 +1383,7 @@ class Frame { Compiler::Operand* append(object o) { BootContext* bc = context->bootContext; if (bc) { - Promise* p = new (bc->zone->allocate(sizeof(ListenPromise))) - ListenPromise(t->m->system, bc->zone); + Promise* p = new (bc->zone) ListenPromise(t->m->system, bc->zone); PROTECT(t, o); object pointer = makePointer(t, p); @@ -1391,7 +1392,7 @@ class Frame { return c->add (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadHeapImage), c->promiseConstant + TARGET_THREAD_HEAPIMAGE), c->promiseConstant (p, Compiler::AddressType)); } else { for (PoolElement* e = context->objectPool; e; e = e->next) { @@ -1400,9 +1401,7 @@ class Frame { } } - context->objectPool = new - (context->zone.allocate(sizeof(PoolElement))) - PoolElement(t, o, context->objectPool); + context->objectPool = new(&context->zone) PoolElement(t, o, context->objectPool); ++ context->objectPoolCount; @@ -1607,8 +1606,7 @@ class Frame { Promise* addressPromise(Promise* p) { BootContext* bc = context->bootContext; if (bc) { - bc->addresses = new (bc->zone->allocate(sizeof(DelayedPromise))) - DelayedPromise(t->m->system, bc->zone, p, bc->addresses); + bc->addresses = new(bc->zone) DelayedPromise(t->m->system, bc->zone, p, bc->addresses); return bc->addresses; } else { return p; @@ -1624,8 +1622,8 @@ class Frame { ? c->add (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadCodeImage), c->promiseConstant - (new (context->zone.allocate(sizeof(OffsetPromise))) + TARGET_THREAD_CODEIMAGE), c->promiseConstant + (new(&context->zone) OffsetPromise (p, - reinterpret_cast(codeAllocator(t)->base)), Compiler::AddressType)) @@ -1934,8 +1932,7 @@ class Frame { subroutine->handle = c->startSubroutine(); this->subroutine = subroutine; - SubroutineCall* call = new - (context->zone.allocate(sizeof(SubroutineCall))) + SubroutineCall* call = new(&context->zone) SubroutineCall(subroutine, returnAddress); context->eventLog.append(PushSubroutineEvent); @@ -2065,6 +2062,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetFrame, } object target = t->trace->targetMethod; + bool mostRecent = true; *targetIp = 0; while (*targetIp == 0) { @@ -2075,7 +2073,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetFrame, if (handler) { *targetIp = handler; - nextFrame(t, &ip, &stack, method, target); + nextFrame(t, &ip, &stack, method, target, mostRecent); void** sp = static_cast(stackForFrame(t, stack, method)) + t->arch->frameReturnAddressSize(); @@ -2089,7 +2087,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetFrame, t->exception = 0; } else { - nextFrame(t, &ip, &stack, method, target); + nextFrame(t, &ip, &stack, method, target, mostRecent); if (t->exception) { releaseLock(t, method, stack); @@ -2137,6 +2135,8 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetFrame, *targetContinuation = continuationNext(t, c); } } + + mostRecent = false; } } @@ -2160,6 +2160,8 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack) object last = 0; PROTECT(t, last); + bool mostRecent = true; + *targetIp = 0; while (*targetIp == 0) { object method = methodForIp(t, ip); @@ -2177,7 +2179,7 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack) } void* nextIp = ip; - nextFrame(t, &nextIp, &stack, method, target); + nextFrame(t, &nextIp, &stack, method, target, mostRecent); void** bottom = static_cast(stack) + t->arch->frameReturnAddressSize(); @@ -2215,6 +2217,8 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack) *targetStack = static_cast(stack) + t->arch->frameReturnAddressSize(); } + + mostRecent = false; } expect(t, last); @@ -2357,6 +2361,31 @@ findInterfaceMethodFromInstanceAndReference return findInterfaceMethodFromInstance(t, method, instance); } +void +checkMethod(Thread* t, object method, bool shouldBeStatic) +{ + if (((methodFlags(t, method) & ACC_STATIC) == 0) == shouldBeStatic) { + throwNew(t, Machine::IncompatibleClassChangeErrorType, + "expected %s.%s%s to be %s", + &byteArrayBody(t, className(t, methodClass(t, method)), 0), + &byteArrayBody(t, methodName(t, method), 0), + &byteArrayBody(t, methodSpec(t, method), 0), + shouldBeStatic ? "static" : "non-static"); + } +} + +void +checkField(Thread* t, object field, bool shouldBeStatic) +{ + if (((fieldFlags(t, field) & ACC_STATIC) == 0) == shouldBeStatic) { + throwNew(t, Machine::IncompatibleClassChangeErrorType, + "expected %s.%s to be %s", + &byteArrayBody(t, className(t, fieldClass(t, field)), 0), + &byteArrayBody(t, fieldName(t, field), 0), + shouldBeStatic ? "static" : "non-static"); + } +} + int64_t findSpecialMethodFromReference(MyThread* t, object pair) { @@ -2369,7 +2398,7 @@ findSpecialMethodFromReference(MyThread* t, object pair) target = findVirtualMethod(t, target, classSuper(t, class_)); } - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); + checkMethod(t, target, false); return prepareMethodForCall(t, target); } @@ -2379,7 +2408,7 @@ findStaticMethodFromReference(MyThread* t, object pair) { object target = resolveMethod(t, pair); - assert(t, methodFlags(t, target) & ACC_STATIC); + checkMethod(t, target, true); return prepareMethodForCall(t, target); } @@ -2393,7 +2422,7 @@ findVirtualMethodFromReference(MyThread* t, object pair, object instance) target = findVirtualMethod(t, target, objectClass(t, instance)); - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); + checkMethod(t, target, false); return prepareMethodForCall(t, target); } @@ -3350,7 +3379,7 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall, frame->absoluteAddressOperand(returnAddressPromise), TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadTailAddress)); + TARGET_THREAD_TAILADDRESS)); c->exit (c->constant @@ -3402,8 +3431,7 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall) and (not (TailCalls and tailCall and (methodFlags(t, target) & ACC_NATIVE)))) { - Promise* p = new (bc->zone->allocate(sizeof(ListenPromise))) - ListenPromise(t->m->system, bc->zone); + Promise* p = new(bc->zone) ListenPromise(t->m->system, bc->zone); PROTECT(t, target); object pointer = makePointer(t, p); @@ -4295,6 +4323,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, 0, Compiler::VoidType, 2, c->register_(t->arch->thread()), target); + + if (ip == codeLength(t, code)) { + c->trap(); + } } return; case bipush: @@ -4569,7 +4601,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* table; if (instruction == getstatic) { - assert(t, fieldFlags(t, field) & ACC_STATIC); + checkField(t, field, true); PROTECT(t, field); @@ -4589,7 +4621,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, table = frame->append(classStaticTable(t, fieldClass(t, field))); } else { - assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0); + checkField(t, field, false); table = frame->popObject(); @@ -5034,7 +5066,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, int returnCode; bool tailCall; if (LIKELY(target)) { - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); + checkMethod(t, target, false); argument = target; thunk = findInterfaceMethodFromInstanceThunk; @@ -5093,7 +5125,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, target = findVirtualMethod(t, target, classSuper(t, class_)); } - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); + checkMethod(t, target, false); bool tailCall = isTailCall(t, code, ip, context->method, target); @@ -5123,7 +5155,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object target = resolveMethod(t, context->method, index - 1, false); if (LIKELY(target)) { - assert(t, methodFlags(t, target) & ACC_STATIC); + checkMethod(t, target, true); if (not intrinsic(t, frame, target)) { bool tailCall = isTailCall(t, code, ip, context->method, target); @@ -5149,8 +5181,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object target = resolveMethod(t, context->method, index - 1, false); if (LIKELY(target)) { - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); - + checkMethod(t, target, false); + if (not intrinsic(t, frame, target)) { bool tailCall = isTailCall(t, code, ip, context->method, target); @@ -5530,7 +5562,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, (context->bootContext ? c->add (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadCodeImage), address) + TARGET_THREAD_CODEIMAGE), address) : address); Compiler::State* state = c->saveState(); @@ -5763,7 +5795,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object staticTable = 0; if (instruction == putstatic) { - assert(t, fieldFlags(t, field) & ACC_STATIC); + checkField(t, field, true); if (fieldClass(t, field) != methodClass(t, context->method) and classNeedsInit(t, fieldClass(t, field))) @@ -5783,7 +5815,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, staticTable = classStaticTable(t, fieldClass(t, field)); } else { - assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0); + checkField(t, field, false); if (inTryBlock(t, code, ip - 3)) { c->saveLocals(); @@ -6077,7 +6109,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, ? c->add (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadCodeImage), entry) + TARGET_THREAD_CODEIMAGE), entry) : entry, TargetBytesPerWord)); @@ -6149,29 +6181,15 @@ FILE* compileLog = 0; void logCompile(MyThread* t, const void* code, unsigned size, const char* class_, - const char* name, const char* spec) -{ - static bool open = false; - if (not open) { - open = true; - const char* path = findProperty(t, "avian.jit.log"); - if (path) { - compileLog = vm::fopen(path, "wb"); - } else if (DebugCompile) { - compileLog = stderr; - } - } - - if (compileLog) { - fprintf(compileLog, "%p %p %s.%s%s\n", - code, static_cast(code) + size, - class_, name, spec); - } -} + const char* name, const char* spec); int resolveIpForwards(Context* context, int start, int end) { + if (start < 0) { + start = 0; + } + while (start < end and context->visitTable[start] == 0) { ++ start; } @@ -6186,6 +6204,13 @@ resolveIpForwards(Context* context, int start, int end) int resolveIpBackwards(Context* context, int start, int end) { + Thread* t = context->thread; + if (start >= static_cast + (codeLength(t, methodCode(t, context->method)))) + { + start = codeLength(t, methodCode(t, context->method)) - 1; + } + while (start >= end and context->visitTable[start] == 0) { -- start; } @@ -6205,8 +6230,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; } @@ -6219,8 +6246,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; } @@ -6233,9 +6262,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; } @@ -6269,11 +6300,16 @@ translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start) exceptionHandlerEnd(oldHandler)); if (LIKELY(handlerStart >= 0)) { + assert(t, handlerStart < static_cast + (codeLength(t, methodCode(t, context->method)))); + int handlerEnd = resolveIpBackwards (context, exceptionHandlerEnd(oldHandler), exceptionHandlerStart(oldHandler)); assert(t, handlerEnd >= 0); + assert(t, handlerEnd < static_cast + (codeLength(t, methodCode(t, context->method)))); intArrayBody(t, newIndex, ni * 3) = c->machineIp(handlerStart)->value() - start; @@ -6619,7 +6655,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, } if (path == 0) { - path = new (context->zone.allocate(sizeof(SubroutinePath))) + path = new(&context->zone) SubroutinePath(call, subroutinePath, makeRootTable(t, &(context->zone), context->method)); } @@ -6996,20 +7032,19 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) // of cycles if another thread compiles the same method in parallel, // which might be mitigated by fine-grained, per-method locking): c->compile(context->leaf ? 0 : stackOverflowThunk(t), - TargetThreadStackLimit); + TARGET_THREAD_STACKLIMIT); // we must acquire the class lock here at the latest unsigned codeSize = c->resolve - (allocator->base + allocator->offset + TargetBytesPerWord); + (allocator->base + allocator->offset); unsigned total = pad(codeSize, TargetBytesPerWord) - + pad(c->poolSize(), TargetBytesPerWord) + TargetBytesPerWord; + + pad(c->poolSize(), TargetBytesPerWord); target_uintptr_t* code = static_cast (allocator->allocate(total, TargetBytesPerWord)); - code[0] = codeSize; - uint8_t* start = reinterpret_cast(code + 1); + uint8_t* start = reinterpret_cast(code); context->executableAllocator = allocator; context->executableStart = code; @@ -7045,8 +7080,7 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) p != bc->addressSentinal; p = p->next) { - p->basis = new (bc->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(p->basis->value()); + p->basis = new(bc->zone) ResolvedPromise(p->basis->value()); } } @@ -7062,7 +7096,7 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) code = makeCode (t, 0, newExceptionHandlerTable, newLineNumberTable, - reinterpret_cast(start), codeMaxStack(t, code), + reinterpret_cast(start), codeSize, codeMaxStack(t, code), codeMaxLocals(t, code), 0); set(t, context->method, MethodCode, code); @@ -7587,11 +7621,11 @@ invokeNative(MyThread* t) stack += t->arch->frameReturnAddressSize(); - transition(t, getIp(t), stack, t->continuation, t->trace); - t->trace->targetMethod = 0; t->trace->nativeMethod = 0; + t->newStack = stack; + return result; } @@ -7766,6 +7800,7 @@ visitStack(MyThread* t, Heap::Visitor* v) MyThread::CallTrace* trace = t->trace; object targetMethod = (trace ? trace->targetMethod : 0); object target = targetMethod; + bool mostRecent = true; while (stack) { if (targetMethod) { @@ -7778,7 +7813,7 @@ visitStack(MyThread* t, Heap::Visitor* v) PROTECT(t, method); void* nextIp = ip; - nextFrame(t, &nextIp, &stack, method, target); + nextFrame(t, &nextIp, &stack, method, target, mostRecent); visitStackAndLocals(t, v, stack, method, ip); @@ -7799,6 +7834,8 @@ visitStack(MyThread* t, Heap::Visitor* v) } else { break; } + + mostRecent = false; } } @@ -8185,6 +8222,47 @@ class ArgumentList { } } + ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask, + object this_, const char* spec, const jvalue* arguments): + t(static_cast(t)), + array(array), + objectMask(objectMask), + size(size), + position(0), + protector(this) + { + if (this_) { + addObject(this_); + } + + unsigned index = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': { + object* v = arguments[index++].l; + addObject(v ? *v : 0); + } break; + + case 'J': + addLong(arguments[index++].j); + break; + + case 'D': + addLong(arguments[index++].d); + break; + + case 'F': + addLong(arguments[index++].f); + break; + + default: + addLong(arguments[index++].i); + break; + } + } + } + ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask, object this_, const char* spec, object arguments): t(static_cast(t)), @@ -8287,7 +8365,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); } @@ -8432,6 +8510,34 @@ processor(MyThread* t); void compileThunks(MyThread* t, FixedAllocator* allocator); +class CompilationHandlerList { +public: + CompilationHandlerList(CompilationHandlerList* next, Processor::CompilationHandler* handler): + next(next), + handler(handler) {} + + void dispose(Allocator* allocator) { + if(this) { + next->dispose(allocator); + handler->dispose(); + allocator->free(this, sizeof(*this)); + } + } + + CompilationHandlerList* next; + Processor::CompilationHandler* handler; +}; + +template +int checkConstant(MyThread* t, size_t expected, T C::* field, const char* name) { + size_t actual = reinterpret_cast(&(t->*field)) - reinterpret_cast(t); + if(expected != actual) { + fprintf(stderr, "constant mismatch (%s): \n\tconstant says: %d\n\tc++ compiler says: %d\n", name, (unsigned) expected, (unsigned) actual); + return 1; + } + return 0; +} + class MyProcessor: public Processor { public: class Thunk { @@ -8475,7 +8581,8 @@ class MyProcessor: public Processor { FixedSizeOfArithmeticException), codeAllocator(s, 0, 0), callTableSize(0), - useNativeFeatures(useNativeFeatures) + useNativeFeatures(useNativeFeatures), + compilationHandlers(0) { thunkTable[compileMethodIndex] = voidPointer(local::compileMethod); thunkTable[compileVirtualMethodIndex] = voidPointer(compileVirtualMethod); @@ -8507,38 +8614,25 @@ class MyProcessor: public Processor { t->codeImage = codeImage; t->thunkTable = thunkTable; - if (false) { - fprintf(stderr, "stack %d\n", - difference(&(t->stack), t)); - fprintf(stderr, "scratch %d\n", - difference(&(t->scratch), t)); - fprintf(stderr, "continuation %d\n", - difference(&(t->continuation), t)); - fprintf(stderr, "exception %d\n", - difference(&(t->exception), t)); - fprintf(stderr, "exceptionStackAdjustment %d\n", - difference(&(t->exceptionStackAdjustment), t)); - fprintf(stderr, "exceptionOffset %d\n", - difference(&(t->exceptionOffset), t)); - fprintf(stderr, "exceptionHandler %d\n", - difference(&(t->exceptionHandler), t)); - fprintf(stderr, "tailAddress %d\n", - difference(&(t->tailAddress), t)); - fprintf(stderr, "stackLimit %d\n", - difference(&(t->stackLimit), t)); - fprintf(stderr, "ip %d\n", - difference(&(t->ip), t)); - fprintf(stderr, "virtualCallTarget %d\n", - difference(&(t->virtualCallTarget), t)); - fprintf(stderr, "virtualCallIndex %d\n", - difference(&(t->virtualCallIndex), t)); - fprintf(stderr, "heapImage %d\n", - difference(&(t->heapImage), t)); - fprintf(stderr, "codeImage %d\n", - difference(&(t->codeImage), t)); - fprintf(stderr, "thunkTable %d\n", - difference(&(t->thunkTable), t)); - exit(0); + int mismatches = + checkConstant(t, TARGET_THREAD_EXCEPTION, &Thread::exception, "TARGET_THREAD_EXCEPTION") + + checkConstant(t, TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT, &MyThread::exceptionStackAdjustment, "TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT") + + checkConstant(t, TARGET_THREAD_EXCEPTIONOFFSET, &MyThread::exceptionOffset, "TARGET_THREAD_EXCEPTIONOFFSET") + + checkConstant(t, TARGET_THREAD_EXCEPTIONHANDLER, &MyThread::exceptionHandler, "TARGET_THREAD_EXCEPTIONHANDLER") + + checkConstant(t, TARGET_THREAD_IP, &MyThread::ip, "TARGET_THREAD_IP") + + checkConstant(t, TARGET_THREAD_STACK, &MyThread::stack, "TARGET_THREAD_STACK") + + checkConstant(t, TARGET_THREAD_NEWSTACK, &MyThread::newStack, "TARGET_THREAD_NEWSTACK") + + checkConstant(t, TARGET_THREAD_TAILADDRESS, &MyThread::tailAddress, "TARGET_THREAD_TAILADDRESS") + + checkConstant(t, TARGET_THREAD_VIRTUALCALLTARGET, &MyThread::virtualCallTarget, "TARGET_THREAD_VIRTUALCALLTARGET") + + checkConstant(t, TARGET_THREAD_VIRTUALCALLINDEX, &MyThread::virtualCallIndex, "TARGET_THREAD_VIRTUALCALLINDEX") + + checkConstant(t, TARGET_THREAD_HEAPIMAGE, &MyThread::heapImage, "TARGET_THREAD_HEAPIMAGE") + + checkConstant(t, TARGET_THREAD_CODEIMAGE, &MyThread::codeImage, "TARGET_THREAD_CODEIMAGE") + + checkConstant(t, TARGET_THREAD_THUNKTABLE, &MyThread::thunkTable, "TARGET_THREAD_THUNKTABLE") + + checkConstant(t, TARGET_THREAD_STACKLIMIT, &MyThread::stackLimit, "TARGET_THREAD_STACKLIMIT"); + + if(mismatches > 0) { + fprintf(stderr, "%d constant mismatches\n", mismatches); + abort(t); } t->init(); @@ -8710,6 +8804,36 @@ class MyProcessor: public Processor { return local::invoke(t, method, &list); } + virtual object + invokeArray(Thread* t, object method, object this_, const jvalue* arguments) + { + assert(t, t->exception == 0); + + assert(t, t->state == Thread::ActiveState + or t->state == Thread::ExclusiveState); + + assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); + + method = findMethod(t, method, this_); + + const char* spec = reinterpret_cast + (&byteArrayBody(t, methodSpec(t, method), 0)); + + unsigned size = methodParameterFootprint(t, method); + THREAD_RUNTIME_ARRAY(t, uintptr_t, array, size); + THREAD_RUNTIME_ARRAY(t, bool, objectMask, size); + ArgumentList list + (t, RUNTIME_ARRAY_BODY(array), size, RUNTIME_ARRAY_BODY(objectMask), + this_, spec, arguments); + + PROTECT(t, method); + + compile(static_cast(t), + local::codeAllocator(static_cast(t)), 0, method); + + return local::invoke(t, method, &list); + } + virtual object invokeList(Thread* t, object method, object this_, bool indirectObjects, va_list arguments) @@ -8781,6 +8905,7 @@ class MyProcessor: public Processor { t->arch->release(); t->m->heap->free(t, sizeof(*t)); + } virtual void dispose() { @@ -8788,6 +8913,8 @@ class MyProcessor: public Processor { s->freeExecutable(codeAllocator.base, codeAllocator.capacity); } + compilationHandlers->dispose(allocator); + s->handleSegFault(0); allocator->free(this, sizeof(*this)); @@ -8811,7 +8938,7 @@ class MyProcessor: public Processor { // we caught the thread in Java code - use the register values c.ip = ip; c.stack = stack; - c.javaStackLimit = stack; + c.methodIsMostRecent = true; } else if (target->transition) { // we caught the thread in native code while in the middle // of updating the context fields (MyThread::stack, etc.) @@ -8884,6 +9011,10 @@ class MyProcessor: public Processor { codeAllocator.capacity = capacity; } + virtual void addCompilationHandler(CompilationHandler* handler) { + compilationHandlers = new(allocator->allocate(sizeof(CompilationHandlerList))) CompilationHandlerList(compilationHandlers, handler); + } + virtual void compileMethod(Thread* vmt, Zone* zone, object* constants, object* calls, DelayedPromise** addresses, object method, OffsetResolver* resolver) @@ -9039,8 +9170,56 @@ class MyProcessor: public Processor { unsigned callTableSize; bool useNativeFeatures; void* thunkTable[dummyIndex + 1]; + CompilationHandlerList* compilationHandlers; }; +const char* +stringOrNull(const char* str) { + if(str) { + return str; + } else { + return "(null)"; + } +} + +size_t +stringOrNullSize(const char* str) { + return strlen(stringOrNull(str)); +} + +void +logCompile(MyThread* t, const void* code, unsigned size, const char* class_, + const char* name, const char* spec) +{ + static bool open = false; + if (not open) { + open = true; + const char* path = findProperty(t, "avian.jit.log"); + if (path) { + compileLog = vm::fopen(path, "wb"); + } else if (DebugCompile) { + compileLog = stderr; + } + } + + if (compileLog) { + fprintf(compileLog, "%p %p %s.%s%s\n", + code, static_cast(code) + size, + class_, name, spec); + } + + size_t nameLength = stringOrNullSize(class_) + stringOrNullSize(name) + stringOrNullSize(spec) + 2; + + THREAD_RUNTIME_ARRAY(t, char, completeName, nameLength); + + sprintf(RUNTIME_ARRAY_BODY(completeName), "%s.%s%s", stringOrNull(class_), stringOrNull(name), stringOrNull(spec)); + + MyProcessor* p = static_cast(t->m->processor); + for(CompilationHandlerList* h = p->compilationHandlers; h; h = h->next) { + h->handler->compiled(code, 0, 0, RUNTIME_ARRAY_BODY(completeName)); + } +} + void* compileMethod2(MyThread* t, void* ip) { @@ -9440,8 +9619,7 @@ fixupMethods(Thread* t, object map, BootImage* image UNUSED, uint8_t* code) logCompile (static_cast(t), reinterpret_cast(methodCompiled(t, method)), - reinterpret_cast - (methodCompiled(t, method))[-1], + methodCompiledSize(t, method), reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, method)), 0)), reinterpret_cast @@ -9522,9 +9700,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) // fprintf(stderr, "code from %p to %p\n", // code, code + image->codeSize); - static bool fixed = false; - - if (not fixed) { + if (not image->initialized) { fixupHeap(t, heapMap, heapMapSizeInWords, heap); } @@ -9571,7 +9747,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) findThunks(t, image, code); - if (fixed) { + if (image->initialized) { resetRuntimeState (t, classLoaderMap(t, root(t, Machine::BootLoader)), heap, image->heapSize); @@ -9594,7 +9770,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) (t, classLoaderMap(t, root(t, Machine::AppLoader)), image, code); } - fixed = true; + image->initialized = true; setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0)); } @@ -9621,7 +9797,7 @@ compileCall(MyThread* t, Context* c, ThunkIndex index, bool call = true) Assembler* a = c->assembler; if (processor(t)->bootImage) { - Assembler::Memory table(t->arch->thread(), TargetThreadThunkTable); + Assembler::Memory table(t->arch->thread(), TARGET_THREAD_THUNKTABLE); Assembler::Register scratch(t->arch->scratch()); a->apply(Move, TargetBytesPerWord, MemoryOperand, &table, TargetBytesPerWord, RegisterOperand, &scratch); @@ -9632,8 +9808,7 @@ compileCall(MyThread* t, Context* c, ThunkIndex index, bool call = true) (call ? Call : Jump, TargetBytesPerWord, RegisterOperand, &scratch); } else { Assembler::Constant proc - (new (c->zone.allocate(sizeof(ResolvedPromise))) - ResolvedPromise(reinterpret_cast(t->thunkTable[index]))); + (new(&c->zone) ResolvedPromise(reinterpret_cast(t->thunkTable[index]))); a->apply (call ? LongCall : LongJump, TargetBytesPerWord, ConstantOperand, &proc); @@ -9648,7 +9823,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.default_.frameSavedOffset = a->length(); @@ -9681,19 +9856,19 @@ compileThunks(MyThread* t, FixedAllocator* allocator) TargetBytesPerWord, RegisterOperand, &class_); Assembler::Memory virtualCallTargetDst - (t->arch->thread(), TargetThreadVirtualCallTarget); + (t->arch->thread(), TARGET_THREAD_VIRTUALCALLTARGET); a->apply(Move, TargetBytesPerWord, RegisterOperand, &class_, TargetBytesPerWord, MemoryOperand, &virtualCallTargetDst); Assembler::Register index(t->arch->virtualCallIndex()); Assembler::Memory virtualCallIndex - (t->arch->thread(), TargetThreadVirtualCallIndex); + (t->arch->thread(), TARGET_THREAD_VIRTUALCALLINDEX); a->apply(Move, TargetBytesPerWord, RegisterOperand, &index, TargetBytesPerWord, MemoryOperand, &virtualCallIndex); - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.defaultVirtual.frameSavedOffset = a->length(); @@ -9716,7 +9891,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.native.frameSavedOffset = a->length(); @@ -9726,7 +9901,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) compileCall(t, &context, invokeNativeIndex); a->popFrameAndUpdateStackAndReturn - (t->arch->alignFrameSize(1), TargetThreadStack); + (t->arch->alignFrameSize(1), TARGET_THREAD_NEWSTACK); p->thunks.native.length = a->endBlock(false)->resolve(0, 0); @@ -9737,7 +9912,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.aioob.frameSavedOffset = a->length(); @@ -9755,7 +9930,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.stackOverflow.frameSavedOffset = a->length(); @@ -9773,7 +9948,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.table.frameSavedOffset = a->length(); @@ -9792,7 +9967,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) Context context(t); \ Assembler* a = context.assembler; \ \ - a->saveFrame(TargetThreadStack, TargetThreadIp); \ + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); \ \ p->thunks.table.frameSavedOffset = a->length(); \ \ @@ -9908,7 +10083,15 @@ compileVirtualThunk(MyThread* t, unsigned index, unsigned* size) a->setDestination(start); a->write(); - logCompile(t, start, *size, 0, "virtualThunk", 0); + const char* const virtualThunkBaseName = "virtualThunk"; + const size_t virtualThunkBaseNameLength = strlen(virtualThunkBaseName); + const size_t maxIntStringLength = 10; + + THREAD_RUNTIME_ARRAY(t, char, virtualThunkName, virtualThunkBaseNameLength + maxIntStringLength); + + sprintf(RUNTIME_ARRAY_BODY(virtualThunkName), "%s%d", virtualThunkBaseName, index); + + logCompile(t, start, *size, 0, RUNTIME_ARRAY_BODY(virtualThunkName), 0); return reinterpret_cast(start); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 737f723da4..8e118008bb 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -576,28 +576,7 @@ count(Cell* c) Cell* cons(Context* c, void* value, Cell* next) { - return new (c->zone->allocate(sizeof(Cell))) Cell(next, value); -} - -Cell* -append(Context* c, Cell* first, Cell* second) -{ - if (first) { - if (second) { - Cell* start = cons(c, first->value, second); - Cell* end = start; - for (Cell* cell = first->next; cell; cell = cell->next) { - Cell* n = cons(c, cell->value, second); - end->next = n; - end = n; - } - return start; - } else { - return first; - } - } else { - return second; - } + return new (c->zone) Cell(next, value); } Cell* @@ -648,7 +627,7 @@ Link* link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor, Link* nextSuccessor, ForkState* forkState) { - return new (c->zone->allocate(sizeof(Link))) Link + return new(c->zone) Link (predecessor, nextPredecessor, successor, nextSuccessor, forkState); } @@ -992,6 +971,8 @@ valid(Read* r) return r and r->valid(); } +#ifndef NDEBUG + bool hasBuddy(Context* c, Value* a, Value* b) { @@ -1011,6 +992,8 @@ hasBuddy(Context* c, Value* a, Value* b) return false; } +#endif // not NDEBUG + Read* live(Context* c UNUSED, Value* v) { @@ -1602,15 +1585,13 @@ constantSite(Context* c, Promise* value); ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { - return new (c->zone->allocate(sizeof(ShiftMaskPromise))) - ShiftMaskPromise(base, shift, mask); + return new(c->zone) ShiftMaskPromise(base, shift, mask); } CombinedPromise* combinedPromise(Context* c, Promise* low, Promise* high) { - return new (c->zone->allocate(sizeof(CombinedPromise))) - CombinedPromise(low, high); + return new(c->zone) CombinedPromise(low, high); } class ConstantSite: public Site { @@ -1620,7 +1601,7 @@ class ConstantSite: public Site { virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { if (value->resolved()) { return vm::snprintf - (buffer, bufferSize, "constant %"LLD, value->value()); + (buffer, bufferSize, "constant %" LLD, value->value()); } else { return vm::snprintf(buffer, bufferSize, "constant unresolved"); } @@ -1686,14 +1667,13 @@ class ConstantSite: public Site { ConstantSite* constantSite(Context* c, Promise* value) { - return new (c->zone->allocate(sizeof(ConstantSite))) ConstantSite(value); + return new(c->zone) ConstantSite(value); } ResolvedPromise* resolved(Context* c, int64_t value) { - return new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value); + return new(c->zone) ResolvedPromise(value); } ConstantSite* @@ -1712,7 +1692,7 @@ class AddressSite: public Site { virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { if (address->resolved()) { return vm::snprintf - (buffer, bufferSize, "address %"LLD, address->value()); + (buffer, bufferSize, "address %" LLD, address->value()); } else { return vm::snprintf(buffer, bufferSize, "address unresolved"); } @@ -1776,7 +1756,7 @@ class AddressSite: public Site { AddressSite* addressSite(Context* c, Promise* address) { - return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); + return new(c->zone) AddressSite(address); } RegisterSite* @@ -1978,15 +1958,13 @@ registerSite(Context* c, int number) assert(c, (1 << number) & (c->arch->generalRegisterMask() | c->arch->floatRegisterMask())); - return new (c->zone->allocate(sizeof(RegisterSite))) - RegisterSite(1 << number, number); + return new(c->zone) RegisterSite(1 << number, number); } RegisterSite* freeRegisterSite(Context* c, uint32_t mask) { - return new (c->zone->allocate(sizeof(RegisterSite))) - RegisterSite(mask, NoRegister); + return new(c->zone) RegisterSite(mask, NoRegister); } MemorySite* @@ -2219,8 +2197,7 @@ class MemorySite: public Site { MemorySite* memorySite(Context* c, int base, int offset, int index, unsigned scale) { - return new (c->zone->allocate(sizeof(MemorySite))) - MemorySite(base, offset, index, scale); + return new(c->zone) MemorySite(base, offset, index, scale); } MemorySite* @@ -2341,8 +2318,7 @@ read(Context* c, const SiteMask& mask, Value* successor = 0) { assert(c, (mask.typeMask != 1 << MemoryOperand) or mask.frameIndex >= 0); - return new (c->zone->allocate(sizeof(SingleRead))) - SingleRead(mask, successor); + return new(c->zone) SingleRead(mask, successor); } bool @@ -2762,7 +2738,7 @@ class MultiRead: public Read { MultiRead* multiRead(Context* c) { - return new (c->zone->allocate(sizeof(MultiRead))) MultiRead; + return new(c->zone) MultiRead; } class StubRead: public Read { @@ -2811,7 +2787,7 @@ class StubRead: public Read { StubRead* stubRead(Context* c) { - return new (c->zone->allocate(sizeof(StubRead))) StubRead; + return new(c->zone) StubRead; } Site* @@ -3121,15 +3097,13 @@ clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, CodePromise* codePromise(Context* c, Event* e) { - return e->promises = new (c->zone->allocate(sizeof(CodePromise))) - CodePromise(c, e->promises); + return e->promises = new(c->zone) CodePromise(c, e->promises); } CodePromise* codePromise(Context* c, Promise* offset) { - return new (c->zone->allocate(sizeof(CodePromise))) - CodePromise(c, offset); + return new (c->zone) CodePromise(c, offset); } void @@ -3467,7 +3441,7 @@ appendCall(Context* c, Value* address, unsigned flags, Stack* argumentStack, unsigned argumentCount, unsigned stackArgumentFootprint) { - append(c, new (c->zone->allocate(sizeof(CallEvent))) + append(c, new(c->zone) CallEvent(c, address, flags, traceHandler, result, resultSize, argumentStack, argumentCount, stackArgumentFootprint)); @@ -3515,8 +3489,7 @@ class ReturnEvent: public Event { void appendReturn(Context* c, unsigned size, Value* value) { - append(c, new (c->zone->allocate(sizeof(ReturnEvent))) - ReturnEvent(c, size, value)); + append(c, new(c->zone) ReturnEvent(c, size, value)); } void @@ -3714,7 +3687,7 @@ pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, Value* value(Context* c, ValueType type, Site* site = 0, Site* target = 0) { - return new (c->zone->allocate(sizeof(Value))) Value(site, target, type); + return new(c->zone) Value(site, target, type); } void @@ -3800,26 +3773,32 @@ class MoveEvent: public Event { and srcSelectSize >= dstSize) { if (dst->target) { - if (dstSize > TargetBytesPerWord - and src->source->registerSize(c) > TargetBytesPerWord) - { - apply(c, Move, srcSelectSize, src->source, src->source, - dstSize, dst->target, dst->target); - - if (live(c, dst) == 0) { - removeSite(c, dst, dst->target); - if (dstSize > TargetBytesPerWord) { - removeSite(c, dst->nextWord, dst->nextWord->target); + if (dstSize > TargetBytesPerWord) { + if (src->source->registerSize(c) > TargetBytesPerWord) { + apply(c, Move, srcSelectSize, src->source, src->source, + dstSize, dst->target, dst->target); + + if (live(c, dst) == 0) { + removeSite(c, dst, dst->target); + if (dstSize > TargetBytesPerWord) { + removeSite(c, dst->nextWord, dst->nextWord->target); + } } - } - } else { - maybeMove(c, Move, TargetBytesPerWord, TargetBytesPerWord, src, - TargetBytesPerWord, dst, dstLowMask); - if (dstSize > TargetBytesPerWord) { + } else { + src->nextWord->source->freeze(c, src->nextWord); + + maybeMove(c, Move, TargetBytesPerWord, TargetBytesPerWord, src, + TargetBytesPerWord, dst, dstLowMask); + + src->nextWord->source->thaw(c, src->nextWord); + maybeMove (c, Move, TargetBytesPerWord, TargetBytesPerWord, src->nextWord, TargetBytesPerWord, dst->nextWord, dstHighMask); } + } else { + maybeMove(c, Move, TargetBytesPerWord, TargetBytesPerWord, src, + TargetBytesPerWord, dst, dstLowMask); } } else { Site* low = pickSiteOrMove(c, src, dst, 0, 0); @@ -3914,7 +3893,7 @@ appendMove(Context* c, BinaryOperation type, unsigned srcSize, assert(c, not thunk); - append(c, new (c->zone->allocate(sizeof(MoveEvent))) + append(c, new(c->zone) MoveEvent (c, type, srcSize, srcSelectSize, src, dstSize, dst, SiteMask(srcTypeMask, srcRegisterMask, AnyFrameIndex), @@ -4173,7 +4152,7 @@ snapshot(Context* c, Value* value, Snapshot* next) value, value->buddy, buffer); } - return new (c->zone->allocate(sizeof(Snapshot))) Snapshot(c, value, next); + return new(c->zone) Snapshot(c, value, next); } Snapshot* @@ -4189,8 +4168,7 @@ makeSnapshots(Context* c, Value* value, Snapshot* next) Stack* stack(Context* c, Value* value, Stack* next) { - return new (c->zone->allocate(sizeof(Stack))) - Stack(next ? next->index + 1 : 0, value, next); + return new(c->zone) Stack(next ? next->index + 1 : 0, value, next); } Value* @@ -4450,7 +4428,7 @@ appendCombine(Context* c, TernaryOperation type, resultSize, argumentStack, stackSize, 0); } else { append - (c, new (c->zone->allocate(sizeof(CombineEvent))) + (c, new(c->zone) CombineEvent (c, type, firstSize, first, @@ -4568,7 +4546,7 @@ appendTranslate(Context* c, BinaryOperation type, unsigned firstSize, 0, 0, result, resultSize, argumentStack, ceiling(firstSize, TargetBytesPerWord), 0); } else { - append(c, new (c->zone->allocate(sizeof(TranslateEvent))) + append(c, new(c->zone) TranslateEvent (c, type, firstSize, first, resultSize, result, SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), @@ -4576,14 +4554,14 @@ appendTranslate(Context* c, BinaryOperation type, unsigned firstSize, } } -class BarrierEvent: public Event { +class OperationEvent: public Event { public: - BarrierEvent(Context* c, Operation op): + OperationEvent(Context* c, Operation op): Event(c), op(op) { } virtual const char* name() { - return "BarrierEvent"; + return "OperationEvent"; } virtual void compile(Context* c) { @@ -4594,9 +4572,10 @@ class BarrierEvent: public Event { }; void -appendBarrier(Context* c, Operation op) +appendOperation(Context* c, Operation op) { - append(c, new (c->zone->allocate(sizeof(BarrierEvent))) BarrierEvent(c, op)); + append + (c, new(c->zone) OperationEvent(c, op)); } class MemoryEvent: public Event { @@ -4676,7 +4655,7 @@ void appendMemory(Context* c, Value* base, int displacement, Value* index, unsigned scale, Value* result) { - append(c, new (c->zone->allocate(sizeof(MemoryEvent))) + append(c, new(c->zone) MemoryEvent(c, base, displacement, index, scale, result)); } @@ -4907,7 +4886,7 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first, result, address); } else { append - (c, new (c->zone->allocate(sizeof(BranchEvent))) + (c, new(c->zone) BranchEvent (c, type, size, first, second, address, SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), @@ -4971,8 +4950,7 @@ void appendJump(Context* c, UnaryOperation type, Value* address, bool exit = false, bool cleanLocals = false) { - append(c, new (c->zone->allocate(sizeof(JumpEvent))) - JumpEvent(c, type, address, exit, cleanLocals)); + append(c, new(c->zone) JumpEvent(c, type, address, exit, cleanLocals)); } class BoundsCheckEvent: public Event { @@ -5050,8 +5028,7 @@ void appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, Value* index, intptr_t handler) { - append(c, new (c->zone->allocate(sizeof(BoundsCheckEvent))) - BoundsCheckEvent(c, object, lengthOffset, index, handler)); + append(c, new(c->zone) BoundsCheckEvent(c, object, lengthOffset, index, handler)); } class FrameSiteEvent: public Event { @@ -5077,8 +5054,7 @@ class FrameSiteEvent: public Event { void appendFrameSite(Context* c, Value* value, int index) { - append(c, new (c->zone->allocate(sizeof(FrameSiteEvent))) - FrameSiteEvent(c, value, index)); + append(c, new(c->zone) FrameSiteEvent(c, value, index)); } unsigned @@ -5156,8 +5132,7 @@ class BuddyEvent: public Event { void appendBuddy(Context* c, Value* original, Value* buddy) { - append(c, new (c->zone->allocate(sizeof(BuddyEvent))) - BuddyEvent(c, original, buddy)); + append(c, new(c->zone) BuddyEvent(c, original, buddy)); } class SaveLocalsEvent: public Event { @@ -5182,8 +5157,7 @@ class SaveLocalsEvent: public Event { void appendSaveLocals(Context* c) { - append(c, new (c->zone->allocate(sizeof(SaveLocalsEvent))) - SaveLocalsEvent(c)); + append(c, new(c->zone) SaveLocalsEvent(c)); } class DummyEvent: public Event { @@ -5209,7 +5183,7 @@ appendDummy(Context* c) c->stack = i->stack; c->locals = i->locals; - append(c, new (c->zone->allocate(sizeof(DummyEvent))) DummyEvent(c)); + append(c, new(c->zone) DummyEvent(c)); c->stack = stack; c->locals = locals; @@ -5317,16 +5291,17 @@ propagateJunctionSites(Context* c, Event* e) class SiteRecord { public: - SiteRecord(Site* site, Value* value): - site(site), value(value) - { } - - SiteRecord() { } - Site* site; Value* value; }; +void +init(SiteRecord* r, Site* s, Value* v) +{ + r->site = s; + r->value = v; +} + class SiteRecordList { public: SiteRecordList(SiteRecord* records, unsigned capacity): @@ -5344,7 +5319,7 @@ freeze(Context* c, SiteRecordList* frozen, Site* s, Value* v) assert(c, frozen->index < frozen->capacity); s->freeze(c, v); - new (frozen->records + (frozen->index ++)) SiteRecord(s, v); + init(new (frozen->records + (frozen->index ++)) SiteRecord, s, v); } void @@ -5745,7 +5720,7 @@ class Block { Block* block(Context* c, Event* head) { - return new (c->zone->allocate(sizeof(Block))) Block(head); + return new(c->zone) Block(head); } void @@ -5881,17 +5856,6 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) c->firstBlock = firstBlock; } -unsigned -count(Stack* s) -{ - unsigned c = 0; - while (s) { - ++ c; - s = s->next; - } - return c; -} - void restore(Context* c, ForkState* state) { @@ -6056,8 +6020,7 @@ class MyCompiler: public Compiler { } virtual Subroutine* startSubroutine() { - return c.subroutine = new (c.zone->allocate(sizeof(MySubroutine))) - MySubroutine; + return c.subroutine = new(c.zone) MySubroutine; } virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address) { @@ -6198,7 +6161,7 @@ class MyCompiler: public Compiler { } virtual Promise* machineIp(unsigned logicalIp) { - return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(&c, logicalIp); + return new(c.zone) IpPromise(&c, logicalIp); } virtual Promise* poolAppend(intptr_t value) { @@ -6206,12 +6169,9 @@ class MyCompiler: public Compiler { } virtual Promise* poolAppendPromise(Promise* value) { - Promise* p = new (c.zone->allocate(sizeof(PoolPromise))) - PoolPromise(&c, c.constantCount); + Promise* p = new(c.zone) PoolPromise(&c, c.constantCount); - ConstantPoolNode* constant - = new (c.zone->allocate(sizeof(ConstantPoolNode))) - ConstantPoolNode(value); + ConstantPoolNode* constant = new (c.zone) ConstantPoolNode(value); if (c.firstConstant) { c.lastConstant->next = constant; @@ -6902,16 +6862,20 @@ class MyCompiler: public Compiler { return result; } + virtual void trap() { + appendOperation(&c, Trap); + } + virtual void loadBarrier() { - appendBarrier(&c, LoadBarrier); + appendOperation(&c, LoadBarrier); } virtual void storeStoreBarrier() { - appendBarrier(&c, StoreStoreBarrier); + appendOperation(&c, StoreStoreBarrier); } virtual void storeLoadBarrier() { - appendBarrier(&c, StoreLoadBarrier); + appendOperation(&c, StoreLoadBarrier); } virtual void compile(uintptr_t stackOverflowHandler, @@ -6992,8 +6956,7 @@ Compiler* makeCompiler(System* system, Assembler* assembler, Zone* zone, Compiler::Client* client) { - return new (zone->allocate(sizeof(local::MyCompiler))) - local::MyCompiler(system, assembler, zone, client); + return new(zone) local::MyCompiler(system, assembler, zone, client); } } // namespace vm diff --git a/src/compiler.h b/src/compiler.h index 85deed9473..e66c69a67c 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -184,6 +184,8 @@ class Compiler { virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) = 0; virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) = 0; + virtual void trap() = 0; + virtual void loadBarrier() = 0; virtual void storeStoreBarrier() = 0; virtual void storeLoadBarrier() = 0; diff --git a/src/continuations-x86.S b/src/continuations-x86.S index eea08ed21e..6cb67e8c09 100644 --- a/src/continuations-x86.S +++ b/src/continuations-x86.S @@ -10,11 +10,11 @@ #ifdef __x86_64__ -#define THREAD_CONTINUATION 2240 +#define THREAD_CONTINUATION 2248 #define THREAD_EXCEPTION 80 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2248 -#define THREAD_EXCEPTION_OFFSET 2256 -#define THREAD_EXCEPTION_HANDLER 2264 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2256 +#define THREAD_EXCEPTION_OFFSET 2264 +#define THREAD_EXCEPTION_HANDLER 2272 #define CONTINUATION_NEXT 8 #define CONTINUATION_ADDRESS 32 @@ -91,11 +91,11 @@ LOCAL(vmInvoke_exit): #elif defined __i386__ -#define THREAD_CONTINUATION 2156 +#define THREAD_CONTINUATION 2160 #define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2160 -#define THREAD_EXCEPTION_OFFSET 2164 -#define THREAD_EXCEPTION_HANDLER 2168 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2164 +#define THREAD_EXCEPTION_OFFSET 2168 +#define THREAD_EXCEPTION_HANDLER 2172 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 diff --git a/src/environment.h b/src/environment.h new file mode 100644 index 0000000000..045eb2642d --- /dev/null +++ b/src/environment.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2008-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. */ + +#ifndef AVIAN_ENVIRONMENT_H +#define AVIAN_ENVIRONMENT_H + +#ifndef AVIAN_TARGET_PLATFORM +#error build system should have defined AVIAN_TARGET_PLATFORM +#endif + +#ifndef AVIAN_TARGET_ARCH +#error build system should have defined AVIAN_TARGET_ARCH +#endif + +#define AVIAN_PLATFORM_UNKNOWN 0 +#define AVIAN_PLATFORM_LINUX 1 +#define AVIAN_PLATFORM_WINDOWS 2 +#define AVIAN_PLATFORM_DARWIN 3 + +#define AVIAN_ARCH_UNKNOWN 0 +#define AVIAN_ARCH_X86 (1 << 8) +#define AVIAN_ARCH_X86_64 (2 << 8) +#define AVIAN_ARCH_ARM (3 << 8) +#define AVIAN_ARCH_POWERPC (4 << 8) + +#endif \ No newline at end of file diff --git a/src/finder.cpp b/src/finder.cpp index f53738e9f4..ba8aef75f4 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -12,6 +12,7 @@ #include "system.h" #include "tokenizer.h" #include "finder.h" +#include "lzma.h" using namespace vm; @@ -173,11 +174,12 @@ class DirectoryElement: public Element { class PointerRegion: public System::Region { public: PointerRegion(System* s, Allocator* allocator, const uint8_t* start, - size_t length): + size_t length, bool freePointer = false): s(s), allocator(allocator), start_(start), - length_(length) + length_(length), + freePointer(freePointer) { } virtual const uint8_t* start() { @@ -189,6 +191,9 @@ class PointerRegion: public System::Region { } virtual void dispose() { + if (freePointer) { + allocator->free(start_, length_); + } allocator->free(this, sizeof(*this)); } @@ -196,6 +201,7 @@ class PointerRegion: public System::Region { Allocator* allocator; const uint8_t* start_; size_t length_; + bool freePointer; }; class DataRegion: public System::Region { @@ -448,6 +454,7 @@ class JarElement: public Element { unsigned jarLength): s(s), allocator(allocator), + originalName(0), name(0), urlPrefix_(name ? append(allocator, "jar:file:", name, "!/") : 0), sourceUrl_(name ? append(allocator, "file:", name) : 0), @@ -517,12 +524,14 @@ class JarElement: public Element { } virtual void dispose(unsigned size) { - if (originalName != name) { - allocator->free(originalName, strlen(originalName) + 1); + if (name) { + if (originalName != name) { + allocator->free(originalName, strlen(originalName) + 1); + } + allocator->free(name, strlen(name) + 1); + allocator->free(urlPrefix_, strlen(urlPrefix_) + 1); + allocator->free(sourceUrl_, strlen(sourceUrl_) + 1); } - allocator->free(name, strlen(name) + 1); - allocator->free(urlPrefix_, strlen(urlPrefix_) + 1); - allocator->free(sourceUrl_, strlen(sourceUrl_) + 1); if (index) { index->dispose(); } @@ -553,7 +562,10 @@ class BuiltinElement: public JarElement { virtual void init() { if (index == 0) { if (s->success(s->load(&library, libraryName))) { - void* p = library->resolve(name); + bool lzma = strncmp("lzma:", name, 5) == 0; + const char* symbolName = lzma ? name + 5 : name; + + void* p = library->resolve(symbolName); if (p) { uint8_t* (*function)(unsigned*); memcpy(&function, &p, BytesPerWord); @@ -561,10 +573,29 @@ class BuiltinElement: public JarElement { unsigned size; uint8_t* data = function(&size); if (data) { + bool freePointer; + if (lzma) { +#ifdef AVIAN_USE_LZMA + unsigned outSize; + data = decodeLZMA(s, allocator, data, size, &outSize); + size = outSize; + freePointer = true; +#else + abort(s); +#endif + } else { + freePointer = false; + } region = new (allocator->allocate(sizeof(PointerRegion))) - PointerRegion(s, allocator, data, size); + PointerRegion(s, allocator, data, size, freePointer); index = JarIndex::open(s, allocator, region); + } else if (DebugFind) { + fprintf(stderr, "%s in %s returned null\n", symbolName, + libraryName); } + } else if (DebugFind) { + fprintf(stderr, "unable to find %s in %s\n", symbolName, + libraryName); } } } @@ -906,7 +937,9 @@ class MyFinder: public Finder { e = e->next; t->dispose(); } - allocator->free(pathString, strlen(pathString) + 1); + if (pathString) { + allocator->free(pathString, strlen(pathString) + 1); + } allocator->free(this, sizeof(*this)); } diff --git a/src/finder.h b/src/finder.h index e784fe6e9a..f4582417fa 100644 --- a/src/finder.h +++ b/src/finder.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/heap.cpp b/src/heap.cpp index b99de70de7..ed5d8777d4 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -60,7 +60,6 @@ void NO_RETURN abort(Context*); void assert(Context*, bool); #endif -System* system(Context*); void* tryAllocate(Context* c, unsigned size); void* allocate(Context* c, unsigned size); void free(Context* c, const void* p, unsigned size); @@ -689,12 +688,6 @@ class Context { int64_t totalTime; }; -inline System* -system(Context* c) -{ - return c->system; -} - const char* segment(Context* c, void* p) { diff --git a/src/heap.h b/src/heap.h index 838d88786c..875b4a5cbc 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/heapdump.cpp b/src/heapdump.cpp index 2f70e80c5f..da283e61a1 100644 --- a/src/heapdump.cpp +++ b/src/heapdump.cpp @@ -34,7 +34,11 @@ write1(FILE* out, uint8_t v) void write4(FILE* out, uint32_t v) { - uint8_t b[] = { v >> 24, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF }; + uint8_t b[] = { static_cast( v >> 24 ), + static_cast((v >> 16) & 0xFF), + static_cast((v >> 8) & 0xFF), + static_cast( v & 0xFF) }; + size_t n UNUSED = fwrite(b, 4, 1, out); } diff --git a/src/heapwalk.cpp b/src/heapwalk.cpp index a34baf96dc..811382a825 100644 --- a/src/heapwalk.cpp +++ b/src/heapwalk.cpp @@ -231,16 +231,6 @@ get(object o, unsigned offsetInWords) (mask(cast(o, offsetInWords * BytesPerWord))); } -unsigned -objectSize(Thread* t, object o) -{ - unsigned n = baseSize(t, o, objectClass(t, o)); - if (objectExtended(t, o)) { - ++ n; - } - return n; -} - unsigned walk(Context* c, HeapVisitor* v, object p) { diff --git a/src/interpret.cpp b/src/interpret.cpp index 6f3c853ec6..10cfb2c33e 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -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,9 +156,9 @@ 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); + return reinterpret_cast(t->stack[(index * 2) + 1]); } inline uint32_t @@ -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); } @@ -2706,7 +2706,8 @@ interpret(Thread* t) while (true) { bool success = false; - uintptr_t arguments[] = { base, reinterpret_cast(&success) }; + uintptr_t arguments[] = { static_cast(base), + reinterpret_cast(&success) }; uint64_t r = run(t, interpret2, arguments); if (success) { @@ -2757,6 +2758,39 @@ pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects, } } +void +pushArguments(Thread* t, object this_, const char* spec, + const jvalue* arguments) +{ + if (this_) { + pushObject(t, this_); + } + + unsigned index = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': { + jobject v = arguments[index++].l; + pushObject(t, v ? *v : 0); + } break; + + case 'J': + case 'D': + pushLong(t, arguments[index++].j); + break; + + case 'F': { + pushFloat(t, arguments[index++].d); + } break; + + default: + pushInt(t, arguments[index++].i); + break; + } + } +} + void pushArguments(Thread* t, object this_, const char* spec, object a) { @@ -2879,7 +2913,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 +3030,31 @@ 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); + } + + const char* spec = reinterpret_cast + (&byteArrayBody(t, methodSpec(t, method), 0)); + pushArguments(t, this_, spec, arguments); + + return ::invoke(t, method); + } + + virtual object + invokeArray(vm::Thread* vmt, object method, object this_, + const jvalue* arguments) + { + Thread* t = static_cast(vmt); + + assert(t, t->state == Thread::ActiveState + or t->state == Thread::ExclusiveState); + + assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); + + if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 + > stackSizeInWords(t) / 2)) { throwNew(t, Machine::StackOverflowErrorType); } @@ -3020,7 +3078,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 +3101,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); } @@ -3067,6 +3125,10 @@ class MyProcessor: public Processor { abort(s); } + virtual void addCompilationHandler(CompilationHandler*) { + abort(s); + } + virtual void compileMethod(vm::Thread*, Zone*, object*, object*, DelayedPromise**, object, OffsetResolver*) { diff --git a/src/jnienv.cpp b/src/jnienv.cpp index f815497078..5846bea7b2 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -252,7 +252,8 @@ NewString(Thread* t, const jchar* chars, jsize size) { if (chars == 0) return 0; - uintptr_t arguments[] = { reinterpret_cast(chars), size }; + uintptr_t arguments[] = { reinterpret_cast(chars), + static_cast(size) }; return reinterpret_cast(run(t, newString, arguments)); } @@ -311,7 +312,7 @@ DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer, { uintptr_t arguments[] = { reinterpret_cast(loader), reinterpret_cast(buffer), - length }; + static_cast(length) }; return reinterpret_cast(run(t, defineClass, arguments)); } @@ -630,17 +631,41 @@ NewObject(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +newObjectA(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + object o = make(t, jclassVmClass(t, *c)); + PROTECT(t, o); + + t->m->processor->invokeArray(t, getMethod(t, m), o, a); + + return reinterpret_cast(makeLocalReference(t, o)); +} + +jobject JNICALL +NewObjectA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return reinterpret_cast(run(t, newObjectA, arguments)); +} + uint64_t callObjectMethodV(Thread* t, uintptr_t* arguments) { - jobject o = reinterpret_cast(arguments[0]); + jobject o = reinterpret_cast(arguments[0]); jmethodID m = arguments[1]; va_list* a = reinterpret_cast(arguments[2]); - object method = getMethod(t, m); return reinterpret_cast (makeLocalReference - (t, t->m->processor->invokeList(t, method, *o, true, *a))); + (t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a))); } jobject JNICALL @@ -666,15 +691,37 @@ CallObjectMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +uint64_t +callObjectMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + return reinterpret_cast + (makeLocalReference + (t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a))); +} + +jobject JNICALL +CallObjectMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return reinterpret_cast(run(t, callObjectMethodA, arguments)); +} + uint64_t callIntMethodV(Thread* t, uintptr_t* arguments) { - jobject o = reinterpret_cast(arguments[0]); + jobject o = reinterpret_cast(arguments[0]); jmethodID m = arguments[1]; va_list* a = reinterpret_cast(arguments[2]); - object method = getMethod(t, m); - return intValue(t, t->m->processor->invokeList(t, method, *o, true, *a)); + return intValue + (t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a)); } jboolean JNICALL @@ -700,6 +747,27 @@ CallBooleanMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +uint64_t +callIntMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + return intValue + (t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a)); +} + +jboolean JNICALL +CallBooleanMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments) != 0; +} + jbyte JNICALL CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -723,6 +791,16 @@ CallByteMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jbyte JNICALL +CallByteMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments); +} + jchar JNICALL CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -746,6 +824,16 @@ CallCharMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jchar JNICALL +CallCharMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments); +} + jshort JNICALL CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -769,6 +857,16 @@ CallShortMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jshort JNICALL +CallShortMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments); +} + jint JNICALL CallIntMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -792,15 +890,25 @@ CallIntMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jint JNICALL +CallIntMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments); +} + uint64_t callLongMethodV(Thread* t, uintptr_t* arguments) { - jobject o = reinterpret_cast(arguments[0]); + jobject o = reinterpret_cast(arguments[0]); jmethodID m = arguments[1]; va_list* a = reinterpret_cast(arguments[2]); - object method = getMethod(t, m); - return longValue(t, t->m->processor->invokeList(t, method, *o, true, *a)); + return longValue + (t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a)); } jlong JNICALL @@ -826,6 +934,27 @@ CallLongMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +uint64_t +callLongMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + return longValue + (t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a)); +} + +jlong JNICALL +CallLongMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callLongMethodA, arguments); +} + jfloat JNICALL CallFloatMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -849,6 +978,16 @@ CallFloatMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jfloat JNICALL +CallFloatMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return bitsToFloat(run(t, callIntMethodA, arguments)); +} + jdouble JNICALL CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -872,15 +1011,24 @@ CallDoubleMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jdouble JNICALL +CallDoubleMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return bitsToDouble(run(t, callLongMethodA, arguments)); +} + uint64_t callVoidMethodV(Thread* t, uintptr_t* arguments) { - jobject o = reinterpret_cast(arguments[0]); + jobject o = reinterpret_cast(arguments[0]); jmethodID m = arguments[1]; va_list* a = reinterpret_cast(arguments[2]); - object method = getMethod(t, m); - t->m->processor->invokeList(t, method, *o, true, *a); + t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a); return 0; } @@ -906,6 +1054,28 @@ CallVoidMethod(Thread* t, jobject o, jmethodID m, ...) va_end(a); } +uint64_t +callVoidMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + t->m->processor->invokeArray(t, getMethod(t, m), *o, a); + + return 0; +} + +void JNICALL +CallVoidMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + run(t, callVoidMethodA, arguments); +} + object getStaticMethod(Thread* t, jmethodID m) { @@ -950,6 +1120,25 @@ CallStaticObjectMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callStaticObjectMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + return reinterpret_cast + (makeLocalReference + (t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a))); +} + +jobject JNICALL +CallStaticObjectMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return reinterpret_cast(run(t, callStaticObjectMethodA, arguments)); +} + uint64_t callStaticIntMethodV(Thread* t, uintptr_t* arguments) { @@ -981,6 +1170,24 @@ CallStaticBooleanMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callStaticIntMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + return intValue + (t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a)); +} + +jboolean JNICALL +CallStaticBooleanMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments) != 0; +} + jbyte JNICALL CallStaticByteMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1002,6 +1209,14 @@ CallStaticByteMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jbyte JNICALL +CallStaticByteMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments); +} + jchar JNICALL CallStaticCharMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1023,6 +1238,14 @@ CallStaticCharMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jchar JNICALL +CallStaticCharMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments); +} + jshort JNICALL CallStaticShortMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1044,6 +1267,14 @@ CallStaticShortMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jshort JNICALL +CallStaticShortMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments); +} + jint JNICALL CallStaticIntMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1065,6 +1296,14 @@ CallStaticIntMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jint JNICALL +CallStaticIntMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments); +} + uint64_t callStaticLongMethodV(Thread* t, uintptr_t* arguments) { @@ -1096,6 +1335,24 @@ CallStaticLongMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callStaticLongMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + return longValue + (t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a)); +} + +jlong JNICALL +CallStaticLongMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticLongMethodA, arguments); +} + jfloat JNICALL CallStaticFloatMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1117,6 +1374,14 @@ CallStaticFloatMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jfloat JNICALL +CallStaticFloatMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return bitsToFloat(run(t, callStaticIntMethodA, arguments)); +} + jdouble JNICALL CallStaticDoubleMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1138,6 +1403,14 @@ CallStaticDoubleMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jdouble JNICALL +CallStaticDoubleMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return bitsToDouble(run(t, callStaticLongMethodA, arguments)); +} + uint64_t callStaticVoidMethodV(Thread* t, uintptr_t* arguments) { @@ -1168,6 +1441,25 @@ CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...) va_end(a); } +uint64_t +callStaticVoidMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a); + + return 0; +} + +void JNICALL +CallStaticVoidMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + run(t, callStaticVoidMethodA, arguments); +} + jint fieldID(Thread* t, object field) { @@ -1495,7 +1787,7 @@ SetByteField(Thread* t, jobject o, jfieldID field, jbyte v) { uintptr_t arguments[] = { reinterpret_cast(o), field, - v }; + static_cast(v) }; run(t, setByteField, arguments); } @@ -1545,7 +1837,7 @@ SetShortField(Thread* t, jobject o, jfieldID field, jshort v) { uintptr_t arguments[] = { reinterpret_cast(o), field, - v }; + static_cast(v) }; run(t, setShortField, arguments); } @@ -1570,7 +1862,7 @@ SetIntField(Thread* t, jobject o, jfieldID field, jint v) { uintptr_t arguments[] = { reinterpret_cast(o), field, - v }; + static_cast(v) }; run(t, setIntField, arguments); } @@ -1975,7 +2267,7 @@ SetStaticByteField(Thread* t, jobject c, jfieldID field, jbyte v) { uintptr_t arguments[] = { reinterpret_cast(c), field, - v }; + static_cast(v) }; run(t, setStaticByteField, arguments); } @@ -2033,7 +2325,7 @@ SetStaticShortField(Thread* t, jobject c, jfieldID field, jshort v) { uintptr_t arguments[] = { reinterpret_cast(c), field, - v }; + static_cast(v) }; run(t, setStaticShortField, arguments); } @@ -2062,7 +2354,7 @@ SetStaticIntField(Thread* t, jobject c, jfieldID field, jint v) { uintptr_t arguments[] = { reinterpret_cast(c), field, - v }; + static_cast(v) }; run(t, setStaticIntField, arguments); } @@ -2261,7 +2553,7 @@ newObjectArray(Thread* t, uintptr_t* arguments) jobjectArray JNICALL NewObjectArray(Thread* t, jsize length, jclass class_, jobject init) { - uintptr_t arguments[] = { length, + uintptr_t arguments[] = { static_cast(length), reinterpret_cast(class_), reinterpret_cast(init) }; @@ -2302,7 +2594,7 @@ NewBooleanArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeBooleanArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2318,7 +2610,7 @@ NewByteArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeByteArray0)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2328,7 +2620,7 @@ NewCharArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeCharArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2338,7 +2630,7 @@ NewShortArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeShortArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2348,7 +2640,7 @@ NewIntArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeIntArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2358,7 +2650,7 @@ NewLongArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeLongArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2368,7 +2660,7 @@ NewFloatArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeFloatArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2378,7 +2670,7 @@ NewDoubleArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeDoubleArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2905,7 +3197,7 @@ RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods, { uintptr_t arguments[] = { reinterpret_cast(c), reinterpret_cast(methods), - methodCount }; + static_cast(methodCount) }; return run(t, registerNatives, arguments) ? 0 : -1; } @@ -3104,47 +3396,68 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) envTable->GetFieldID = local::GetFieldID; envTable->GetMethodID = local::GetMethodID; envTable->GetStaticMethodID = local::GetStaticMethodID; - envTable->NewObject = local::NewObject; envTable->NewObjectV = local::NewObjectV; + envTable->NewObjectA = local::NewObjectA; + envTable->NewObject = local::NewObject; envTable->CallObjectMethodV = local::CallObjectMethodV; + envTable->CallObjectMethodA = local::CallObjectMethodA; envTable->CallObjectMethod = local::CallObjectMethod; envTable->CallBooleanMethodV = local::CallBooleanMethodV; + envTable->CallBooleanMethodA = local::CallBooleanMethodA; envTable->CallBooleanMethod = local::CallBooleanMethod; envTable->CallByteMethodV = local::CallByteMethodV; + envTable->CallByteMethodA = local::CallByteMethodA; envTable->CallByteMethod = local::CallByteMethod; envTable->CallCharMethodV = local::CallCharMethodV; + envTable->CallCharMethodA = local::CallCharMethodA; envTable->CallCharMethod = local::CallCharMethod; envTable->CallShortMethodV = local::CallShortMethodV; + envTable->CallShortMethodA = local::CallShortMethodA; envTable->CallShortMethod = local::CallShortMethod; envTable->CallIntMethodV = local::CallIntMethodV; + envTable->CallIntMethodA = local::CallIntMethodA; envTable->CallIntMethod = local::CallIntMethod; envTable->CallLongMethodV = local::CallLongMethodV; + envTable->CallLongMethodA = local::CallLongMethodA; envTable->CallLongMethod = local::CallLongMethod; envTable->CallFloatMethodV = local::CallFloatMethodV; + envTable->CallFloatMethodA = local::CallFloatMethodA; envTable->CallFloatMethod = local::CallFloatMethod; envTable->CallDoubleMethodV = local::CallDoubleMethodV; + envTable->CallDoubleMethodA = local::CallDoubleMethodA; envTable->CallDoubleMethod = local::CallDoubleMethod; envTable->CallVoidMethodV = local::CallVoidMethodV; + envTable->CallVoidMethodA = local::CallVoidMethodA; envTable->CallVoidMethod = local::CallVoidMethod; envTable->CallStaticObjectMethodV = local::CallStaticObjectMethodV; + envTable->CallStaticObjectMethodA = local::CallStaticObjectMethodA; envTable->CallStaticObjectMethod = local::CallStaticObjectMethod; envTable->CallStaticBooleanMethodV = local::CallStaticBooleanMethodV; + envTable->CallStaticBooleanMethodA = local::CallStaticBooleanMethodA; envTable->CallStaticBooleanMethod = local::CallStaticBooleanMethod; envTable->CallStaticByteMethodV = local::CallStaticByteMethodV; + envTable->CallStaticByteMethodA = local::CallStaticByteMethodA; envTable->CallStaticByteMethod = local::CallStaticByteMethod; envTable->CallStaticCharMethodV = local::CallStaticCharMethodV; + envTable->CallStaticCharMethodA = local::CallStaticCharMethodA; envTable->CallStaticCharMethod = local::CallStaticCharMethod; envTable->CallStaticShortMethodV = local::CallStaticShortMethodV; + envTable->CallStaticShortMethodA = local::CallStaticShortMethodA; envTable->CallStaticShortMethod = local::CallStaticShortMethod; envTable->CallStaticIntMethodV = local::CallStaticIntMethodV; + envTable->CallStaticIntMethodA = local::CallStaticIntMethodA; envTable->CallStaticIntMethod = local::CallStaticIntMethod; envTable->CallStaticLongMethodV = local::CallStaticLongMethodV; + envTable->CallStaticLongMethodA = local::CallStaticLongMethodA; envTable->CallStaticLongMethod = local::CallStaticLongMethod; envTable->CallStaticFloatMethodV = local::CallStaticFloatMethodV; + envTable->CallStaticFloatMethodA = local::CallStaticFloatMethodA; envTable->CallStaticFloatMethod = local::CallStaticFloatMethod; envTable->CallStaticDoubleMethodV = local::CallStaticDoubleMethodV; + envTable->CallStaticDoubleMethodA = local::CallStaticDoubleMethodA; envTable->CallStaticDoubleMethod = local::CallStaticDoubleMethod; envTable->CallStaticVoidMethodV = local::CallStaticVoidMethodV; + envTable->CallStaticVoidMethodA = local::CallStaticVoidMethodA; envTable->CallStaticVoidMethod = local::CallStaticVoidMethod; envTable->GetStaticFieldID = local::GetStaticFieldID; envTable->GetObjectField = local::GetObjectField; @@ -3269,6 +3582,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 +3599,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 +3643,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 +3695,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/lzma-decode.cpp b/src/lzma-decode.cpp new file mode 100644 index 0000000000..874e6f584d --- /dev/null +++ b/src/lzma-decode.cpp @@ -0,0 +1,61 @@ +/* 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. */ + +#include "lzma-util.h" +#include "C/LzmaDec.h" + +using namespace vm; + +namespace { + +int32_t +read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) + | (static_cast(in[0]) ); +} + +} // namespace + +namespace vm { + +uint8_t* +decodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + int32_t outSize32 = read4(in + PropHeaderSize); + expect(s, outSize32 >= 0); + SizeT outSizeT = outSize32; + + uint8_t* out = static_cast(a->allocate(outSize32)); + + SizeT inSizeT = inSize; + LzmaAllocator allocator(a); + + ELzmaStatus status; + int result = LzmaDecode + (out, &outSizeT, in + HeaderSize, &inSizeT, in, PropHeaderSize, + LZMA_FINISH_END, &status, &(allocator.allocator)); + + expect(s, result == SZ_OK); + expect(s, status == LZMA_STATUS_FINISHED_WITH_MARK); + + *outSize = outSize32; + + return out; +} + +} // namespace vm + diff --git a/src/lzma-encode.cpp b/src/lzma-encode.cpp new file mode 100644 index 0000000000..cc7f8ad178 --- /dev/null +++ b/src/lzma-encode.cpp @@ -0,0 +1,71 @@ +/* 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. */ + +#include "lzma-util.h" +#include "C/LzmaEnc.h" + +using namespace vm; + +namespace { + +SRes +myProgress(void*, UInt64, UInt64) +{ + return SZ_OK; +} + +} // namespace + +namespace vm { + +uint8_t* +encodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + unsigned bufferSize = inSize * 2; + + uint8_t* buffer = static_cast(a->allocate(bufferSize)); + + LzmaAllocator allocator(a); + + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = 9; + props.writeEndMark = 1; + + ICompressProgress progress = { myProgress }; + + SizeT propsSize = PropHeaderSize; + + int32_t inSize32 = inSize; + memcpy(buffer + PropHeaderSize, &inSize32, 4); + + SizeT outSizeT = bufferSize; + int result = LzmaEncode + (buffer + HeaderSize, &outSizeT, in, inSize, &props, buffer, + &propsSize, 1, &progress, &(allocator.allocator), &(allocator.allocator)); + + expect(s, result == SZ_OK); + + *outSize = outSizeT + HeaderSize; + + uint8_t* out = static_cast(a->allocate(*outSize)); + memcpy(out, buffer, *outSize); + + a->free(buffer, bufferSize); + + return out; +} + +} // namespace vm + diff --git a/src/lzma-util.h b/src/lzma-util.h new file mode 100644 index 0000000000..e7fc3093a0 --- /dev/null +++ b/src/lzma-util.h @@ -0,0 +1,53 @@ +/* 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. */ + +#ifndef LZMA_UTIL_H +#define LZMA_UTIL_H + +#include "lzma.h" +#include "C/Types.h" +#include "system.h" +#include "allocator.h" + +namespace vm { + +const unsigned Padding = 16; + +class LzmaAllocator { + public: + LzmaAllocator(Allocator* a): a(a) { + allocator.Alloc = allocate; + allocator.Free = free; + } + + ISzAlloc allocator; + Allocator* a; + + static void* allocate(void* allocator, size_t size) { + uint8_t* p = static_cast + (static_cast(allocator)->a->allocate(size + Padding)); + int32_t size32 = size; + memcpy(p, &size32, 4); + return p + Padding; + } + + static void free(void* allocator, void* address) { + if (address) { + void* p = static_cast(address) - Padding; + int32_t size32; + memcpy(&size32, p, 4); + static_cast(allocator)->a->free(p, size32 + Padding); + } + } +}; + +} // namespace vm + +#endif // LZMA_UTIL_H diff --git a/src/lzma.h b/src/lzma.h new file mode 100644 index 0000000000..5e6ba35a82 --- /dev/null +++ b/src/lzma.h @@ -0,0 +1,29 @@ +/* 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. */ + +#ifndef LZMA_H +#define LZMA_H + +#include "system.h" +#include "allocator.h" + +namespace vm { + +uint8_t* +decodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize); + +uint8_t* +encodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize); + +} // namespace vm + +#endif // LZMA_H diff --git a/src/lzma/load.cpp b/src/lzma/load.cpp new file mode 100644 index 0000000000..4a68466772 --- /dev/null +++ b/src/lzma/load.cpp @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "C/LzmaDec.h" + +#if (defined __MINGW32__) || (defined _MSC_VER) +# define EXPORT __declspec(dllexport) +# include +# define open _open +# define write _write +# define close _close +# ifdef _MSC_VER +# define S_IRWXU (_S_IREAD | _S_IWRITE) +# define and && +# endif +#else +# define EXPORT __attribute__ ((visibility("default"))) +# include +# include +# include +# define O_BINARY 0 +#endif + +#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) +# define SYMBOL(x) binary_exe_##x +#else +# define SYMBOL(x) _binary_exe_##x +#endif + +extern "C" { + + extern const uint8_t SYMBOL(start)[]; + extern const uint8_t SYMBOL(end)[]; + +} // extern "C" + +namespace { + +int32_t +read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) + | (static_cast(in[0]) ); +} + +void* +myAllocate(void*, size_t size) +{ + return malloc(size); +} + +void +myFree(void*, void* address) +{ + free(address); +} + +#if (defined __MINGW32__) || (defined _MSC_VER) + +void* +openLibrary(const char* name) +{ + return LoadLibrary(name); +} + +void* +librarySymbol(void* library, const char* name) +{ + void* address; + FARPROC p = GetProcAddress(static_cast(library), name); + memcpy(&address, &p, sizeof(void*)); + return address; +} + +const char* +libraryError(void*) +{ + return "unknown error"; +} + +const char* +temporaryFileName(char* buffer, unsigned size) +{ + unsigned c = GetTempPathA(size, buffer); + if (c) { + if (GetTempFileNameA(buffer, "223", 0, buffer + c)) { + DeleteFileA(buffer + c); + return buffer + c; + } + } + return 0; +} + +#else + +void* +openLibrary(const char* name) +{ + return dlopen(name, RTLD_LAZY | RTLD_LOCAL); +} + +void* +librarySymbol(void* library, const char* name) +{ + return dlsym(library, name); +} + +const char* +libraryError(void*) +{ + return dlerror(); +} + +const char* +temporaryFileName(char* buffer, unsigned) +{ + return tmpnam(buffer); +} + +#endif + +} // namespace + +int +main(int ac, const char** av) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + SizeT inSize = SYMBOL(end) - SYMBOL(start); + + int32_t outSize32 = read4(SYMBOL(start) + PropHeaderSize); + SizeT outSize = outSize32; + + uint8_t* out = static_cast(malloc(outSize)); + if (out) { + ISzAlloc allocator = { myAllocate, myFree }; + ELzmaStatus status = LZMA_STATUS_NOT_SPECIFIED; + + if (SZ_OK == LzmaDecode + (out, &outSize, SYMBOL(start) + HeaderSize, &inSize, SYMBOL(start), + PropHeaderSize, LZMA_FINISH_END, &status, &allocator)) + { + const unsigned BufferSize = 1024; + char buffer[BufferSize]; + const char* name = temporaryFileName(buffer, BufferSize); + if (name) { + int file = open(name, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, S_IRWXU); + if (file != -1) { + SizeT result = write(file, out, outSize); + free(out); + + if (close(file) == 0 and outSize == result) { + void* library = openLibrary(name); + unlink(name); + + if (library) { + void* main = librarySymbol(library, "avianMain"); + if (main) { + int (*mainFunction)(const char*, int, const char**); + memcpy(&mainFunction, &main, sizeof(void*)); + return mainFunction(name, ac, av); + } else { + fprintf(stderr, "unable to find main in %s", name); + } + } else { + fprintf(stderr, "unable to load %s: %s\n", name, + libraryError(library)); + } + } else { + unlink(name); + + fprintf(stderr, "close or write failed; tried %d, got %d; %s\n", + static_cast(outSize), static_cast(result), + strerror(errno)); + } + } else { + fprintf(stderr, "unable to open %s\n", name); + } + } else { + fprintf(stderr, "unable to make temporary file name\n"); + } + } else { + fprintf(stderr, "unable to decode LZMA data\n"); + } + } else { + fprintf(stderr, "unable to allocate buffer of size %d\n", + static_cast(outSize)); + } + + return -1; +} diff --git a/src/lzma/main.cpp b/src/lzma/main.cpp new file mode 100644 index 0000000000..f6baa39bb9 --- /dev/null +++ b/src/lzma/main.cpp @@ -0,0 +1,190 @@ +#include +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#include +#endif +#include + +#include "LzmaEnc.h" +#include "LzmaDec.h" + +namespace { + +int32_t +read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) + | (static_cast(in[0]) ); +} + +void* +myAllocate(void*, size_t size) +{ + return malloc(size); +} + +void +myFree(void*, void* address) +{ + free(address); +} + +SRes +myProgress(void*, UInt64, UInt64) +{ + return SZ_OK; +} + +void +usageAndExit(const char* program) +{ + fprintf(stderr, + "usage: %s {encode|decode} " + "[]", program); + exit(-1); +} + +} // namespace + +int +main(int argc, const char** argv) +{ + if (argc < 4 or argc > 5) { + usageAndExit(argv[0]); + } + + bool encode = strcmp(argv[1], "encode") == 0; + + uint8_t* data = 0; + unsigned size; + int fd = open(argv[2], O_RDONLY); + if (fd != -1) { + struct stat s; + int r = fstat(fd, &s); + if (r != -1) { +#ifdef WIN32 + HANDLE fm; + HANDLE h = (HANDLE) _get_osfhandle (fd); + + fm = CreateFileMapping( + h, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + data = static_cast(MapViewOfFile( + fm, + FILE_MAP_READ, + 0, + 0, + s.st_size)); + + CloseHandle(fm); +#else + data = static_cast + (mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0)); +#endif + size = s.st_size; + } + close(fd); + } + + bool success = false; + + if (data) { + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + SizeT outSize; + if (encode) { + outSize = size * 2; + } else { + int32_t outSize32 = read4(data + PropHeaderSize); + if (outSize32 >= 0) { + outSize = outSize32; + } else if (argc == 5) { + outSize = atoi(argv[4]); + } else { + outSize = -1; + } + } + + if (outSize >= 0) { + uint8_t* out = static_cast(malloc(outSize)); + if (out) { + SizeT inSize = size; + ISzAlloc allocator = { myAllocate, myFree }; + ELzmaStatus status = LZMA_STATUS_NOT_SPECIFIED; + int result; + if (encode) { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = 9; + props.writeEndMark = 1; + + ICompressProgress progress = { myProgress }; + + SizeT propsSize = PropHeaderSize; + + int32_t inSize32 = inSize; + memcpy(out + PropHeaderSize, &inSize32, 4); + + result = LzmaEncode + (out + HeaderSize, &outSize, data, inSize, &props, out, + &propsSize, 1, &progress, &allocator, &allocator); + + outSize += HeaderSize; + } else { + result = LzmaDecode + (out, &outSize, data + HeaderSize, &inSize, data, PropHeaderSize, + LZMA_FINISH_END, &status, &allocator); + } + + if (result == SZ_OK) { + FILE* outFile = fopen(argv[3], "wb"); + + if (outFile) { + if (fwrite(out, outSize, 1, outFile) == 1) { + success = true; + } else { + fprintf(stderr, "unable to write to %s\n", argv[3]); + } + + fclose(outFile); + } else { + fprintf(stderr, "unable to open %s\n", argv[3]); + } + } else { + fprintf(stderr, "unable to %s data: result %d status %d\n", + encode ? "encode" : "decode", result, status); + } + + free(out); + } else { + fprintf(stderr, "unable to allocate output buffer\n"); + } + } else { + fprintf(stderr, "unable to determine uncompressed size\n"); + } + +#ifdef WIN32 + UnmapViewOfFile(data); +#else + munmap(data, size); +#endif + } else { + perror(argv[0]); + } + + return (success ? 0 : -1); +} diff --git a/src/machine.cpp b/src/machine.cpp index d6c249ad8d..964bfd5452 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -15,6 +15,7 @@ #include "constants.h" #include "processor.h" #include "arch.h" +#include "lzma.h" using namespace vm; @@ -35,14 +36,6 @@ atomicIncrement(uint32_t* p, int v) } #endif -bool -find(Thread* t, Thread* o) -{ - return (t == o) - or (t->peer and find(t->peer, o)) - or (t->child and find(t->child, o)); -} - void join(Thread* t, Thread* o) { @@ -56,6 +49,16 @@ join(Thread* t, Thread* o) } } +#ifndef NDEBUG + +bool +find(Thread* t, Thread* o) +{ + return (t == o) + or (t->peer and find(t->peer, o)) + or (t->child and find(t->child, o)); +} + unsigned count(Thread* t, Thread* o) { @@ -78,6 +81,8 @@ fill(Thread* t, Thread* o, Thread** array) return array; } +#endif // not NDEBUG + void dispose(Thread* t, Thread* o, bool remove) { @@ -233,8 +238,8 @@ turnOffTheLights(Thread* t) Finder* af = m->appFinder; c->dispose(); - m->dispose(); h->disposeFixies(); + m->dispose(); p->dispose(); bf->dispose(); af->dispose(); @@ -1199,9 +1204,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; @@ -1240,9 +1244,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); @@ -1727,7 +1730,7 @@ parseCode(Thread* t, Stream& s, object pool) fprintf(stderr, " code: maxStack %d maxLocals %d length %d\n", maxStack, maxLocals, length); } - object code = makeCode(t, pool, 0, 0, 0, maxStack, maxLocals, length); + object code = makeCode(t, pool, 0, 0, 0, 0, maxStack, maxLocals, length); s.read(&codeBody(t, code, 0), length); PROTECT(t, code); @@ -2666,7 +2669,7 @@ boot(Thread* t) m->processor->boot(t, 0, 0); - { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 1); + { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 0, 1); codeBody(t, bootCode, 0) = impdep1; object bootMethod = makeMethod (t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode); @@ -2850,6 +2853,38 @@ isInitializing(Thread* t, object c) return false; } +object +findInTable(Thread* t, object table, object name, object spec, + object& (*getName)(Thread*, object), + object& (*getSpec)(Thread*, object)) +{ + if (table) { + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + object o = arrayBody(t, table, i); + if (vm::strcmp(&byteArrayBody(t, getName(t, o), 0), + &byteArrayBody(t, name, 0)) == 0 and + vm::strcmp(&byteArrayBody(t, getSpec(t, o), 0), + &byteArrayBody(t, spec, 0)) == 0) + { + return o; + } + } + +// fprintf(stderr, "%s %s not in\n", +// &byteArrayBody(t, name, 0), +// &byteArrayBody(t, spec, 0)); + +// for (unsigned i = 0; i < arrayLength(t, table); ++i) { +// object o = arrayBody(t, table, i); +// fprintf(stderr, "\t%s %s\n", +// &byteArrayBody(t, getName(t, o), 0), +// &byteArrayBody(t, getSpec(t, o), 0)); +// } + } + + return 0; +} + } // namespace namespace vm { @@ -2857,7 +2892,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))) @@ -2880,6 +2916,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, liveCount(0), daemonCount(0), fixedFootprint(0), + stackSizeInBytes(stackSizeInBytes), localThread(0), stateLock(0), heapLock(0), @@ -2888,6 +2925,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, shutdownLock(0), libraries(0), errorLog(0), + bootimage(0), types(0), roots(0), finalizers(0), @@ -2943,6 +2981,10 @@ Machine::dispose() heap->free(heapPool[i], ThreadHeapSizeInBytes); } + if (bootimage) { + heap->free(bootimage, bootimageSize); + } + heap->free(arguments, sizeof(const char*) * argumentCount); heap->free(properties, sizeof(const char*) * propertyCount); @@ -2998,13 +3040,28 @@ Thread::init() uint8_t* code = 0; const char* imageFunctionName = findProperty(m, "avian.bootimage"); if (imageFunctionName) { - void* imagep = m->libraries->resolve(imageFunctionName); + bool lzma = strncmp("lzma:", imageFunctionName, 5) == 0; + const char* symbolName + = lzma ? imageFunctionName + 5 : imageFunctionName; + + void* imagep = m->libraries->resolve(symbolName); if (imagep) { - BootImage* (*imageFunction)(unsigned*); + uint8_t* (*imageFunction)(unsigned*); memcpy(&imageFunction, &imagep, BytesPerWord); unsigned size; - image = imageFunction(&size); + uint8_t* imageBytes = imageFunction(&size); + if (lzma) { +#ifdef AVIAN_USE_LZMA + m->bootimage = image = reinterpret_cast + (decodeLZMA + (m->system, m->heap, imageBytes, size, &(m->bootimageSize))); +#else + abort(this); +#endif + } else { + image = reinterpret_cast(imageBytes); + } const char* codeFunctionName = findProperty(m, "avian.codeimage"); if (codeFunctionName) { @@ -4323,35 +4380,17 @@ makeObjectArray(Thread* t, object elementClass, unsigned count) } object -findInTable(Thread* t, object table, object name, object spec, - object& (*getName)(Thread*, object), - object& (*getSpec)(Thread*, object)) +findFieldInClass(Thread* t, object class_, object name, object spec) { - if (table) { - for (unsigned i = 0; i < arrayLength(t, table); ++i) { - object o = arrayBody(t, table, i); - if (vm::strcmp(&byteArrayBody(t, getName(t, o), 0), - &byteArrayBody(t, name, 0)) == 0 and - vm::strcmp(&byteArrayBody(t, getSpec(t, o), 0), - &byteArrayBody(t, spec, 0)) == 0) - { - return o; - } - } + return findInTable + (t, classFieldTable(t, class_), name, spec, fieldName, fieldSpec); +} -// fprintf(stderr, "%s %s not in\n", -// &byteArrayBody(t, name, 0), -// &byteArrayBody(t, spec, 0)); - -// for (unsigned i = 0; i < arrayLength(t, table); ++i) { -// object o = arrayBody(t, table, i); -// fprintf(stderr, "\t%s %s\n", -// &byteArrayBody(t, getName(t, o), 0), -// &byteArrayBody(t, getSpec(t, o), 0)); -// } - } - - return 0; +object +findMethodInClass(Thread* t, object class_, object name, object spec) +{ + return findInTable + (t, classMethodTable(t, class_), name, spec, methodName, methodSpec); } object @@ -4850,7 +4889,10 @@ populateMultiArray(Thread* t, object array, int32_t* counts, PROTECT(t, class_); for (int32_t i = 0; i < counts[index]; ++i) { - object a = makeArray(t, counts[index + 1]); + object a = makeArray + (t, ceiling + (counts[index + 1] * classArrayElementSize(t, class_), BytesPerWord)); + arrayLength(t, a) = counts[index + 1]; setObjectClass(t, a, class_); set(t, array, ArrayBody + (i * BytesPerWord), a); diff --git a/src/machine.h b/src/machine.h index a52cf30a73..a9cba4024e 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -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 @@ -170,50 +167,6 @@ const unsigned ConstructorFlag = 1 << 1; typedef Machine JavaVM; typedef Thread JNIEnv; -typedef uint8_t jboolean; -typedef int8_t jbyte; -typedef uint16_t jchar; -typedef int16_t jshort; -typedef int32_t jint; -typedef int64_t jlong; -typedef float jfloat; -typedef double jdouble; - -typedef jint jsize; - -typedef object* jobject; - -typedef jobject jclass; -typedef jobject jthrowable; -typedef jobject jstring; -typedef jobject jweak; - -typedef jobject jarray; -typedef jarray jbooleanArray; -typedef jarray jbyteArray; -typedef jarray jcharArray; -typedef jarray jshortArray; -typedef jarray jintArray; -typedef jarray jlongArray; -typedef jarray jfloatArray; -typedef jarray jdoubleArray; -typedef jarray jobjectArray; - -typedef uintptr_t jfieldID; -typedef uintptr_t jmethodID; - -union jvalue { - jboolean z; - jbyte b; - jchar c; - jshort s; - jint i; - jlong j; - jfloat f; - jdouble d; - jobject l; -}; - struct JNINativeMethod { char* name; char* signature; @@ -1281,7 +1234,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 +1263,7 @@ class Machine { unsigned liveCount; unsigned daemonCount; unsigned fixedFootprint; + unsigned stackSizeInBytes; System::Local* localThread; System::Monitor* stateLock; System::Monitor* heapLock; @@ -1318,6 +1272,7 @@ class Machine { System::Monitor* shutdownLock; System::Library* libraries; FILE* errorLog; + BootImage* bootimage; object types; object roots; object finalizers; @@ -1334,6 +1289,7 @@ class Machine { JNIEnvVTable jniEnvVTable; uintptr_t* heapPool[ThreadHeapPoolSize]; unsigned heapPoolIndex; + unsigned bootimageSize; }; void @@ -1579,6 +1535,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 +1598,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); @@ -2224,6 +2189,39 @@ makeByteArray(Thread* t, const char* format, ...); object makeString(Thread* t, const char* format, ...); +#ifndef HAVE_StringOffset + +inline unsigned +stringLength(Thread* t, object string) +{ + return charArrayLength(t, stringData(t, string)); +} + +inline unsigned +stringOffset(Thread*, object) +{ + return 0; +} + +inline object +makeString(Thread* t, object data, unsigned offset, unsigned length, unsigned) +{ + if (offset == 0 and length == charArrayLength(t, data)) { + return makeString(t, data, 0, 0); + } else { + PROTECT(t, data); + + object array = makeCharArray(t, length); + + memcpy(&charArrayBody(t, array, 0), &charArrayBody(t, data, offset), + length * 2); + + return makeString(t, array, 0, 0); + } +} + +#endif // not HAVE_StringOffset + int stringUTFLength(Thread* t, object string, unsigned start, unsigned length); @@ -2591,16 +2589,7 @@ makeObjectArray(Thread* t, unsigned count) } object -findInTable(Thread* t, object table, object name, object spec, - object& (*getName)(Thread*, object), - object& (*getSpec)(Thread*, object)); - -inline object -findFieldInClass(Thread* t, object class_, object name, object spec) -{ - return findInTable - (t, classFieldTable(t, class_), name, spec, fieldName, fieldSpec); -} +findFieldInClass(Thread* t, object class_, object name, object spec); inline object findFieldInClass2(Thread* t, object class_, const char* name, const char* spec) @@ -2612,12 +2601,8 @@ findFieldInClass2(Thread* t, object class_, const char* name, const char* spec) return findFieldInClass(t, class_, n, s); } -inline object -findMethodInClass(Thread* t, object class_, object name, object spec) -{ - return findInTable - (t, classMethodTable(t, class_), name, spec, methodName, methodSpec); -} +object +findMethodInClass(Thread* t, object class_, object name, object spec); inline object makeThrowable @@ -3224,6 +3209,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..2518d60a13 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -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/jni_md.h b/src/openjdk/jni_md.h index bf5614c995..86858429d3 100644 --- a/src/openjdk/jni_md.h +++ b/src/openjdk/jni_md.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided 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..ea3f133d37 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -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; @@ -327,7 +340,8 @@ class MySystem: public System { // milliseconds) is infinity so as to avoid overflow: if (time and time < INT64_C(31536000000000000)) { int64_t then = s->now() + time; - timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 }; + timespec ts = { static_cast(then / 1000), + static_cast((then % 1000) * 1000 * 1000) }; int rv UNUSED = pthread_cond_timedwait (&(t->condition), &(t->mutex), &ts); expect(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR); @@ -343,14 +357,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 +402,7 @@ class MySystem: public System { Thread* t = first; first = first->next; if (t == last) { + expect(s, first == 0); last = 0; } diff --git a/src/powerpc.cpp b/src/powerpc.cpp index 7e315b1f35..a184c21f36 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2011, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -130,6 +130,7 @@ inline int cmpw(int ra, int rb) { return cmp(0, ra, rb); } inline int cmplw(int ra, int rb) { return cmpl(0, ra, rb); } inline int cmpwi(int ra, int i) { return cmpi(0, ra, i); } inline int cmplwi(int ra, int i) { return cmpli(0, ra, i); } +inline int trap() { return 0x7fe00008; } // todo: macro-ify } const int64_t MASK_LO32 = 0x0ffffffff; @@ -232,7 +233,7 @@ class Context { public: Context(System* s, Allocator* a, Zone* zone): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(this, 0)), + firstBlock(new(zone) MyBlock(this, 0)), lastBlock(firstBlock), jumpOffsetHead(0), jumpOffsetTail(0), constantPool(0), constantPoolCount(0) { } @@ -348,8 +349,7 @@ class Offset: public Promise { Promise* offset(Context* c) { - return new (c->zone->allocate(sizeof(Offset))) - Offset(c, c->lastBlock, c->code.length()); + return new(c->zone) Offset(c, c->lastBlock, c->code.length()); } bool @@ -467,14 +467,13 @@ void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, bool conditional) { - OffsetTask* task = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask - (c->tasks, promise, instructionOffset, conditional); + OffsetTask* task = new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, conditional); c->tasks = task; if (conditional) { - JumpOffset* offset = new (c->zone->allocate(sizeof(JumpOffset))) JumpOffset - (c->lastBlock, task, c->code.length() - c->lastBlock->offset); + JumpOffset* offset = + new(c->zone) JumpOffset(c->lastBlock, task, c->code.length() - c->lastBlock->offset); if (c->lastBlock->jumpOffsetTail) { c->lastBlock->jumpOffsetTail->next = offset; @@ -489,7 +488,7 @@ void appendJumpEvent(Context* c, MyBlock* b, unsigned offset, JumpOffset* head, JumpOffset* tail) { - JumpEvent* e = new (c->zone->allocate(sizeof(JumpEvent))) JumpEvent + JumpEvent* e = new(c->zone) JumpEvent (head, tail, offset); if (b->jumpEventTail) { @@ -857,8 +856,7 @@ void appendImmediateTask(Context* c, Promise* promise, Promise* offset, unsigned size, unsigned promiseOffset, bool address) { - c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask - (c->tasks, promise, offset, size, promiseOffset, address); + c->tasks = new(c->zone) ImmediateTask(c->tasks, promise, offset, size, promiseOffset, address); } class ConstantPoolEntry: public Promise { @@ -889,8 +887,7 @@ class ConstantPoolEntry: public Promise { ConstantPoolEntry* appendConstantPoolEntry(Context* c, Promise* constant) { - return new (c->zone->allocate(sizeof(ConstantPoolEntry))) - ConstantPoolEntry(c, constant); + return new (c->zone) ConstantPoolEntry(c, constant); } void @@ -1784,8 +1781,7 @@ branchCM(Context* c, TernaryOperation op, unsigned size, ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { - return new (c->zone->allocate(sizeof(ShiftMaskPromise))) - ShiftMaskPromise(base, shift, mask); + return new (c->zone) ShiftMaskPromise(base, shift, mask); } void @@ -1907,6 +1903,12 @@ return_(Context* c) emit(c, blr()); } +void +trap(Context* c) +{ + emit(c, trap()); +} + void memoryBarrier(Context* c) { @@ -1923,7 +1925,7 @@ argumentFootprint(unsigned footprint) void nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size, - unsigned footprint, void* link, void*, + unsigned footprint, void* link, bool, unsigned targetParameterFootprint, void** ip, void** stack) { assert(c, *ip >= start); @@ -1988,6 +1990,7 @@ populateTables(ArchitectureContext* c) zo[LoadBarrier] = memoryBarrier; zo[StoreStoreBarrier] = memoryBarrier; zo[StoreLoadBarrier] = memoryBarrier; + zo[Trap] = trap; uo[index(c, LongCall, C)] = CAST1(longCallC); @@ -2215,12 +2218,12 @@ class MyArchitecture: public Assembler::Architecture { } virtual void nextFrame(void* start, unsigned size, unsigned footprint, - void* link, void* stackLimit, + void* link, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) { ::nextFrame(&c, static_cast(start), size, footprint, link, - stackLimit, targetParameterFootprint, ip, stack); + mostRecent, targetParameterFootprint, ip, stack); } virtual void* frameIp(void* stack) { @@ -2454,8 +2457,7 @@ class MyAssembler: public Assembler { Register stack(StackRegister); Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); Constant handlerConstant - (new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(handler)); + (new(c.zone) ResolvedPromise(handler)); branchRM(&c, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, &handlerConstant); } @@ -2775,8 +2777,7 @@ class MyAssembler: public Assembler { MyBlock* b = c.lastBlock; b->size = c.code.length() - b->offset; if (startNew) { - c.lastBlock = new (c.zone->allocate(sizeof(MyBlock))) - MyBlock(&c, c.code.length()); + c.lastBlock = new(c.zone) MyBlock(&c, c.code.length()); } else { c.lastBlock = 0; } @@ -2847,9 +2848,9 @@ Assembler* makeAssembler(System* system, Allocator* allocator, Zone* zone, Assembler::Architecture* architecture) { - return new (zone->allocate(sizeof(MyAssembler))) - MyAssembler(system, allocator, zone, - static_cast(architecture)); + return + new(zone) MyAssembler(system, allocator, zone, + static_cast(architecture)); } } // namespace vm diff --git a/src/powerpc.h b/src/powerpc.h index 9b877719d0..8ddc9fc73c 100644 --- a/src/powerpc.h +++ b/src/powerpc.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/process.h b/src/process.h index 45de6d975c..04fcf57c7d 100644 --- a/src/process.h +++ b/src/process.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/processor.h b/src/processor.h index 71defc268e..c4c6fd9ad2 100644 --- a/src/processor.h +++ b/src/processor.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -41,6 +41,13 @@ class Processor { virtual unsigned count() = 0; }; + class CompilationHandler { + public: + virtual void compiled(const void* code, unsigned size, unsigned frameSize, const char* name) = 0; + + virtual void dispose() = 0; + }; + virtual Thread* makeThread(Machine* m, object javaThread, Thread* parent) = 0; @@ -99,6 +106,10 @@ class Processor { virtual object invokeArray(Thread* t, object method, object this_, object arguments) = 0; + virtual object + invokeArray(Thread* t, object method, object this_, const jvalue* arguments) + = 0; + virtual object invokeList(Thread* t, object method, object this_, bool indirectObjects, va_list arguments) = 0; @@ -120,6 +131,9 @@ class Processor { virtual void initialize(BootImage* image, uint8_t* code, unsigned capacity) = 0; + virtual void + addCompilationHandler(CompilationHandler* handler) = 0; + virtual void compileMethod(Thread* t, Zone* zone, object* constants, object* calls, DelayedPromise** addresses, object method, diff --git a/src/system.h b/src/system.h index 897193d042..c36aefacd9 100644 --- a/src/system.h +++ b/src/system.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/target-fields.h b/src/target-fields.h new file mode 100644 index 0000000000..3481d4516e --- /dev/null +++ b/src/target-fields.h @@ -0,0 +1,63 @@ +/* Copyright (c) 2011, 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. */ + +#ifndef AVIAN_TARGET_FIELDS_H +#define AVIAN_TARGET_FIELDS_H + + +#ifdef TARGET_BYTES_PER_WORD +# if (TARGET_BYTES_PER_WORD == 8) + +#define TARGET_THREAD_EXCEPTION 80 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2256 +#define TARGET_THREAD_EXCEPTIONOFFSET 2264 +#define TARGET_THREAD_EXCEPTIONHANDLER 2272 + +#define TARGET_THREAD_IP 2216 +#define TARGET_THREAD_STACK 2224 +#define TARGET_THREAD_NEWSTACK 2232 +#define TARGET_THREAD_SCRATCH 2240 +#define TARGET_THREAD_CONTINUATION 2248 +#define TARGET_THREAD_TAILADDRESS 2280 +#define TARGET_THREAD_VIRTUALCALLTARGET 2288 +#define TARGET_THREAD_VIRTUALCALLINDEX 2296 +#define TARGET_THREAD_HEAPIMAGE 2304 +#define TARGET_THREAD_CODEIMAGE 2312 +#define TARGET_THREAD_THUNKTABLE 2320 +#define TARGET_THREAD_STACKLIMIT 2368 + +# elif (TARGET_BYTES_PER_WORD == 4) + +#define TARGET_THREAD_EXCEPTION 44 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2164 +#define TARGET_THREAD_EXCEPTIONOFFSET 2168 +#define TARGET_THREAD_EXCEPTIONHANDLER 2172 + +#define TARGET_THREAD_IP 2144 +#define TARGET_THREAD_STACK 2148 +#define TARGET_THREAD_NEWSTACK 2152 +#define TARGET_THREAD_SCRATCH 2156 +#define TARGET_THREAD_CONTINUATION 2160 +#define TARGET_THREAD_TAILADDRESS 2176 +#define TARGET_THREAD_VIRTUALCALLTARGET 2180 +#define TARGET_THREAD_VIRTUALCALLINDEX 2184 +#define TARGET_THREAD_HEAPIMAGE 2188 +#define TARGET_THREAD_CODEIMAGE 2192 +#define TARGET_THREAD_THUNKTABLE 2196 +#define TARGET_THREAD_STACKLIMIT 2220 + +# else +# error +# endif +#else +# error +#endif + +#endif \ No newline at end of file diff --git a/src/target.h b/src/target.h index 509a574996..996d76348f 100644 --- a/src/target.h +++ b/src/target.h @@ -11,6 +11,8 @@ #ifndef TARGET_H #define TARGET_H +#include "target-fields.h" + namespace vm { template @@ -90,18 +92,6 @@ targetVW(T v) typedef uint64_t target_uintptr_t; typedef int64_t target_intptr_t; -const unsigned TargetBytesPerWord = 8; - -const unsigned TargetThreadIp = 2216; -const unsigned TargetThreadStack = 2224; -const unsigned TargetThreadTailAddress = 2272; -const unsigned TargetThreadVirtualCallTarget = 2280; -const unsigned TargetThreadVirtualCallIndex = 2288; -const unsigned TargetThreadHeapImage = 2296; -const unsigned TargetThreadCodeImage = 2304; -const unsigned TargetThreadThunkTable = 2312; -const unsigned TargetThreadStackLimit = 2360; - const unsigned TargetClassFixedSize = 12; const unsigned TargetClassArrayElementSize = 14; const unsigned TargetClassVtable = 128; @@ -120,18 +110,6 @@ targetVW(T v) typedef uint32_t target_uintptr_t; typedef int32_t target_intptr_t; -const unsigned TargetBytesPerWord = 4; - -const unsigned TargetThreadIp = 2144; -const unsigned TargetThreadStack = 2148; -const unsigned TargetThreadTailAddress = 2172; -const unsigned TargetThreadVirtualCallTarget = 2176; -const unsigned TargetThreadVirtualCallIndex = 2180; -const unsigned TargetThreadHeapImage = 2184; -const unsigned TargetThreadCodeImage = 2188; -const unsigned TargetThreadThunkTable = 2192; -const unsigned TargetThreadStackLimit = 2216; - const unsigned TargetClassFixedSize = 8; const unsigned TargetClassArrayElementSize = 10; const unsigned TargetClassVtable = 68; @@ -145,6 +123,8 @@ const unsigned TargetFieldOffset = 8; # error #endif +const unsigned TargetBytesPerWord = TARGET_BYTES_PER_WORD; + const unsigned TargetBitsPerWord = TargetBytesPerWord * 8; const target_uintptr_t TargetPointerMask diff --git a/src/type-generator.cpp b/src/type-generator.cpp index ca5bd37056..f31b0f18c8 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -70,12 +70,6 @@ equal(const char* a, const char* b) return strcmp(a, b) == 0; } -inline bool -startsWith(const char* a, const char* b) -{ - return strncmp(a, b, strlen(a)) == 0; -} - inline bool endsWith(const char* a, const char* b) { @@ -284,14 +278,6 @@ setCdr(Object* o, Object* v) static_cast(o)->cdr = v; } -unsigned -length(Object* o) -{ - unsigned c = 0; - for (; o; o = cdr(o)) ++c; - return c; -} - class List { public: Object* first; @@ -1078,53 +1064,6 @@ parseSubdeclaration(Object* t, Object* p, Object* declarations) } } -bool -memberEqual(Object* a, Object* b) -{ - if (a->type == b->type) { - switch (a->type) { - case Object::Scalar: - return equal(memberTypeName(a), memberTypeName(b)) - and memberNoAssert(a) == memberNoAssert(b) - and memberNoGC(a) == memberNoGC(b); - - // todo: compare array fields - - default: return false; - } - } else { - return false; - } -} - -bool -specEqual(Object* a, Object* b) -{ - if (a->type == Object::Type and - b->type == Object::Type) - { - MemberIterator ai(a); - MemberIterator bi(b); - while (ai.hasMore()) { - if (not bi.hasMore()) { - return false; - } - - if (not memberEqual(ai.next(), bi.next())) { - return false; - } - } - - if (bi.hasMore()) { - return false; - } else { - return true; - } - } else { - return false; - } -} - const char* append(const char* a, const char* b, const char* c, const char* d) { @@ -1445,6 +1384,11 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false) out->write(" = "); writeOffset(out, offset); out->write(";\n\n"); + + out->write("#define HAVE_"); + out->write(capitalize(local::typeName(memberOwner(member)))); + out->write(capitalize(memberName(member))); + out->write(" 1\n\n"); } out->write("inline "); @@ -1725,13 +1669,6 @@ writeConstructorInitializations(Output* out, Object* t) } } -unsigned -typeMemberCount(Object* o) -{ - if (o == 0) return 0; - return length(typeMembers(o)) + typeMemberCount(typeSuper(o)); -} - void writeInitializerDeclarations(Output* out, Object* declarations) { @@ -1888,17 +1825,6 @@ writeEnums(Output* out, Object* declarations) } } -unsigned -memberCount(Object* o) -{ - unsigned c = 0; - for (MemberIterator it(o); it.hasMore();) { - it.next(); - ++c; - } - return c; -} - unsigned methodCount(Object* o) { diff --git a/src/types.def b/src/types.def index c95ed03a0a..31d96404a8 100644 --- a/src/types.def +++ b/src/types.def @@ -77,6 +77,7 @@ (object exceptionHandlerTable) (object lineNumberTable) (intptr_t compiled) + (uint32_t compiledSize) (uint16_t maxStack) (uint16_t maxLocals) (array uint8_t body)) @@ -219,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/util.cpp b/src/util.cpp index 562255b95a..915913e6e1 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -58,8 +58,7 @@ class TreeContext { TreeContext::Path* path(TreeContext* c, object node, TreeContext::Path* next) { - return new (c->zone->allocate(sizeof(TreeContext::Path))) - TreeContext::Path(node, next); + return new(c->zone) TreeContext::Path(node, next); } inline object diff --git a/src/windows.cpp b/src/windows.cpp index 42a79d3024..f6b4f1e550 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -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; } diff --git a/src/x86.cpp b/src/x86.cpp index 28c6dc2bc7..2a6d39d0aa 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -8,6 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ +#include "environment.h" #include "assembler.h" #include "target.h" #include "vector.h" @@ -156,7 +157,7 @@ class Context { public: Context(System* s, Allocator* a, Zone* zone, ArchitectureContext* ac): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(0)), + firstBlock(new(zone) MyBlock(0)), lastBlock(firstBlock), ac(ac) { } @@ -197,43 +198,10 @@ assert(ArchitectureContext* c, bool v) } #endif // not NDEBUG -void -expect(Context* c, bool v) -{ - expect(c->s, v); -} - ResolvedPromise* resolved(Context* c, int64_t value) { - return new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value); -} - -class CodePromise: public Promise { - public: - CodePromise(Context* c, unsigned offset): c(c), offset(offset) { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast(c->result + offset); - } - - abort(c); - } - - virtual bool resolved() { - return c->result != 0; - } - - Context* c; - unsigned offset; -}; - -CodePromise* -codePromise(Context* c, unsigned offset) -{ - return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset); + return new(c->zone) ResolvedPromise(value); } class Offset: public Promise { @@ -267,8 +235,7 @@ class Offset: public Promise { Promise* offset(Context* c) { - return new (c->zone->allocate(sizeof(Offset))) - Offset(c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); + return new(c->zone) Offset(c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); } class Task { @@ -345,8 +312,8 @@ void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, unsigned instructionSize) { - OffsetTask* task = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask - (c->tasks, promise, instructionOffset, instructionSize); + OffsetTask* task = + new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, instructionSize); c->tasks = task; } @@ -417,7 +384,7 @@ void appendImmediateTask(Context* c, Promise* promise, Promise* offset, unsigned size, unsigned promiseOffset = 0) { - c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask + c->tasks = new(c->zone) ImmediateTask (c->tasks, promise, offset, size, promiseOffset); } @@ -630,20 +597,18 @@ opcode(Context* c, uint8_t op1, uint8_t op2) c->code.append(op2); } -void -opcode(Context* c, uint8_t op1, uint8_t op2, uint8_t op3) -{ - c->code.append(op1); - c->code.append(op2); - c->code.append(op3); -} - void return_(Context* c) { opcode(c, 0xc3); } +void +trap(Context* c) +{ + opcode(c, 0xcc); +} + void ignore(Context*) { } @@ -832,7 +797,7 @@ callM(Context* c, unsigned size UNUSED, Assembler::Memory* a) void alignedCallC(Context* c, unsigned size, Assembler::Constant* a) { - new (c->zone->allocate(sizeof(AlignmentPadding))) AlignmentPadding(c, 1, 4); + new(c->zone) AlignmentPadding(c, 1, 4); callC(c, size, a); } @@ -842,8 +807,7 @@ alignedLongCallC(Context* c, unsigned size, Assembler::Constant* a) assert(c, size == TargetBytesPerWord); if (TargetBytesPerWord == 8) { - new (c->zone->allocate(sizeof(AlignmentPadding))) - AlignmentPadding(c, 2, 8); + new (c->zone) AlignmentPadding(c, 2, 8); longCallC(c, size, a); } else { alignedCallC(c, size, a); @@ -853,7 +817,7 @@ alignedLongCallC(Context* c, unsigned size, Assembler::Constant* a) void alignedJumpC(Context* c, unsigned size, Assembler::Constant* a) { - new (c->zone->allocate(sizeof(AlignmentPadding))) AlignmentPadding(c, 1, 4); + new (c->zone) AlignmentPadding(c, 1, 4); jumpC(c, size, a); } @@ -863,8 +827,7 @@ alignedLongJumpC(Context* c, unsigned size, Assembler::Constant* a) assert(c, size == TargetBytesPerWord); if (TargetBytesPerWord == 8) { - new (c->zone->allocate(sizeof(AlignmentPadding))) - AlignmentPadding(c, 2, 8); + new (c->zone) AlignmentPadding(c, 2, 8); longJumpC(c, size, a); } else { alignedJumpC(c, size, a); @@ -1289,8 +1252,7 @@ moveAR(Context* c, unsigned aSize, Assembler::Address* a, ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { - return new (c->zone->allocate(sizeof(ShiftMaskPromise))) - ShiftMaskPromise(base, shift, mask); + return new(c->zone) ShiftMaskPromise(base, shift, mask); } void @@ -1478,7 +1440,8 @@ subtractBorrowCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, opcode(c, 0x83, 0xd8 + regCode(b)); c->code.append(v); } else { - abort(c); + opcode(c, 0x81, 0xd8 + regCode(b)); + c->code.append4(v); } } @@ -2161,8 +2124,8 @@ divideRR(Context* c, unsigned aSize, Assembler::Register* a, assert(c, a->low != rdx); c->client->save(rdx); - - maybeRex(c, aSize, a, b); + + maybeRex(c, aSize, a, b); opcode(c, 0x99); // cdq maybeRex(c, aSize, b, a); opcode(c, 0xf7, 0xf8 + regCode(a)); @@ -2178,8 +2141,8 @@ remainderRR(Context* c, unsigned aSize, Assembler::Register* a, assert(c, a->low != rdx); c->client->save(rdx); - - maybeRex(c, aSize, a, b); + + maybeRex(c, aSize, a, b); opcode(c, 0x99); // cdq maybeRex(c, aSize, b, a); opcode(c, 0xf7, 0xf8 + regCode(a)); @@ -2550,7 +2513,7 @@ read4(uint8_t* p) void nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, - unsigned footprint, void*, void* stackLimit, + unsigned footprint, void*, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) { assert(c, *ip >= start); @@ -2561,13 +2524,14 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, // skip stack overflow check, if present: if (TargetBytesPerWord == 4) { if (*start == 0x39) { - start += 11; + start += 12; } } else if (*start == 0x48 and start[1] == 0x39) { - start += 12; + start += 13; } if (instruction <= start) { + assert(c, mostRecent); *ip = static_cast(*stack)[0]; return; } @@ -2577,6 +2541,8 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, start += (TargetBytesPerWord == 4 ? 3 : 4); if (instruction <= start or *instruction == 0x5d) { + assert(c, mostRecent); + *ip = static_cast(*stack)[1]; *stack = static_cast(*stack) + 1; return; @@ -2588,8 +2554,7 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, return; } - unsigned offset = footprint + FrameHeaderSize - - (stackLimit == *stack ? 1 : 0); + unsigned offset = footprint + FrameHeaderSize - (mostRecent ? 1 : 0); if (TailCalls) { if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) { @@ -2640,6 +2605,7 @@ populateTables(ArchitectureContext* c) zo[LoadBarrier] = ignore; zo[StoreStoreBarrier] = ignore; zo[StoreLoadBarrier] = storeLoadBarrier; + zo[Trap] = trap; uo[index(c, Call, C)] = CAST1(callC); uo[index(c, Call, R)] = CAST1(callR); @@ -2677,6 +2643,7 @@ populateTables(ArchitectureContext* c) bo[index(c, MoveZ, R, R)] = CAST2(moveZRR); bo[index(c, MoveZ, M, R)] = CAST2(moveZMR); + bo[index(c, MoveZ, C, R)] = CAST2(moveCR); bo[index(c, Add, R, R)] = CAST2(addRR); bo[index(c, Add, C, R)] = CAST2(addCR); @@ -2814,7 +2781,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned frameFootprint(unsigned footprint) { -#ifdef TARGET_PLATFORM_WINDOWS +#if AVIAN_TARGET_PLATFORM == AVIAN_PLATFORM_WINDOWS return max(footprint, StackAlignmentInWords); #else return max(footprint > argumentRegisterCount() ? @@ -2836,7 +2803,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned argumentRegisterCount() { -#ifdef TARGET_PLATFORM_WINDOWS +#if AVIAN_TARGET_PLATFORM == AVIAN_PLATFORM_WINDOWS if (TargetBytesPerWord == 8) return 4; else #else if (TargetBytesPerWord == 8) return 6; else @@ -2847,7 +2814,7 @@ class MyArchitecture: public Assembler::Architecture { virtual int argumentRegister(unsigned index) { assert(&c, TargetBytesPerWord == 8); switch (index) { -#ifdef TARGET_PLATFORM_WINDOWS +#if AVIAN_TARGET_PLATFORM == AVIAN_PLATFORM_WINDOWS case 0: return rcx; case 1: @@ -2963,12 +2930,12 @@ class MyArchitecture: public Assembler::Architecture { } virtual void nextFrame(void* start, unsigned size, unsigned footprint, - void* link, void* stackLimit, + void* link, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) { local::nextFrame(&c, static_cast(start), size, footprint, - link, stackLimit, targetParameterFootprint, ip, stack); + link, mostRecent, targetParameterFootprint, ip, stack); } virtual void* frameIp(void* stack) { @@ -3695,8 +3662,7 @@ class MyAssembler: public Assembler { MyBlock* b = c.lastBlock; b->size = c.code.length() - b->offset; if (startNew) { - c.lastBlock = new (c.zone->allocate(sizeof(MyBlock))) - MyBlock(c.code.length()); + c.lastBlock = new(c.zone) MyBlock(c.code.length()); } else { c.lastBlock = 0; } @@ -3740,9 +3706,9 @@ Assembler* makeAssembler(System* system, Allocator* allocator, Zone* zone, Assembler::Architecture* architecture) { - return new (zone->allocate(sizeof(local::MyAssembler))) - local::MyAssembler(system, allocator, zone, - static_cast(architecture)); + return + new(zone) local::MyAssembler(system, allocator, zone, + static_cast(architecture)); } } // namespace vm diff --git a/src/x86.h b/src/x86.h index 72cc891ac1..298cab6aaa 100644 --- a/src/x86.h +++ b/src/x86.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/zlib-custom.h b/src/zlib-custom.h index cf1119e1fe..ab00841eec 100644 --- a/src/zlib-custom.h +++ b/src/zlib-custom.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2009, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/test/Annotations.java b/test/Annotations.java index 17929065d1..c0234d21c0 100644 --- a/test/Annotations.java +++ b/test/Annotations.java @@ -1,7 +1,10 @@ -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; +import avian.testing.annotations.Color; +import avian.testing.annotations.Test; +import avian.testing.annotations.TestEnum; +import avian.testing.annotations.TestInteger; + public class Annotations { private static void expect(boolean v) { if (! v) throw new RuntimeException(); @@ -18,6 +21,12 @@ public class Annotations { .equals(Color.Red)); expect(((TestInteger) m.getAnnotation(TestInteger.class)).value() == 42); + + expect(m.getAnnotations().length == 3); + + Method noAnno = Annotations.class.getMethod("noAnnotation"); + expect(noAnno.getAnnotation(Test.class) == null); + expect(noAnno.getAnnotations().length == 0); } @Test("couscous") @@ -26,24 +35,8 @@ public class Annotations { public static void foo() { } - - @Retention(RetentionPolicy.RUNTIME) - private @interface Test { - public String value(); + + public static void noAnnotation() { + } - - @Retention(RetentionPolicy.RUNTIME) - private @interface TestEnum { - public Color value(); - } - - @Retention(RetentionPolicy.RUNTIME) - private @interface TestInteger { - public int value(); - } - - private static enum Color { - Red, Yellow, Blue - } - } diff --git a/test/Files.java b/test/Files.java index 7661e79018..7a0170b678 100644 --- a/test/Files.java +++ b/test/Files.java @@ -1,4 +1,6 @@ import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; public class Files { private static void expect(boolean v) { @@ -21,7 +23,9 @@ public class Files { } - private static void setExecutableTestWithPermissions(boolean executable) { + private static void setExecutableTestWithPermissions(boolean executable) + throws Exception + { File file = File.createTempFile("avian.", null); file.setExecutable(executable); if (executable) { @@ -33,11 +37,43 @@ public class Files { } } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { isAbsoluteTest(true); isAbsoluteTest(false); setExecutableTestWithPermissions(true); setExecutableTestWithPermissions(false); + + { File f = new File("test.txt"); + f.createNewFile(); + expect(! f.createNewFile()); + f.delete(); + } + + { File f = new File("test.txt"); + FileOutputStream out = new FileOutputStream(f); + try { + byte[] message = "hello, world!\n".getBytes(); + out.write(message); + out.close(); + + FileInputStream in = new FileInputStream(f); + try { + expect(in.available() == message.length); + + for (int i = 0; i < message.length; ++i) { + in.read(); + expect(in.available() == message.length - i - 1); + } + + expect(in.read() == -1); + expect(in.available() == 0); + } finally { + in.close(); + } + } finally { + f.delete(); + } + } } } diff --git a/test/Floats.java b/test/Floats.java index 2e869a9a87..723b899a1a 100644 --- a/test/Floats.java +++ b/test/Floats.java @@ -260,5 +260,17 @@ public class Floats { int result = Float.floatToIntBits(number); expect(result == orig); } + + for (int x = 0; x < 1000; ++x) { + int m = 100; + int n = 200; + double array[][] = new double[m][n]; + + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + array[i][j] = 1234567890.0; + } + } + } } } diff --git a/test/List.java b/test/List.java index 797aefbb7f..c7d73d93fc 100644 --- a/test/List.java +++ b/test/List.java @@ -131,6 +131,20 @@ public class List { expect(l.size() == 2); } + private static void testGrow() { + ArrayList foo = new ArrayList(2); + foo.add(0); + foo.add(1); + foo.add(2); // first grow + foo.add(3); + foo.add(4); // second grow + foo.add(5); + + for (int i = 0; i < foo.size(); i++) { + expect(i == foo.get(i)); + } + } + public static void main(String args[]) { ArrayList l = new ArrayList(); l.add(1); l.add(2); l.add(3); l.add(4); l.add(5); @@ -155,5 +169,6 @@ public class List { testIterators2(new ArrayList()); testIterators2(new LinkedList()); + testGrow(); } } diff --git a/test/Longs.java b/test/Longs.java index 434ee908c9..0472536f60 100644 --- a/test/Longs.java +++ b/test/Longs.java @@ -234,6 +234,54 @@ public class Longs { expect((a ^ 25214903884L) == (2L ^ 25214903884L)); } + { long b = 2; + expect((-281474976710656L) >> b == -281474976710656L >> 2); + expect((-281474976710656L) >>> b == -281474976710656L >>> 2); + expect((-281474976710656L) << b == -281474976710656L << 2); + expect((-281474976710656L) + b == -281474976710656L + 2L); + expect((-281474976710656L) - b == -281474976710656L - 2L); + expect((-281474976710656L) * b == -281474976710656L * 2L); + expect((-281474976710656L) / b == -281474976710656L / 2L); + expect((-281474976710656L) % b == -281474976710656L % 2L); + expect(((-281474976710656L) & b) == (-281474976710656L & 2L)); + expect(((-281474976710656L) | b) == (-281474976710656L | 2L)); + expect(((-281474976710656L) ^ b) == (-281474976710656L ^ 2L)); + + b = 2; + expect(281474976710656L >> b == 281474976710656L >> 2); + expect(281474976710656L >>> b == 281474976710656L >>> 2); + expect(281474976710656L << b == 281474976710656L << 2); + expect(281474976710656L + b == 281474976710656L + 2L); + expect(281474976710656L - b == 281474976710656L - 2L); + expect(281474976710656L * b == 281474976710656L * 2L); + expect(281474976710656L / b == 281474976710656L / 2L); + expect(281474976710656L % b == 281474976710656L % 2L); + expect((281474976710656L & b) == (281474976710656L & 2L)); + expect((281474976710656L | b) == (281474976710656L | 2L)); + expect((281474976710656L ^ b) == (281474976710656L ^ 2L)); + } + + { long a = 2L; + expect(a + (-281474976710656L) == 2L + (-281474976710656L)); + expect(a - (-281474976710656L) == 2L - (-281474976710656L)); + expect(a * (-281474976710656L) == 2L * (-281474976710656L)); + expect(a / (-281474976710656L) == 2L / (-281474976710656L)); + expect(a % (-281474976710656L) == 2L % (-281474976710656L)); + expect((a & (-281474976710656L)) == (2L & (-281474976710656L))); + expect((a | (-281474976710656L)) == (2L | (-281474976710656L))); + expect((a ^ (-281474976710656L)) == (2L ^ (-281474976710656L))); + + a = 2L; + expect(a + 281474976710656L == 2L + 281474976710656L); + expect(a - 281474976710656L == 2L - 281474976710656L); + expect(a * 281474976710656L == 2L * 281474976710656L); + expect(a / 281474976710656L == 2L / 281474976710656L); + expect(a % 281474976710656L == 2L % 281474976710656L); + expect((a & 281474976710656L) == (2L & 281474976710656L)); + expect((a | 281474976710656L) == (2L | 281474976710656L)); + expect((a ^ 281474976710656L) == (2L ^ 281474976710656L)); + } + { long x = 231; expect((x >> 32) == 0); expect((x >>> 32) == 0); diff --git a/test/UnsafeTest.java b/test/UnsafeTest.java new file mode 100644 index 0000000000..5167526c3b --- /dev/null +++ b/test/UnsafeTest.java @@ -0,0 +1,65 @@ +import sun.misc.Unsafe; + +public class UnsafeTest { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) { + Unsafe u = avian.Machine.getUnsafe(); + + final long size = 64; + long memory = u.allocateMemory(size); + try { + for (int i = 0; i < size; ++i) + u.putByte(memory + i, (byte) 42); + + for (int i = 0; i < size; ++i) + expect(u.getByte(memory + i) == 42); + + for (int i = 0; i < size / 2; ++i) + u.putShort(memory + (i * 2), (short) -12345); + + for (int i = 0; i < size / 2; ++i) + expect(u.getShort(memory + (i * 2)) == -12345); + + for (int i = 0; i < size / 2; ++i) + u.putChar(memory + (i * 2), (char) 23456); + + for (int i = 0; i < size / 2; ++i) + expect(u.getChar(memory + (i * 2)) == 23456); + + for (int i = 0; i < size / 4; ++i) + u.putInt(memory + (i * 4), 0x12345678); + + for (int i = 0; i < size / 4; ++i) + expect(u.getInt(memory + (i * 4)) == 0x12345678); + + for (int i = 0; i < size / 4; ++i) + u.putFloat(memory + (i * 4), 1.2345678F); + + for (int i = 0; i < size / 4; ++i) + expect(u.getFloat(memory + (i * 4)) == 1.2345678F); + + for (int i = 0; i < size / 8; ++i) + u.putLong(memory + (i * 8), 0x1234567890ABCDEFL); + + for (int i = 0; i < size / 8; ++i) + expect(u.getLong(memory + (i * 8)) == 0x1234567890ABCDEFL); + + for (int i = 0; i < size / 8; ++i) + u.putDouble(memory + (i * 8), 1.23456789012345D); + + for (int i = 0; i < size / 8; ++i) + expect(u.getDouble(memory + (i * 8)) == 1.23456789012345D); + + for (int i = 0; i < size / 8; ++i) + u.putAddress(memory + (i * 8), 0x12345678); + + for (int i = 0; i < size / 8; ++i) + expect(u.getAddress(memory + (i * 8)) == 0x12345678); + } finally { + u.freeMemory(memory); + } + } +} diff --git a/test/avian/testing/annotations/Color.java b/test/avian/testing/annotations/Color.java new file mode 100644 index 0000000000..f054b0420a --- /dev/null +++ b/test/avian/testing/annotations/Color.java @@ -0,0 +1,5 @@ +package avian.testing.annotations; + +public enum Color { + Red, Yellow, Blue +} \ No newline at end of file diff --git a/test/avian/testing/annotations/Test.java b/test/avian/testing/annotations/Test.java new file mode 100644 index 0000000000..f9ba919647 --- /dev/null +++ b/test/avian/testing/annotations/Test.java @@ -0,0 +1,9 @@ +package avian.testing.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Test { + public String value(); +} diff --git a/test/avian/testing/annotations/TestEnum.java b/test/avian/testing/annotations/TestEnum.java new file mode 100644 index 0000000000..f8a252fd54 --- /dev/null +++ b/test/avian/testing/annotations/TestEnum.java @@ -0,0 +1,8 @@ +package avian.testing.annotations; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface TestEnum { + public Color value(); +} \ No newline at end of file diff --git a/test/avian/testing/annotations/TestInteger.java b/test/avian/testing/annotations/TestInteger.java new file mode 100644 index 0000000000..b7ec78d0bc --- /dev/null +++ b/test/avian/testing/annotations/TestInteger.java @@ -0,0 +1,8 @@ +package avian.testing.annotations; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface TestInteger { + public int value(); +} \ No newline at end of file diff --git a/update-copyright.sh b/update-copyright.sh new file mode 100644 index 0000000000..994addef38 --- /dev/null +++ b/update-copyright.sh @@ -0,0 +1,12 @@ +for x in $(find -name *.S -or -name *.cpp -or -name *.h -or -name *.java | sort); do + year_of_last_change=$(git log -1 --format=format:"%ai" $x | cut -c 1-4) + copyright_years=$(grep "^/\* Copyright (c) .*, Avian Contributors$" $x | sed "s-^/\* Copyright (c) \(.*\), Avian Contributors\$-\1-") + if [ "$copyright_years" != "" ]; then + first_copyright_year=$(echo "$copyright_years" | sed "s/\(.*\)-.*/\1/") + last_copyright_year=$(echo "$copyright_years" | sed "s/.*-\(.*\)/\1/") + if [ "$last_copyright_year" != "$year_of_last_change" ]; then + echo "$first_copyright_year-$year_of_last_change $x" + sed -i "s:^/\* Copyright (c) .*, Avian Contributors\$:/* Copyright (c) $first_copyright_year-$year_of_last_change, Avian Contributors:" $x + fi + fi +done diff --git a/vm.pro b/vm.pro index 495bc4c3ab..4cdb1654ee 100644 --- a/vm.pro +++ b/vm.pro @@ -66,6 +66,7 @@ -keep public class java.lang.UnsatisfiedLinkError -keep public class java.lang.ExceptionInInitializerError -keep public class java.lang.OutOfMemoryError +-keep public class java.lang.IncompatibleClassChangeError -keep public class java.lang.reflect.InvocationTargetException -keep public class java.io.IOException -keep public class java.io.FileNotFoundException