From afdab27e022c0f5e9ea371051d302d75905832a1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 20 Jul 2009 14:32:25 -0600 Subject: [PATCH 1/6] backport GC safety fixes from gnu branch --- src/compile.cpp | 4 +++- src/machine.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compile.cpp b/src/compile.cpp index ee41dd9cb7..48ab0aebeb 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5984,9 +5984,11 @@ class MyProcessor: public Processor { virtual void initVtable(Thread* t, object c) { + PROTECT(t, c); for (int i = classLength(t, c) - 1; i >= 0; --i) { - classVtable(t, c, i) = reinterpret_cast + void* thunk = reinterpret_cast (virtualThunk(static_cast(t), i)); + classVtable(t, c, i) = thunk; } } diff --git a/src/machine.cpp b/src/machine.cpp index 9b8ddb7c38..574b5ffd99 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2439,6 +2439,8 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) classLoader(t, class_), vtableLength); + PROTECT(t, real); + t->m->processor->initVtable(t, real); updateClassTables(t, real, class_); From ed5be834678f65d508c2fbd06c9013c0d842a9d3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 22 Jul 2009 10:38:32 -0600 Subject: [PATCH 2/6] add avian.commit system property --- makefile | 2 +- src/builtin.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 583d0fdb90..2bcf0afefe 100644 --- a/makefile +++ b/makefile @@ -83,7 +83,7 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \ common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \ "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ - + -DAVIAN_COMMIT=\"$(shell git rev-parse --short=8 HEAD)\" build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread diff --git a/src/builtin.cpp b/src/builtin.cpp index f4541036d4..0bb1b1f7a8 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -503,6 +503,8 @@ Avian_java_lang_System_getVMProperty r = reinterpret_cast(makeString(t, "%s", t->m->finder->path())); } else if (strcmp(n, "avian.version") == 0) { r = reinterpret_cast(makeString(t, AVIAN_VERSION)); + } else if (strcmp(n, "avian.commit") == 0) { + r = reinterpret_cast(makeString(t, AVIAN_COMMIT)); } else if (strcmp(n, "file.encoding") == 0) { r = reinterpret_cast(makeString(t, "ASCII")); } else { From 77f1bddce2dc305af51a62fae52ae270fcc96378 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 22 Jul 2009 10:45:38 -0600 Subject: [PATCH 3/6] Revert "add avian.commit system property" This reverts commit ed5be834678f65d508c2fbd06c9013c0d842a9d3. --- makefile | 2 +- src/builtin.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/makefile b/makefile index 2bcf0afefe..583d0fdb90 100644 --- a/makefile +++ b/makefile @@ -83,7 +83,7 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \ common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \ "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ - -DAVIAN_COMMIT=\"$(shell git rev-parse --short=8 HEAD)\" + build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread diff --git a/src/builtin.cpp b/src/builtin.cpp index 0bb1b1f7a8..f4541036d4 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -503,8 +503,6 @@ Avian_java_lang_System_getVMProperty r = reinterpret_cast(makeString(t, "%s", t->m->finder->path())); } else if (strcmp(n, "avian.version") == 0) { r = reinterpret_cast(makeString(t, AVIAN_VERSION)); - } else if (strcmp(n, "avian.commit") == 0) { - r = reinterpret_cast(makeString(t, AVIAN_COMMIT)); } else if (strcmp(n, "file.encoding") == 0) { r = reinterpret_cast(makeString(t, "ASCII")); } else { From 29858a529925362b01e917591e092a2357a33f0d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 23 Jul 2009 13:08:41 -0600 Subject: [PATCH 4/6] implement Selector.selectNow() and select() --- classpath/java-nio.cpp | 12 +++++++++++- classpath/java/nio/channels/Selector.java | 4 ++++ classpath/java/nio/channels/SocketSelector.java | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index e5a0e345ff..6c3fb14ee5 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -626,7 +626,17 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass, } #endif - timeval time = { interval / 1000, (interval % 1000) * 1000 }; + timeval time; + if (interval > 0) { + time.tv_sec = interval / 1000; + time.tv_usec = (interval % 1000) * 1000; + } else if (interval < 0) { + time.tv_sec = 0; + time.tv_usec = 0; + } else { + time.tv_sec = INT32_MAX; + time.tv_usec = 0; + } int r = ::select(max + 1, &(s->read), &(s->write), &(s->except), &time); if (r < 0) { diff --git a/classpath/java/nio/channels/Selector.java b/classpath/java/nio/channels/Selector.java index 021f267f17..7716db60e9 100644 --- a/classpath/java/nio/channels/Selector.java +++ b/classpath/java/nio/channels/Selector.java @@ -42,7 +42,11 @@ public abstract class Selector { public abstract Selector wakeup(); + public abstract int selectNow() throws IOException; + public abstract int select(long interval) throws IOException; + public abstract int select() throws IOException; + public abstract void close(); } diff --git a/classpath/java/nio/channels/SocketSelector.java b/classpath/java/nio/channels/SocketSelector.java index 587340a508..79d01d8594 100644 --- a/classpath/java/nio/channels/SocketSelector.java +++ b/classpath/java/nio/channels/SocketSelector.java @@ -48,7 +48,21 @@ class SocketSelector extends Selector { } } + public synchronized int selectNow() throws IOException { + return doSelect(-1); + } + + public synchronized int select() throws IOException { + return doSelect(0); + } + public synchronized int select(long interval) throws IOException { + if (interval < 0) throw new IllegalArgumentException(); + + return doSelect(interval); + } + + public int doSelect(long interval) throws IOException { selectedKeys.clear(); if (clearWoken()) return 0; From 08e9a99cb51c18ba6df94c865c5c8d264347c9d5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 24 Jul 2009 19:03:33 -0600 Subject: [PATCH 5/6] don't abort if pthread_kill fails in MySystem::visit --- src/compile.cpp | 2 +- src/posix.cpp | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 48ab0aebeb..b1f5e0111a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -6254,7 +6254,7 @@ class MyProcessor: public Processor { collect(t, Heap::MinorCollection); } - return visitor.trace; + return visitor.trace ? visitor.trace : makeArray(t, 0); } virtual void initialize(BootImage* image, uint8_t* code, unsigned capacity) { diff --git a/src/posix.cpp b/src/posix.cpp index b2b3800eee..fd45942ec5 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -628,13 +628,16 @@ class MySystem: public System { visitTarget = target; int rv = pthread_kill(target->thread, VisitSignal); - expect(this, rv == 0); - while (visitTarget) visitLock->wait(t, 0); + if (rv == 0) { + while (visitTarget) visitLock->wait(t, 0); - threadVisitor = 0; + threadVisitor = 0; - return 0; + return 0; + } else { + return -1; + } } virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, From d327f6ba5a25ff85d70364f3b118975c39cc30a2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 25 Jul 2009 15:41:43 -0600 Subject: [PATCH 6/6] implement java.util.TreeMap --- classpath/java/util/Collections.java | 56 ++++++++ classpath/java/util/HashMap.java | 68 ++------- classpath/java/util/TreeMap.java | 197 +++++++++++++++++++++++++++ classpath/java/util/TreeSet.java | 30 +++- test/Tree.java | 56 ++++++++ 5 files changed, 341 insertions(+), 66 deletions(-) create mode 100644 classpath/java/util/TreeMap.java diff --git a/classpath/java/util/Collections.java b/classpath/java/util/Collections.java index 619a4c5c61..3b6ab87d87 100644 --- a/classpath/java/util/Collections.java +++ b/classpath/java/util/Collections.java @@ -64,6 +64,22 @@ public class Collections { return sb.toString(); } + static String toString(Map m) { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + for (Iterator it = m.entrySet().iterator(); it.hasNext();) { + Map.Entry e = it.next(); + sb.append(e.getKey()) + .append("=") + .append(e.getValue()); + if (it.hasNext()) { + sb.append(","); + } + } + sb.append("}"); + return sb.toString(); + } + static class IteratorEnumeration implements Enumeration { private final Iterator it; @@ -312,4 +328,44 @@ public class Collections { public static Set unmodifiableSet(Set hs) { return new UnmodifiableSet(hs); } + + static class KeyIterator implements Iterator { + private final Iterator> it; + + public KeyIterator(Iterator> it) { + this.it = it; + } + + public K next() { + return it.next().getKey(); + } + + public boolean hasNext() { + return it.hasNext(); + } + + public void remove() { + it.remove(); + } + } + + static class ValueIterator implements Iterator { + private final Iterator> it; + + public ValueIterator(Iterator> it) { + this.it = it; + } + + public V next() { + return it.next().getValue(); + } + + public boolean hasNext() { + return it.hasNext(); + } + + public void remove() { + it.remove(); + } + } } diff --git a/classpath/java/util/HashMap.java b/classpath/java/util/HashMap.java index dd6eb85f61..2bc46b5e9d 100644 --- a/classpath/java/util/HashMap.java +++ b/classpath/java/util/HashMap.java @@ -40,19 +40,7 @@ public class HashMap implements Map { } public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("{"); - for (Iterator> it = iterator(); it.hasNext();) { - Entry e = it.next(); - sb.append(e.getKey()) - .append("=") - .append(e.getValue()); - if (it.hasNext()) { - sb.append(","); - } - } - sb.append("}"); - return sb.toString(); + return Collections.toString(this); } private static int nextPowerOfTwo(int n) { @@ -324,7 +312,8 @@ public class HashMap implements Map { } public boolean contains(Object o) { - return (o instanceof Entry) ? containsKey(((Entry)o).getKey()) : false; + return (o instanceof Entry) + && containsKey(((Entry)o).getKey()); } public boolean add(Entry e) { @@ -337,9 +326,9 @@ public class HashMap implements Map { return change; } - public boolean remove(Object o) { - return (o instanceof Entry) ? remove((Entry)o) : false; - } + public boolean remove(Object o) { + return (o instanceof Entry) && remove((Entry)o); + } public boolean remove(Entry e) { return removeCell(e.getKey()) != null; @@ -394,11 +383,10 @@ public class HashMap implements Map { } public Iterator iterator() { - return new KeyIterator(new MyIterator()); + return new Collections.KeyIterator(new MyIterator()); } } - private class Values implements Collection { public int size() { return HashMap.this.size(); @@ -433,7 +421,7 @@ public class HashMap implements Map { } public Iterator iterator() { - return new ValueIterator(new MyIterator()); + return new Collections.ValueIterator(new MyIterator()); } } @@ -495,44 +483,4 @@ public class HashMap implements Map { } } } - - private static class KeyIterator implements Iterator { - private final Iterator> it; - - public KeyIterator(Iterator> it) { - this.it = it; - } - - public K next() { - return it.next().getKey(); - } - - public boolean hasNext() { - return it.hasNext(); - } - - public void remove() { - it.remove(); - } - } - - private static class ValueIterator implements Iterator { - private final Iterator> it; - - public ValueIterator(Iterator> it) { - this.it = it; - } - - public V next() { - return it.next().getValue(); - } - - public boolean hasNext() { - return it.hasNext(); - } - - public void remove() { - it.remove(); - } - } } diff --git a/classpath/java/util/TreeMap.java b/classpath/java/util/TreeMap.java new file mode 100644 index 0000000000..d08bd4958d --- /dev/null +++ b/classpath/java/util/TreeMap.java @@ -0,0 +1,197 @@ +/* Copyright (c) 2008, 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 class TreeMap implements Map { + private TreeSet> set; + + public TreeMap(final Comparator comparator) { + set = new TreeSet(new Comparator>() { + public int compare(MyEntry a, MyEntry b) { + return comparator.compare(a.key, b.key); + } + }); + } + + public TreeMap() { + this(new Comparator() { + public int compare(K a, K b) { + return ((Comparable) a).compareTo(b); + } + }); + } + + public String toString() { + return Collections.toString(this); + } + + public V get(Object key) { + MyEntry e = set.find(new MyEntry(key, null)); + return e == null ? null : e.value; + } + + public V put(K key, V value) { + MyEntry e = set.addAndReplace(new MyEntry(key, value)); + return e == null ? null : e.value; + } + + public void putAll(Map elts) { + for (Map.Entry entry : elts.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + public V remove(Object key) { + MyEntry e = set.removeAndReturn(new MyEntry(key, null)); + return e == null ? null : e.value; + } + + public void clear() { + set.clear(); + } + + public int size() { + return set.size(); + } + + public boolean isEmpty() { + return size() == 0; + } + + public boolean containsKey(Object key) { + return set.contains(new MyEntry(key, null)); + } + + private boolean equal(Object a, Object b) { + return a == null ? b == null : a.equals(b); + } + + public boolean containsValue(Object value) { + for (V v: values()) { + if (equal(v, value)) { + return true; + } + } + return false; + } + + public Set> entrySet() { + return (Set>) (Set) set; + } + + public Set keySet() { + return new KeySet(); + } + + public Collection values() { + return new Values(); + } + + private static class MyEntry implements Entry { + public final K key; + public V value; + + public MyEntry(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } + } + + private class KeySet implements Set { + public int size() { + return TreeMap.this.size(); + } + + public boolean isEmpty() { + return TreeMap.this.isEmpty(); + } + + public boolean contains(Object key) { + return containsKey(key); + } + + public boolean add(K key) { + return set.addAndReplace(new MyEntry(key, null)) != null; + } + + public boolean addAll(Collection collection) { + boolean change = false; + for (K k: collection) if (add(k)) change = true; + return change; + } + + public boolean remove(Object key) { + return set.removeAndReturn(new MyEntry(key, null)) != null; + } + + public T[] toArray(T[] array) { + return Collections.toArray(this, array); + } + + public void clear() { + TreeMap.this.clear(); + } + + public Iterator iterator() { + return new Collections.KeyIterator(set.iterator()); + } + } + + private class Values implements Collection { + public int size() { + return TreeMap.this.size(); + } + + public boolean isEmpty() { + return TreeMap.this.isEmpty(); + } + + public boolean contains(Object value) { + return containsValue(value); + } + + public boolean add(V value) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object value) { + throw new UnsupportedOperationException(); + } + + public T[] toArray(T[] array) { + return Collections.toArray(this, array); + } + + public void clear() { + TreeMap.this.clear(); + } + + public Iterator iterator() { + return new Collections.ValueIterator(set.iterator()); + } + } +} diff --git a/classpath/java/util/TreeSet.java b/classpath/java/util/TreeSet.java index 4940eb0d22..3c63160b99 100644 --- a/classpath/java/util/TreeSet.java +++ b/classpath/java/util/TreeSet.java @@ -10,7 +10,7 @@ package java.util; -public class TreeSet extends AbstractSet implements Collection { +public class TreeSet extends AbstractSet implements Collection { private PersistentSet> set; private int size; @@ -49,34 +49,52 @@ public class TreeSet extends AbstractSet implements Collection { return false; } - // Used by hashMaps for replacement - public void addAndReplace(T value) { + T addAndReplace(T value) { PersistentSet.Path> p = set.find(new Cell(value, null)); if (p.fresh()) { set = p.add(); ++size; + return null; } else { + T old = p.value().value; set = p.replaceWith(new Cell(value, null)); + return old; } } - public boolean remove(Object value) { + T find(T value) { + PersistentSet.Path> p = set.find(new Cell(value, null)); + return p.fresh() ? null : p.value().value; + } + + T removeAndReturn(T value) { + Cell cell = removeCell(value); + return cell == null ? null : cell.value; + } + + private Cell removeCell(Object value) { PersistentSet.Path> p = set.find(new Cell(value, null)); if (p.fresh()) { - return false; + return null; } else { --size; + Cell old = p.value(); + if (p.value().next != null) { set = p.replaceWith(p.value().next); } else { set = p.remove(); } - return true; + return old; } } + public boolean remove(Object value) { + return removeCell(value) != null; + } + public int size() { return size; } diff --git a/test/Tree.java b/test/Tree.java index 5d4ad83d0c..55858ab8d7 100644 --- a/test/Tree.java +++ b/test/Tree.java @@ -1,5 +1,8 @@ import java.util.Comparator; import java.util.TreeSet; +import java.util.TreeMap; +import java.util.Map; +import java.util.Iterator; public class Tree { private static void expect(boolean v) { @@ -17,6 +20,21 @@ public class Tree { return sb.toString(); } + private static String printMap(TreeMap map) { + StringBuilder sb = new StringBuilder(); + + for (Iterator it = map.entrySet().iterator(); it.hasNext();) { + Map.Entry e = it.next(); + sb.append(e.getKey()); + sb.append("="); + sb.append(e.getValue()); + if (it.hasNext()) { + sb.append(", "); + } + } + return sb.toString(); + } + private static void isEqual(String s1, String s2) { System.out.println(s1); expect(s1.equals(s2)); @@ -53,5 +71,43 @@ public class Tree { expect(t2.size() == 6); t2.add("kappa"); isEqual(printList(t2), "999, five, four, kappa, one, three, two"); + + TreeMap map = new TreeMap + (new Comparator() { + public int compare(String s1, String s2) { + return s1.compareTo(s2); + } + }); + + map.put("q", "Q"); + map.put("a", "A"); + map.put("b", "B"); + map.put("z", "Z"); + map.put("c", "C"); + map.put("y", "Y"); + + isEqual(printMap(map), "a=A, b=B, c=C, q=Q, y=Y, z=Z"); + } + + private static class MyEntry implements Map.Entry { + public final K key; + public V value; + + public MyEntry(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } } }