Merge branch 'master' into compiler

This commit is contained in:
Joel Dice 2008-03-09 11:31:55 -06:00
commit 7cfb89bd2a
23 changed files with 353 additions and 154 deletions

View File

@ -431,6 +431,70 @@ Java_java_lang_System_doMapLibraryName(JNIEnv* e, jclass, jstring name)
return r;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_java_lang_Double_isInfinite(JNIEnv*, jclass, jdouble val)
{
return !isfinite(val);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_java_lang_Double_isNaN(JNIEnv*, jclass, jdouble val)
{
return isnan(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Double_doubleFromString(JNIEnv*e, jclass, jstring s,
jintArray numDoublesRead)
{
const char* chars = e->GetStringUTFChars(s, 0);
double d = 0.0;
jint numRead = 0;
if (chars) {
char* lastRead;
d = strtod(chars, &lastRead);
if ((lastRead != chars) && ((chars + strlen(chars)) == lastRead)) {
numRead = 1;
}
e->ReleaseStringUTFChars(s, chars);
}
e->SetIntArrayRegion(numDoublesRead, 0, 1, &numRead);
return d;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_java_lang_Float_isInfinite(JNIEnv*, jclass, jfloat val)
{
return !isfinite(val);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_java_lang_Float_isNaN(JNIEnv*, jclass, jfloat val)
{
return isnan(val);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_java_lang_Float_floatFromString(JNIEnv*e, jclass, jstring s,
jintArray numFloatsRead)
{
const char* chars = e->GetStringUTFChars(s, 0);
float f = 0.0;
jint numRead = 0;
if (chars) {
char* lastRead;
f = strtof(chars, &lastRead);
if ((lastRead != chars) && ((chars + strlen(chars)) == lastRead)) {
numRead = 1;
}
e->ReleaseStringUTFChars(s, chars);
}
e->SetIntArrayRegion(numFloatsRead, 0, 1, &numRead);
return f;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_sin(JNIEnv*, jclass, jdouble val)
{
@ -469,7 +533,12 @@ extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_natRandom(JNIEnv*, jclass)
{
#ifdef WIN32
return rand();
double r = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
if (r < 0 or r >= 1) {
return 0;
} else {
return r;
}
#else
return drand48();
#endif

View File

@ -31,6 +31,10 @@ public final class Double extends Number {
return new Double(value);
}
public static Double valueOf(String s) {
return new Double(s);
}
public boolean equals(Object o) {
return o instanceof Double && ((Double) o).value == value;
}
@ -74,9 +78,22 @@ public final class Double extends Number {
return value;
}
public boolean isInfinite() {
return isInfinite(value);
}
public boolean isNaN() {
return isNaN(value);
}
public static double parseDouble(String s) {
// todo
throw new NumberFormatException(s);
int[] numRead = new int[1];
double d = doubleFromString(s, numRead);
if (numRead[0] == 1) {
return d;
} else {
throw new NumberFormatException(s);
}
}
public static native int fillBufferWithDouble(double value, byte[] buffer,
@ -85,4 +102,10 @@ public final class Double extends Number {
public static native long doubleToRawLongBits(double value);
public static native double longBitsToDouble(long bits);
public static native boolean isInfinite(double value);
public static native boolean isNaN(double value);
public static native double doubleFromString(String s, int[] numRead);
}

View File

@ -15,6 +15,10 @@ public final class Float extends Number {
private final float value;
public Float(String value) {
this.value = parseFloat(value);
}
public Float(float value) {
this.value = value;
}
@ -23,6 +27,10 @@ public final class Float extends Number {
return new Float(value);
}
public static Float valueOf(String s) {
return new Float(s);
}
public boolean equals(Object o) {
return o instanceof Float && ((Float) o).value == value;
}
@ -63,12 +71,31 @@ public final class Float extends Number {
return (double) value;
}
public boolean isInfinite() {
return isInfinite(value);
}
public boolean isNaN() {
return isNaN(value);
}
public static float parseFloat(String s) {
// todo
throw new NumberFormatException(s);
int[] numRead = new int[1];
float f = floatFromString(s, numRead);
if (numRead[0] == 1) {
return f;
} else {
throw new NumberFormatException(s);
}
}
public static native int floatToRawIntBits(float value);
public static native float intBitsToFloat(int bits);
public static native boolean isInfinite(float value);
public static native boolean isNaN(float value);
public static native float floatFromString(String s, int[] numRead);
}

View File

@ -118,7 +118,7 @@ public class StringBuilder {
}
public StringBuilder insert(int i, String s) {
if (i < 0 || i >= length) {
if (i < 0 || i > length) {
throw new IndexOutOfBoundsException();
}

View File

@ -24,11 +24,9 @@ public class ArrayList<T> implements List<T> {
this(0);
}
public ArrayList(Collection<T> source) {
public ArrayList(Collection<? extends T> source) {
this(source.size());
for (T o : source) {
add(o);
}
addAll(source);
}
private void grow() {
@ -91,6 +89,11 @@ public class ArrayList<T> implements List<T> {
return true;
}
public boolean addAll(Collection<? extends T> collection) {
for (T t: collection) add(t);
return true;
}
public int indexOf(T element) {
for (int i = 0; i < size; ++i) {
if (equal(element, array[i])) {
@ -157,20 +160,7 @@ public class ArrayList<T> implements List<T> {
}
public <S> S[] toArray(S[] a) {
Object[] retVal = null;
if (a.length >= size) {
retVal = a;
} else {
retVal = new Object[size];
}
for (int i = 0; i < size; ++i) {
retVal[i] = array[i];
}
if (a.length > size) {
a[size] = null;
}
return (S[])retVal;
return Collections.toArray(this, a);
}
public void clear() {

View File

@ -21,6 +21,14 @@ public class Arrays {
return (a == null && b == null) || (a != null && a.equals(b));
}
public static void sort(Object[] array) {
sort(array, new Comparator() {
public int compare(Object a, Object b) {
return ((Comparable) a).compareTo(b);
}
});
}
public static <T> void sort(T[] array, Comparator<? super T> comparator) {
// insertion sort
for (int j = 1; j < array.length; ++j) {
@ -48,6 +56,10 @@ public class Arrays {
throw new UnsupportedOperationException();
}
public boolean addAll(Collection<? extends T> collection) {
throw new UnsupportedOperationException();
}
public void add(int index, T element) {
throw new UnsupportedOperationException();
}

View File

@ -19,7 +19,11 @@ public interface Collection<T> extends Iterable<T> {
public boolean add(T element);
public boolean addAll(Collection<? extends T> collection);
public boolean remove(T element);
public <S> S[] toArray(S[] array);
public void clear();
}

View File

@ -13,6 +13,25 @@ package java.util;
public class Collections {
private Collections() { }
static <T> T[] toArray(Collection collection, T[] array) {
Class c = array.getClass().getComponentType();
if (array.length < collection.size()) {
array = (T[]) java.lang.reflect.Array.newInstance(c, collection.size());
}
int i = 0;
for (Object o: collection) {
if (c.isInstance(o)) {
array[i++] = (T) o;
} else {
throw new ArrayStoreException();
}
}
return array;
}
static String toString(Collection c) {
StringBuilder sb = new StringBuilder();
sb.append("[");
@ -67,10 +86,18 @@ public class Collections {
synchronized (lock) { return collection.add(e); }
}
public boolean addAll(Collection<? extends T> collection) {
synchronized (lock) { return this.collection.addAll(collection); }
}
public boolean remove(T e) {
synchronized (lock) { return collection.remove(e); }
}
public <T> T[] toArray(T[] array) {
synchronized (lock) { return collection.toArray(array); }
}
public void clear() {
synchronized (lock) { collection.clear(); }
}
@ -87,10 +114,6 @@ public class Collections {
public SynchronizedSet(Object lock, Set<T> set) {
super(lock, set);
}
public void addAll(Collection<T> c) {
synchronized (lock) { ((Set<T>)collection).addAll(c); }
}
}
static class SynchronizedIterator<T> implements Iterator<T> {

View File

@ -32,6 +32,13 @@ public class HashMap<K, V> implements Map<K, V> {
this(0);
}
public HashMap(Map<K, V> map) {
this(map.size());
for (Map.Entry<K, V> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
@ -307,10 +314,6 @@ public class HashMap<K, V> implements Map<K, V> {
return HashMap.this.isEmpty();
}
public void addAll(Collection<Entry<K, V>> c) {
throw new UnsupportedOperationException();
}
public boolean contains(Entry<K, V> e) {
return containsKey(e.getKey());
}
@ -319,10 +322,20 @@ public class HashMap<K, V> implements Map<K, V> {
return putCell(e.getKey(), e.getValue()) != null;
}
public boolean addAll(Collection<? extends Entry<K, V>> collection) {
boolean change = false;
for (Entry<K, V> e: collection) if (add(e)) change = true;
return change;
}
public boolean remove(Entry<K, V> e) {
return removeCell(e.getKey()) != null;
}
public <T> T[] toArray(T[] array) {
return Collections.toArray(this, array);
}
public void clear() {
HashMap.this.clear();
}
@ -345,18 +358,24 @@ public class HashMap<K, V> implements Map<K, V> {
return containsKey(key);
}
public void addAll(Collection<K> c) {
throw new UnsupportedOperationException();
}
public boolean add(K key) {
return putCell(key, null) != null;
}
public boolean addAll(Collection<? extends K> collection) {
boolean change = false;
for (K k: collection) if (add(k)) change = true;
return change;
}
public boolean remove(K key) {
return removeCell(key) != null;
}
public <T> T[] toArray(T[] array) {
return Collections.toArray(this, array);
}
public void clear() {
HashMap.this.clear();
}
@ -384,10 +403,18 @@ public class HashMap<K, V> implements Map<K, V> {
throw new UnsupportedOperationException();
}
public boolean addAll(Collection<? extends V> collection) {
throw new UnsupportedOperationException();
}
public boolean remove(V value) {
throw new UnsupportedOperationException();
}
public <T> T[] toArray(T[] array) {
return Collections.toArray(this, array);
}
public void clear() {
HashMap.this.clear();
}

View File

@ -15,7 +15,7 @@ public class HashSet<T> implements Set<T> {
private final HashMap<T, Object> map;
public HashSet(Collection<T> c) {
public HashSet(Collection<? extends T> c) {
map = new HashMap(c.size());
addAll(c);
}
@ -40,18 +40,24 @@ public class HashSet<T> implements Set<T> {
return map.containsKey(element);
}
public void addAll(Collection<T> c) {
for (T t: c) add(t);
}
public boolean add(T element) {
return map.put(element, Value) != Value;
}
public boolean addAll(Collection<? extends T> collection) {
boolean change = false;
for (T t: collection) if (add(t)) change = true;
return change;
}
public boolean remove(T element) {
return map.remove(element) != Value;
}
public <T> T[] toArray(T[] array) {
return Collections.toArray(this, array);
}
public void clear() {
map.clear();
}

View File

@ -15,7 +15,7 @@ public class LinkedList<T> implements List<T> {
private Cell<T> rear;
private int size;
public LinkedList(Collection<T> c) {
public LinkedList(Collection<? extends T> c) {
addAll(c);
}
@ -86,20 +86,7 @@ public class LinkedList<T> implements List<T> {
}
public <S> S[] toArray(S[] a) {
Object[] retVal = null;
if (a.length >= size) {
retVal = a;
} else {
retVal = new Object[size];
}
int i=0;
for (Object o : this) {
retVal[i++] = o;
}
if (a.length > size) {
a[size] = null;
}
return (S[])retVal;
return Collections.toArray(this, a);
}
public int size() {
@ -119,6 +106,11 @@ public class LinkedList<T> implements List<T> {
return true;
}
public boolean addAll(Collection<? extends T> collection) {
for (T t: collection) add(t);
return true;
}
public void add(int index, T element) {
if (index == 0) {
addFirst(element);

View File

@ -22,6 +22,4 @@ public interface List<T> extends Collection<T> {
public void add(int index, T element);
public boolean isEmpty();
public <S> S[] toArray(S[] a);
}

View File

@ -18,4 +18,8 @@ public class Random {
public int nextInt() {
return (int)(Math.random()*Integer.MAX_VALUE);
}
public double nextDouble() {
return Math.random();
}
}

View File

@ -10,6 +10,4 @@
package java.util;
public interface Set<T> extends Collection<T> {
public void addAll(Collection<T> c);
}
public interface Set<T> extends Collection<T> { }

View File

@ -41,6 +41,12 @@ public class TreeSet<T> implements Collection<T> {
return false;
}
public boolean addAll(Collection<? extends T> collection) {
boolean change = false;
for (T t: collection) if (add(t)) change = true;
return change;
}
// Used by hashMaps for replacement
public void addAndReplace(T value) {
PersistentSet.Path<Cell<T>> p = set.find(new Cell(value, null));
@ -69,6 +75,10 @@ public class TreeSet<T> implements Collection<T> {
}
}
public <T> T[] toArray(T[] array) {
return Collections.toArray(this, array);
}
public int size() {
return size;
}

View File

@ -21,11 +21,8 @@ public class Vector<T> implements List<T> {
this(0);
}
public Vector(List<T> list) {
this(list.size());
for (T o : list) {
add(o);
}
public Vector(Collection<? extends T> source) {
list = new ArrayList(source);
}
public synchronized int size() {
@ -44,6 +41,10 @@ public class Vector<T> implements List<T> {
return list.add(element);
}
public synchronized boolean addAll(Collection<? extends T> collection) {
return list.addAll(collection);
}
public void addElement(T element) {
add(element);
}

View File

@ -1,6 +1,7 @@
#MAKEFLAGS = -s
name = avian
version = 0.0.1
build-arch = $(shell uname -m)
ifeq ($(build-arch),i586)
@ -22,6 +23,7 @@ endif
mode = fast
process = compile
root = $(shell (cd .. && pwd))
build = build
native-build = $(build)/$(platform)-$(arch)-$(process)-$(mode)
classpath-build = $(build)/classpath
@ -55,7 +57,7 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter \
common-cflags = $(warnings) -fno-rtti -fno-exceptions \
-I$(JAVA_HOME)/include -idirafter $(src) -I$(native-build) \
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\"
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
-I$(JAVA_HOME)/include/linux -I$(src) -pthread
@ -88,8 +90,8 @@ ifeq ($(platform),darwin)
endif
ifeq ($(platform),windows)
inc = /usr/local/win32/include
lib = /usr/local/win32/lib
inc = $(root)/win32/include
lib = $(root)/win32/lib
system = windows
object-format = pe-i386
@ -266,7 +268,7 @@ $(classpath-dep): $(classpath-sources)
@echo "compiling classpath classes"
@mkdir -p $(dir $(@))
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
$(shell make -s $(classpath-classes))
$(shell make -s --no-print-directory $(classpath-classes))
@touch $(@)
$(test-build)/%.class: $(test)/%.java
@ -276,7 +278,7 @@ $(test-dep): $(test-sources)
@echo "compiling test classes"
@mkdir -p $(dir $(@))
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
$(shell make -s $(test-classes))
$(shell make -s --no-print-directory $(test-classes))
@touch $(@)
define compile-object

View File

@ -2,7 +2,7 @@ Quick Start
-----------
on Linux:
$ export JAVA_HOME=/usr/local/java
$ export JAVA_HOME=/usr/local/java # or wherever you have Java installed
$ make
$ build/linux-i386-compile-fast/avian -cp build/test Hello
@ -12,6 +12,25 @@ on Mac OS X:
$ build/darwin-i386-compile-fast/avian -cp build/test Hello
Introduction
------------
Avian is a lightweight virtual machine and class library designed to
provide a useful subset of Java's features, suitable for building
self-contained applications. More information is available at the
project web site:
http://oss.readytalk.com/avian
If you have any trouble building, running, or embedding Avian, please
post a message to our discussion group:
http://groups.google.com/group/avian
That's also the place for any other questions, comments, or
suggestions you might have.
Supported Platforms
-------------------
@ -29,6 +48,27 @@ but patches to enable them are welcome.
Building
--------
Build requirements include:
* GNU make 3.80 or later
* GCC 3.4 or later
* JDK 1.5 or later
* GNU binutils 2.17 or later (not needed on OS X)
* MinGW 3.4 or later (only if cross-compiling for Windows)
* zlib 1.2.3 or later
Earlier versions of some of these packages may also work but have not
been tested.
If you are cross-compiling for Windows, you may find it useful to use
our win32 repository: (run this from the directory containing the
avian directory)
$ git clone git://oss.readytalk.com/win32.git
This gives you the Windows JNI headers, zlib headers and library, and
a few other useful libraries like OpenSSL and libjpeg.
The build is directed by a single makefile and may be influenced via
certain flags described below.
@ -43,7 +83,7 @@ certain flags described below.
* mode - which set of compilation flags to use, which determine
optimization level, debug symbols, and whether to enable
assertions.
assertions
default: fast
* process - choice between pure interpreter or JIT compiler

View File

@ -441,7 +441,7 @@ Java_java_lang_System_getVMProperty(Thread* t, jclass, jstring name,
if (strcmp(n, "java.lang.classpath") == 0) {
r = makeLocalReference(t, makeString(t, "%s", t->m->finder->path()));
} else if (strcmp(n, "avian.version") == 0) {
r = makeLocalReference(t, makeString(t, "0.0"));
r = makeLocalReference(t, makeString(t, AVIAN_VERSION));
}
if (r) {

View File

@ -427,6 +427,7 @@ class Context {
TraceElement* traceLog;
uint16_t* visitTable;
uintptr_t* rootTable;
bool dirtyRoots;
Vector eventLog;
MyProtector protector;
};
@ -3297,7 +3298,8 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
// that position, or the contents of that position are as yet
// unknown.
while (eventIndex < context->eventLog.length()) {
unsigned length = context->eventLog.length();
while (eventIndex < length) {
Event e = static_cast<Event>(context->eventLog.get(eventIndex++));
switch (e) {
case PushEvent: {
@ -3309,6 +3311,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
case IpEvent: {
ip = context->eventLog.get2(eventIndex);
eventIndex += 2;
if (DebugFrameMaps) {
fprintf(stderr, " roots at ip %3d: ", ip);
@ -3320,7 +3323,20 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
if (context->visitTable[ip] > 1) {
for (unsigned wi = 0; wi < mapSize; ++wi) {
tableRoots[wi] &= roots[wi];
uintptr_t newRoots = tableRoots[wi] & roots[wi];
if ((eventIndex == length
or context->eventLog.get(eventIndex) == PopEvent)
and newRoots != tableRoots[wi])
{
if (DebugFrameMaps) {
fprintf(stderr, "dirty roots!\n");
}
context->dirtyRoots = true;
}
tableRoots[wi] = newRoots;
roots[wi] &= tableRoots[wi];
}
@ -3332,92 +3348,20 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
} else {
memcpy(tableRoots, roots, mapSize * BytesPerWord);
}
eventIndex += 2;
} break;
case MarkEvent: {
unsigned i = context->eventLog.get2(eventIndex);
markBit(roots, i);
eventIndex += 2;
markBit(roots, i);
} break;
case ClearEvent: {
unsigned i = context->eventLog.get2(eventIndex);
eventIndex += 2;
clearBit(roots, i);
eventIndex += 2;
} break;
case TraceEvent: {
eventIndex += BytesPerWord;
} break;
default: abort(t);
}
}
return eventIndex;
}
unsigned
updateTraceElements(MyThread* t, Context* context, uintptr_t* originalRoots,
unsigned eventIndex)
{
unsigned mapSize = frameMapSizeInWords(t, context->method);
uintptr_t roots[mapSize];
if (originalRoots) {
memcpy(roots, originalRoots, mapSize * BytesPerWord);
} else {
memset(roots, 0, mapSize * BytesPerWord);
}
int32_t ip = -1;
while (eventIndex < context->eventLog.length()) {
Event e = static_cast<Event>(context->eventLog.get(eventIndex++));
switch (e) {
case PushEvent: {
eventIndex = updateTraceElements(t, context, roots, eventIndex);
} break;
case PopEvent:
return eventIndex;
case IpEvent: {
ip = context->eventLog.get2(eventIndex);
if (DebugFrameMaps) {
fprintf(stderr, " map at ip %3d: ", ip);
printSet(*roots);
fprintf(stderr, "\n");
}
if (context->visitTable[ip] > 1) {
uintptr_t* tableRoots = context->rootTable + (ip * mapSize);
for (unsigned wi = 0; wi < mapSize; ++wi) {
roots[wi] &= tableRoots[wi];
}
}
eventIndex += 2;
} break;
case MarkEvent: {
unsigned i = context->eventLog.get2(eventIndex);
markBit(roots, i);
eventIndex += 2;
} break;
case ClearEvent: {
unsigned i = context->eventLog.get2(eventIndex);
clearBit(roots, i);
eventIndex += 2;
} break;
case TraceEvent: {
@ -3586,6 +3530,7 @@ compile(MyThread* t, Context* context)
compile(t, &frame, 0);
if (UNLIKELY(t->exception)) return 0;
context->dirtyRoots = false;
unsigned eventIndex = calculateFrameMaps(t, context, 0, 0);
object eht = codeExceptionHandlerTable(t, methodCode(t, context->method));
@ -3642,7 +3587,10 @@ compile(MyThread* t, Context* context)
}
}
updateTraceElements(t, context, 0, 0);
while (context->dirtyRoots) {
context->dirtyRoots = false;
calculateFrameMaps(t, context, 0, 0);
}
return finish(t, context);
}

View File

@ -87,6 +87,23 @@ public class GC {
System.gc();
}
private static void stackMap6(boolean predicate) {
if (predicate) {
int a = 42;
} else {
Object a = null;
}
if (predicate) {
noop();
} else {
Object a = null;
}
noop();
System.gc();
}
public static void main(String[] args) {
Object[] array = new Object[1024 * 1024];
array[0] = new Object();
@ -119,6 +136,9 @@ public class GC {
stackMap5(true);
stackMap5(false);
stackMap6(true);
stackMap6(false);
}
}

View File

@ -17,7 +17,7 @@ for test in ${tests}; do
printf "%16s" "${test}: "
case ${mode} in
debug )
debug|debug-fast|fast )
${vm} ${flags} ${test} >>${log} 2>&1;;
stress* )

5
vm.pro
View File

@ -59,6 +59,11 @@
-keepnames public class java.lang.**
# Don't optimize calls to ResourceBundle
-keep,allowshrinking,allowobfuscation public class java.util.ResourceBundle {
public static java.util.ResourceBundle getBundle(...);
}
# musn't obfuscate native method names:
-keepclasseswithmembernames class * {