From e98da8440e21e7ebeaee814d3506152f8a54714b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 19 Nov 2008 18:09:02 -0700 Subject: [PATCH 01/10] minor tweak to find function in heapdump.cpp to return 0 where we were returning false (which amounts to the same thing but is less confusing) --- src/heapdump.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/heapdump.cpp b/src/heapdump.cpp index 6d17d82e5a..617d1d2e74 100644 --- a/src/heapdump.cpp +++ b/src/heapdump.cpp @@ -133,7 +133,7 @@ hash(object p, unsigned capacity) Set::Entry* find(Context* c, object p) { - if (c->objects == 0) return false; + if (c->objects == 0) return 0; for (int i = c->objects->index[hash(p, c->objects->capacity)]; i >= 0;) { Set::Entry* e = c->objects->entries + i; @@ -143,7 +143,7 @@ find(Context* c, object p) i = e->next; } - return false; + return 0; } Set::Entry* From 15ea90cd0c3a384163fcbe5469d87a3612f0b13d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 19 Nov 2008 18:10:29 -0700 Subject: [PATCH 02/10] specify -fno-omit-frame-pointer to ease debugging and profiling --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 3b2cbca49e..3e4b0e989a 100644 --- a/makefile +++ b/makefile @@ -56,7 +56,7 @@ rdynamic = -rdynamic warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \ -Wno-non-virtual-dtor -common-cflags = $(warnings) -fno-rtti -fno-exceptions \ +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)\" \ -DBOOT_CLASSPATH=\"[classpathJar]\" From 2e2925c32145913d19c928c580050fef4b78ce5b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 22 Nov 2008 14:14:52 -0700 Subject: [PATCH 03/10] fix backwards logic in treeMapInsert which prevented correct balancing --- src/util.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 219695a536..1963189dd5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -143,7 +143,7 @@ treeAdd(Thread* t, object path) if (treeNodeRed (t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors))))) { - setTreeNodeRed(t, pairFirst(t, ancestors), true); + setTreeNodeRed(t, pairFirst(t, ancestors), false); object n = cloneTreeNode (t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors)))); @@ -154,7 +154,7 @@ treeAdd(Thread* t, object path) (t, treeNodeRight (t, pairFirst(t, pairSecond(t, ancestors))), false); - setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), false); + setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); new_ = pairFirst(t, pairSecond(t, ancestors)); ancestors = pairSecond(t, pairSecond(t, ancestors)); @@ -195,7 +195,7 @@ treeAdd(Thread* t, object path) if (treeNodeRed (t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors))))) { - setTreeNodeRed(t, pairFirst(t, ancestors), true); + setTreeNodeRed(t, pairFirst(t, ancestors), false); object n = cloneTreeNode (t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors)))); @@ -206,7 +206,7 @@ treeAdd(Thread* t, object path) (t, treeNodeLeft (t, pairFirst(t, pairSecond(t, ancestors))), false); - setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), false); + setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); new_ = pairFirst(t, pairSecond(t, ancestors)); ancestors = pairSecond(t, pairSecond(t, ancestors)); From 8a7852172e0aa62e88d4429fe381534edecd2d36 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 22 Nov 2008 14:47:18 -0700 Subject: [PATCH 04/10] increase heap pool size and fixed footprint threshold constants based on performance profiling and experimentation --- src/machine.cpp | 26 ++++++++++++-------------- src/machine.h | 21 +++++++++++---------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 713e4ac0e7..77da017d6f 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -482,9 +482,9 @@ void postCollect(Thread* t) { #ifdef VM_STRESS - t->m->heap->free(t->defaultHeap, Thread::HeapSizeInBytes); + t->m->heap->free(t->defaultHeap, ThreadHeapSizeInBytes); t->defaultHeap = static_cast - (t->m->heap->allocate(Thread::HeapSizeInBytes)); + (t->m->heap->allocate(ThreadHeapSizeInBytes)); #endif t->heap = t->defaultHeap; @@ -1703,7 +1703,7 @@ Machine::dispose() } for (unsigned i = 0; i < heapPoolIndex; ++i) { - heap->free(heapPool[i], Thread::HeapSizeInBytes); + heap->free(heapPool[i], ThreadHeapSizeInBytes); } heap->free(properties, sizeof(const char*) * propertyCount); @@ -1729,7 +1729,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): protector(0), runnable(this), defaultHeap(static_cast - (m->heap->allocate(HeapSizeInBytes))), + (m->heap->allocate(ThreadHeapSizeInBytes))), heap(defaultHeap), backupHeap(0), backupHeapIndex(0), @@ -1870,7 +1870,7 @@ Thread::dispose() systemThread->dispose(); } - m->heap->free(defaultHeap, Thread::HeapSizeInBytes); + m->heap->free(defaultHeap, ThreadHeapSizeInBytes); m->processor->dispose(this); } @@ -2028,7 +2028,7 @@ allocate2(Thread* t, unsigned sizeInBytes, bool objectMask) { return allocate3 (t, t->m->heap, - ceiling(sizeInBytes, BytesPerWord) > Thread::HeapSizeInWords ? + ceiling(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords ? Machine::FixedAllocation : Machine::MovableAllocation, sizeInBytes, objectMask); } @@ -2047,7 +2047,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, return o; } else if (t->tracing) { expect(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord) - <= Thread::HeapSizeInWords); + <= ThreadHeapSizeInWords); return allocateSmall(t, sizeInBytes); } @@ -2060,18 +2060,16 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, } if (type == Machine::FixedAllocation) { - if (t->m->fixedFootprint + sizeInBytes - > Machine::FixedFootprintThresholdInBytes) - { + if (t->m->fixedFootprint + sizeInBytes > FixedFootprintThresholdInBytes) { t->heap = 0; } } else if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) - > Thread::HeapSizeInWords) + > ThreadHeapSizeInWords) { t->heap = 0; - if (t->m->heapPoolIndex < Machine::HeapPoolSize) { + if (t->m->heapPoolIndex < ThreadHeapPoolSize) { t->heap = static_cast - (t->m->heap->tryAllocate(Thread::HeapSizeInBytes)); + (t->m->heap->tryAllocate(ThreadHeapSizeInBytes)); if (t->heap) { t->m->heapPool[t->m->heapPoolIndex++] = t->heap; t->heapOffset += t->heapIndex; @@ -2758,7 +2756,7 @@ collect(Thread* t, Heap::CollectionType type) killZombies(t, m->rootThread); for (unsigned i = 0; i < m->heapPoolIndex; ++i) { - m->heap->free(m->heapPool[i], Thread::HeapSizeInBytes); + m->heap->free(m->heapPool[i], ThreadHeapSizeInBytes); } m->heapPoolIndex = 0; diff --git a/src/machine.h b/src/machine.h index 3c12722c21..0fcf27d948 100644 --- a/src/machine.h +++ b/src/machine.h @@ -45,6 +45,14 @@ const uintptr_t HashTakenMark = 1; const uintptr_t ExtendedMark = 2; const uintptr_t FixedMark = 3; +const unsigned ThreadHeapSizeInBytes = 64 * 1024; +const unsigned ThreadHeapSizeInWords = ThreadHeapSizeInBytes / BytesPerWord; + +const unsigned ThreadHeapPoolSize = 32; + +const unsigned FixedFootprintThresholdInBytes += ThreadHeapPoolSize * ThreadHeapSizeInBytes; + enum FieldCode { VoidField, ByteField, @@ -1128,10 +1136,6 @@ class Machine { dispose(); } - static const unsigned HeapPoolSize = 8; - - static const unsigned FixedFootprintThresholdInBytes = 256 * 1024; - void dispose(); JavaVMVTable* vtable; @@ -1168,7 +1172,7 @@ class Machine { bool unsafe; JavaVMVTable javaVMVTable; JNIEnvVTable jniEnvVTable; - uintptr_t* heapPool[HeapPoolSize]; + uintptr_t* heapPool[ThreadHeapPoolSize]; unsigned heapPoolIndex; }; @@ -1266,9 +1270,6 @@ class Thread { Thread* t; }; - static const unsigned HeapSizeInBytes = 64 * 1024; - static const unsigned HeapSizeInWords = HeapSizeInBytes / BytesPerWord; - Thread(Machine* m, object javaThread, Thread* parent); void init(); @@ -1436,7 +1437,7 @@ inline void ensure(Thread* t, unsigned sizeInBytes) { if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) - > Thread::HeapSizeInWords) + > ThreadHeapSizeInWords) { expect(t, t->backupHeap == 0); t->backupHeap = static_cast @@ -1468,7 +1469,7 @@ allocate(Thread* t, unsigned sizeInBytes, bool objectMask) stress(t); if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord) - > Thread::HeapSizeInWords + > ThreadHeapSizeInWords or t->m->exclusive)) { return allocate2(t, sizeInBytes, objectMask); From 6162dfafbb48a108d55faee91ff6243690c2d533 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 22 Nov 2008 14:48:10 -0700 Subject: [PATCH 05/10] increase heap pool size and fixed footprint threshold constants based on performance profiling and experimentation (second try) --- src/machine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.h b/src/machine.h index 0fcf27d948..c340fa8f53 100644 --- a/src/machine.h +++ b/src/machine.h @@ -48,7 +48,7 @@ const uintptr_t FixedMark = 3; const unsigned ThreadHeapSizeInBytes = 64 * 1024; const unsigned ThreadHeapSizeInWords = ThreadHeapSizeInBytes / BytesPerWord; -const unsigned ThreadHeapPoolSize = 32; +const unsigned ThreadHeapPoolSize = 64; const unsigned FixedFootprintThresholdInBytes = ThreadHeapPoolSize * ThreadHeapSizeInBytes; From fccf906349f6b9e255512b8e7bcc6da09752c959 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 22 Nov 2008 15:32:53 -0700 Subject: [PATCH 06/10] add minimal java.net.Socket implementation to support Socket.setTcpNoDelay --- classpath/java-nio.cpp | 43 +++++++++++++++++++ classpath/java/net/Socket.java | 15 +++++++ classpath/java/net/SocketException.java | 23 ++++++++++ .../nio/channels/ServerSocketChannel.java | 16 +++++-- .../java/nio/channels/SocketChannel.java | 19 +++++++- 5 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 classpath/java/net/Socket.java create mode 100644 classpath/java/net/SocketException.java diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index 86eb9aa6c5..e5a0e345ff 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -26,6 +26,7 @@ # include # include # include +# include #endif #define java_nio_channels_SelectionKey_OP_READ 1L @@ -88,6 +89,26 @@ throwIOException(JNIEnv* e) throwIOException(e, errorString(e)); } +void +throwSocketException(JNIEnv* e, const char* s) +{ + throwNew(e, "java/net/SocketException", s); +} + +void +throwSocketException(JNIEnv* e, jbyteArray a) +{ + jbyte* s = static_cast(e->GetPrimitiveArrayCritical(a, 0)); + throwSocketException(e, reinterpret_cast(s)); + e->ReleasePrimitiveArrayCritical(a, s, 0); +} + +void +throwSocketException(JNIEnv* e) +{ + throwSocketException(e, errorString(e)); +} + void init(JNIEnv* e, sockaddr_in* address, jstring hostString, jint port) { @@ -152,6 +173,19 @@ makeNonblocking(JNIEnv* e, int d) return true; } +bool +setTcpNoDelay(JNIEnv* e, int d, bool on) +{ + int flag = on; + int r = setsockopt + (d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&flag), sizeof(int)); + if (r < 0) { + throwSocketException(e); + return false; + } + return true; +} + void doListen(JNIEnv* e, int s, sockaddr_in* address) { @@ -277,6 +311,15 @@ Java_java_nio_channels_ServerSocketChannel_natDoListen(JNIEnv *e, return s; } +extern "C" JNIEXPORT void JNICALL +Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv *e, + jclass, + jint socket, + jboolean on) +{ + setTcpNoDelay(e, socket, on); +} + extern "C" JNIEXPORT jint JNICALL Java_java_nio_channels_SocketChannel_natDoConnect(JNIEnv *e, jclass, diff --git a/classpath/java/net/Socket.java b/classpath/java/net/Socket.java new file mode 100644 index 0000000000..602b24a19e --- /dev/null +++ b/classpath/java/net/Socket.java @@ -0,0 +1,15 @@ +/* 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.net; + +public abstract class Socket { + public abstract void setTcpNoDelay(boolean on) throws SocketException; +} diff --git a/classpath/java/net/SocketException.java b/classpath/java/net/SocketException.java new file mode 100644 index 0000000000..f0a9ee2ac3 --- /dev/null +++ b/classpath/java/net/SocketException.java @@ -0,0 +1,23 @@ +/* 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.net; + +import java.io.IOException; + +public class SocketException extends IOException { + public SocketException(String message) { + super(message); + } + + public SocketException() { + this(null); + } +} diff --git a/classpath/java/nio/channels/ServerSocketChannel.java b/classpath/java/nio/channels/ServerSocketChannel.java index c1311b5116..f84c9626bc 100644 --- a/classpath/java/nio/channels/ServerSocketChannel.java +++ b/classpath/java/nio/channels/ServerSocketChannel.java @@ -16,11 +16,21 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.ServerSocket; -public class ServerSocketChannel extends SocketChannel { +public class ServerSocketChannel extends SelectableChannel { + private final SocketChannel channel = new SocketChannel(); + public static ServerSocketChannel open() { return new ServerSocketChannel(); } + public SelectableChannel configureBlocking(boolean v) { + return channel.configureBlocking(v); + } + + public void close() throws IOException { + channel.close(); + } + public SocketChannel accept() throws Exception { SocketChannel c = new SocketChannel(); c.socket = doAccept(); @@ -33,7 +43,7 @@ public class ServerSocketChannel extends SocketChannel { } private int doAccept() throws IOException { - return natDoAccept(socket); + return natDoAccept(channel.socket); } private int doListen(String host, int port) throws IOException { @@ -50,7 +60,7 @@ public class ServerSocketChannel extends SocketChannel { } catch (ClassCastException e) { throw new IllegalArgumentException(); } - socket = doListen(a.getHostName(), a.getPort()); + channel.socket = doListen(a.getHostName(), a.getPort()); } } diff --git a/classpath/java/nio/channels/SocketChannel.java b/classpath/java/nio/channels/SocketChannel.java index cc4b2abb90..aa723030db 100644 --- a/classpath/java/nio/channels/SocketChannel.java +++ b/classpath/java/nio/channels/SocketChannel.java @@ -11,8 +11,10 @@ package java.nio.channels; import java.io.IOException; +import java.net.SocketException; import java.net.SocketAddress; import java.net.InetSocketAddress; +import java.net.Socket; import java.nio.ByteBuffer; public class SocketChannel extends SelectableChannel @@ -20,8 +22,8 @@ public class SocketChannel extends SelectableChannel { public static final int InvalidSocket = -1; - protected int socket = InvalidSocket; - protected boolean connected = false; + int socket = InvalidSocket; + boolean connected = false; public static SocketChannel open() { return new SocketChannel(); @@ -32,6 +34,10 @@ public class SocketChannel extends SelectableChannel return this; } + public Socket socket() { + return new Handle(); + } + public boolean connect(SocketAddress address) throws Exception { InetSocketAddress a; try { @@ -87,6 +93,15 @@ public class SocketChannel extends SelectableChannel return socket; } + public class Handle extends Socket { + public void setTcpNoDelay(boolean on) throws SocketException { + natSetTcpNoDelay(socket, on); + } + } + + private static native void natSetTcpNoDelay(int socket, boolean on) + throws SocketException; + private static native int natDoConnect(String host, int port, boolean[] connected) throws Exception; private static native int natRead(int socket, byte[] buffer, int offset, int length) From 4392b04fd02029c8ae2314a4b525c36257335fb3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 22 Nov 2008 16:25:35 -0700 Subject: [PATCH 07/10] avoid creating unecessary garbage in treeInsertNode and friends --- src/compile.cpp | 2 +- src/types.def | 6 -- src/util.cpp | 196 +++++++++++++++++++++++++++++------------------- src/util.h | 3 +- 4 files changed, 122 insertions(+), 85 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 3fe7873a51..3bbf94bcec 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5205,7 +5205,7 @@ compile(MyThread* t, object method) PROTECT(t, node); methodTree(t) = treeInsertNode - (t, methodTree(t), reinterpret_cast + (t, &(context.zone), methodTree(t), reinterpret_cast (&singletonValue(t, compiled, 0)), node, methodTreeSentinal(t), compareIpToMethodBounds); } diff --git a/src/types.def b/src/types.def index bfe450e16a..f1668191f9 100644 --- a/src/types.def +++ b/src/types.def @@ -95,12 +95,6 @@ (object value) (object left) (object right)) - -(type treePath - (uintptr_t fresh) - (object node) - (object root) - (object ancestors)) (type callNode (intptr_t address) diff --git a/src/util.cpp b/src/util.cpp index 1963189dd5..663932cb04 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -14,6 +14,54 @@ using namespace vm; namespace { +class TreeContext { + public: + class Path { + public: + Path(object node, Path* next): node(node), next(next) { } + + object node; + Path* next; + }; + + class MyProtector: public Thread::Protector { + public: + MyProtector(Thread* thread, TreeContext* context): + Protector(thread), context(context) + { } + + virtual void visit(Heap::Visitor* v) { + v->visit(&(context->root)); + v->visit(&(context->node)); + + for (Path* p = context->ancestors; p; p = p->next) { + v->visit(&(p->node)); + } + } + + TreeContext* context; + }; + + TreeContext(Thread* thread, Zone* zone): + zone(zone), root(0), node(0), ancestors(0), protector(thread, this), + fresh(false) + { } + + Zone* zone; + object root; + object node; + Path* ancestors; + MyProtector protector; + bool fresh; +}; + +TreeContext::Path* +path(TreeContext* c, object node, TreeContext::Path* next) +{ + return new (c->zone->allocate(sizeof(TreeContext::Path))) + TreeContext::Path(node, next); +} + inline object getTreeNodeValue(Thread*, object n) { @@ -58,8 +106,9 @@ cloneTreeNode(Thread* t, object n) return newNode; } -object -treeFind(Thread* t, object old, intptr_t key, object node, object sentinal, +void +treeFind(Thread* t, TreeContext* c, object old, intptr_t key, object node, + object sentinal, intptr_t (*compare)(Thread* t, intptr_t key, object b)) { PROTECT(t, old); @@ -72,11 +121,8 @@ treeFind(Thread* t, object old, intptr_t key, object node, object sentinal, object new_ = newRoot; PROTECT(t, new_); - object ancestors = 0; - PROTECT(t, ancestors); - while (old != sentinal) { - ancestors = makePair(t, new_, ancestors); + c->ancestors = path(c, new_, c->ancestors); intptr_t difference = compare(t, key, getTreeNodeValue(t, old)); @@ -91,13 +137,20 @@ treeFind(Thread* t, object old, intptr_t key, object node, object sentinal, set(t, new_, TreeNodeRight, n); new_ = n; } else { - return makeTreePath(t, false, new_, newRoot, pairSecond(t, ancestors)); + c->fresh = false; + c->root = newRoot; + c->node = new_; + c->ancestors = c->ancestors->next; + return; } } setTreeNodeValue(t, new_, getTreeNodeValue(t, node)); - return makeTreePath(t, true, new_, newRoot, ancestors); + c->fresh = true; + c->root = newRoot; + c->node = new_; + c->ancestors = c->ancestors; } object @@ -123,122 +176,109 @@ rightRotate(Thread* t, object n) } object -treeAdd(Thread* t, object path) +treeAdd(Thread* t, TreeContext* c) { - object new_ = treePathNode(t, path); + object new_ = c->node; PROTECT(t, new_); - object newRoot = treePathRoot(t, path); + object newRoot = c->root; PROTECT(t, newRoot); - object ancestors = treePathAncestors(t, path); - PROTECT(t, ancestors); - // rebalance setTreeNodeRed(t, new_, true); - while (ancestors != 0 and treeNodeRed(t, pairFirst(t, ancestors))) { - if (pairFirst(t, ancestors) - == treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors)))) + while (c->ancestors != 0 and treeNodeRed(t, c->ancestors->node)) { + if (c->ancestors->node + == treeNodeLeft(t, c->ancestors->next->node)) { if (treeNodeRed - (t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors))))) + (t, treeNodeRight(t, c->ancestors->next->node))) { - setTreeNodeRed(t, pairFirst(t, ancestors), false); + setTreeNodeRed(t, c->ancestors->node, false); object n = cloneTreeNode - (t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors)))); + (t, treeNodeRight(t, c->ancestors->next->node)); - set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeRight, n); + set(t, c->ancestors->next->node, TreeNodeRight, n); - setTreeNodeRed - (t, treeNodeRight - (t, pairFirst(t, pairSecond(t, ancestors))), false); + setTreeNodeRed(t, treeNodeRight(t, c->ancestors->next->node), false); - setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); + setTreeNodeRed(t, c->ancestors->next->node, true); - new_ = pairFirst(t, pairSecond(t, ancestors)); - ancestors = pairSecond(t, pairSecond(t, ancestors)); + new_ = c->ancestors->next->node; + c->ancestors = c->ancestors->next->next; } else { - if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) { - new_ = pairFirst(t, ancestors); - ancestors = pairSecond(t, ancestors); + if (new_ == treeNodeRight(t, c->ancestors->node)) { + new_ = c->ancestors->node; + c->ancestors = c->ancestors->next; object n = leftRotate(t, new_); - if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) { - set(t, pairFirst(t, ancestors), TreeNodeRight, n); + if (new_ == treeNodeRight(t, c->ancestors->node)) { + set(t, c->ancestors->node, TreeNodeRight, n); } else { - set(t, pairFirst(t, ancestors), TreeNodeLeft, n); + set(t, c->ancestors->node, TreeNodeLeft, n); } - ancestors = makePair(t, n, ancestors); + c->ancestors = path(c, n, c->ancestors); } - setTreeNodeRed(t, pairFirst(t, ancestors), false); - setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); + setTreeNodeRed(t, c->ancestors->node, false); + setTreeNodeRed(t, c->ancestors->next->node, true); - object n = rightRotate(t, pairFirst(t, pairSecond(t, ancestors))); - if (pairSecond(t, pairSecond(t, ancestors)) == 0) { + object n = rightRotate(t, c->ancestors->next->node); + if (c->ancestors->next->next == 0) { newRoot = n; - } else if (treeNodeRight - (t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors)))) - == pairFirst(t, pairSecond(t, ancestors))) + } else if (treeNodeRight(t, c->ancestors->next->next->node) + == c->ancestors->next->node) { - set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))), - TreeNodeRight, n); + set(t, c->ancestors->next->next->node, TreeNodeRight, n); } else { - set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))), - TreeNodeLeft, n); + set(t, c->ancestors->next->next->node, TreeNodeLeft, n); } // done } } else { // this is just the reverse of the code above (right and // left swapped): if (treeNodeRed - (t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors))))) + (t, treeNodeLeft(t, c->ancestors->next->node))) { - setTreeNodeRed(t, pairFirst(t, ancestors), false); + setTreeNodeRed(t, c->ancestors->node, false); object n = cloneTreeNode - (t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors)))); + (t, treeNodeLeft(t, c->ancestors->next->node)); - set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeLeft, n); + set(t, c->ancestors->next->node, TreeNodeLeft, n); - setTreeNodeRed - (t, treeNodeLeft - (t, pairFirst(t, pairSecond(t, ancestors))), false); + setTreeNodeRed(t, treeNodeLeft(t, c->ancestors->next->node), false); - setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); + setTreeNodeRed(t, c->ancestors->next->node, true); - new_ = pairFirst(t, pairSecond(t, ancestors)); - ancestors = pairSecond(t, pairSecond(t, ancestors)); + new_ = c->ancestors->next->node; + c->ancestors = c->ancestors->next->next; } else { - if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) { - new_ = pairFirst(t, ancestors); - ancestors = pairSecond(t, ancestors); + if (new_ == treeNodeLeft(t, c->ancestors->node)) { + new_ = c->ancestors->node; + c->ancestors = c->ancestors->next; object n = rightRotate(t, new_); - if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) { - set(t, pairFirst(t, ancestors), TreeNodeLeft, n); + if (new_ == treeNodeLeft(t, c->ancestors->node)) { + set(t, c->ancestors->node, TreeNodeLeft, n); } else { - set(t, pairFirst(t, ancestors), TreeNodeRight, n); + set(t, c->ancestors->node, TreeNodeRight, n); } - ancestors = makePair(t, n, ancestors); + c->ancestors = path(c, n, c->ancestors); } - setTreeNodeRed(t, pairFirst(t, ancestors), false); - setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); + setTreeNodeRed(t, c->ancestors->node, false); + setTreeNodeRed(t, c->ancestors->next->node, true); - object n = leftRotate(t, pairFirst(t, pairSecond(t, ancestors))); - if (pairSecond(t, pairSecond(t, ancestors)) == 0) { + object n = leftRotate(t, c->ancestors->next->node); + if (c->ancestors->next->next == 0) { newRoot = n; - } else if (treeNodeLeft - (t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors)))) - == pairFirst(t, pairSecond(t, ancestors))) + } else if (treeNodeLeft(t, c->ancestors->next->next->node) + == c->ancestors->next->node) { - set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))), - TreeNodeLeft, n); + set(t, c->ancestors->next->next->node, TreeNodeLeft, n); } else { - set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))), - TreeNodeRight, n); + set(t, c->ancestors->next->next->node, TreeNodeRight, n); } // done } @@ -541,16 +581,18 @@ treeQuery(Thread* t, object tree, intptr_t key, object sentinal, } object -treeInsertNode(Thread* t, object tree, intptr_t key, object node, +treeInsertNode(Thread* t, Zone* zone, object tree, intptr_t key, object node, object sentinal, intptr_t (*compare)(Thread* t, intptr_t key, object b)) { PROTECT(t, tree); PROTECT(t, sentinal); - object path = treeFind(t, tree, key, node, sentinal, compare); - expect(t, treePathFresh(t, path)); - return treeAdd(t, path); + TreeContext c(t, zone); + treeFind(t, &c, tree, key, node, sentinal, compare); + expect(t, c.fresh); + + return treeAdd(t, &c); } } // namespace vm diff --git a/src/util.h b/src/util.h index adf8487723..76ac291ebf 100644 --- a/src/util.h +++ b/src/util.h @@ -12,6 +12,7 @@ #define UTIL_H #include "machine.h" +#include "zone.h" namespace vm { @@ -88,7 +89,7 @@ treeQuery(Thread* t, object tree, intptr_t key, object sentinal, intptr_t (*compare)(Thread* t, intptr_t key, object b)); object -treeInsertNode(Thread* t, object tree, intptr_t key, object node, +treeInsertNode(Thread* t, Zone* zone, object tree, intptr_t key, object node, object sentinal, intptr_t (*compare)(Thread* t, intptr_t key, object b)); From fb9b2bf1733932f33d67df9a9a67a6f7ab5de515 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 22 Nov 2008 16:38:41 -0700 Subject: [PATCH 08/10] avoid creating garbage when iterating over hashmaps --- src/machine.cpp | 14 ++++---------- src/types.def | 5 ----- src/util.cpp | 34 ---------------------------------- src/util.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 49 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 77da017d6f..d0d40de11d 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -770,12 +770,8 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool) PROTECT(t, interfaceTable); unsigned i = 0; - object it = hashMapIterator(t, map); - PROTECT(t, it); - - for (; it; it = hashMapIteratorNext(t, it)) { - object interface = resolveClass - (t, tripleFirst(t, hashMapIteratorNode(t, it))); + for (HashMapIterator it(t, map); it.hasMore();) { + object interface = resolveClass(t, tripleFirst(t, it.next())); if (UNLIKELY(t->exception)) return; set(t, interfaceTable, ArrayBody + (i * BytesPerWord), interface); @@ -1243,10 +1239,8 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) if (classFlags(t, class_) & ACC_INTERFACE) { PROTECT(t, vtable); - for (object it = hashMapIterator(t, virtualMap); it; - it = hashMapIteratorNext(t, it)) - { - object method = tripleFirst(t, hashMapIteratorNode(t, it)); + for (HashMapIterator it(t, virtualMap); it.hasMore();) { + object method = tripleFirst(t, it.next()); assert(t, arrayBody(t, vtable, methodOffset(t, method)) == 0); set(t, vtable, ArrayBody + (methodOffset(t, method) * BytesPerWord), method); diff --git a/src/types.def b/src/types.def index f1668191f9..1fadf50e39 100644 --- a/src/types.def +++ b/src/types.def @@ -73,11 +73,6 @@ (type weakHashMap (extends hashMap)) -(type hashMapIterator - (object map) - (object node) - (unsigned index)) - (type list (uint32_t size) (object front) diff --git a/src/util.cpp b/src/util.cpp index 663932cb04..f149e9c2e2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -482,40 +482,6 @@ hashMapRemove(Thread* t, object map, object key, return o; } -object -hashMapIterator(Thread* t, object map) -{ - object array = hashMapArray(t, map); - if (array) { - for (unsigned i = 0; i < arrayLength(t, array); ++i) { - if (arrayBody(t, array, i)) { - return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1); - } - } - } - return 0; -} - -object -hashMapIteratorNext(Thread* t, object it) -{ - object map = hashMapIteratorMap(t, it); - object node = hashMapIteratorNode(t, it); - unsigned index = hashMapIteratorIndex(t, it); - - if (tripleThird(t, node)) { - return makeHashMapIterator(t, map, tripleThird(t, node), index); - } else { - object array = hashMapArray(t, map); - for (unsigned i = index; i < arrayLength(t, array); ++i) { - if (arrayBody(t, array, i)) { - return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1); - } - } - return 0; - } -} - void listAppend(Thread* t, object list, object value) { diff --git a/src/util.h b/src/util.h index 76ac291ebf..ea8fc8b09c 100644 --- a/src/util.h +++ b/src/util.h @@ -93,6 +93,54 @@ treeInsertNode(Thread* t, Zone* zone, object tree, intptr_t key, object node, object sentinal, intptr_t (*compare)(Thread* t, intptr_t key, object b)); +class HashMapIterator: public Thread::Protector { + public: + HashMapIterator(Thread* t, object map): + Protector(t), map(map), node(0), index(0) + { + find(); + } + + void find() { + object array = hashMapArray(t, map); + for (unsigned i = index; i < arrayLength(t, array); ++i) { + if (arrayBody(t, array, i)) { + node = arrayBody(t, array, i); + index = i + 1; + return; + } + } + node = 0; + } + + bool hasMore() { + return node != 0; + } + + object next() { + if (node) { + object n = node; + if (tripleThird(t, node)) { + node = tripleThird(t, node); + } else { + find(); + } + return n; + } else { + return 0; + } + } + + virtual void visit(Heap::Visitor* v) { + v->visit(&map); + v->visit(&node); + } + + object map; + object node; + unsigned index; +}; + } // vm #endif//UTIL_H From 207f093464f56c8f84489a0cf1fc08b738a18257 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 23 Nov 2008 11:48:39 -0700 Subject: [PATCH 09/10] never trigger a GC due to an immortal allocation --- src/machine.cpp | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index d0d40de11d..3624767412 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2052,24 +2052,33 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, // collection or some other reason. We give it a chance here. ENTER(t, Thread::IdleState); } + + switch (type) { + case Machine::MovableAllocation: + if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + > ThreadHeapSizeInWords) + { + t->heap = 0; + if (t->m->heapPoolIndex < ThreadHeapPoolSize) { + t->heap = static_cast + (t->m->heap->tryAllocate(ThreadHeapSizeInBytes)); + if (t->heap) { + t->m->heapPool[t->m->heapPoolIndex++] = t->heap; + t->heapOffset += t->heapIndex; + t->heapIndex = 0; + } + } + } + break; - if (type == Machine::FixedAllocation) { + case Machine::FixedAllocation: if (t->m->fixedFootprint + sizeInBytes > FixedFootprintThresholdInBytes) { t->heap = 0; } - } else if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) - > ThreadHeapSizeInWords) - { - t->heap = 0; - if (t->m->heapPoolIndex < ThreadHeapPoolSize) { - t->heap = static_cast - (t->m->heap->tryAllocate(ThreadHeapSizeInBytes)); - if (t->heap) { - t->m->heapPool[t->m->heapPoolIndex++] = t->heap; - t->heapOffset += t->heapIndex; - t->heapIndex = 0; - } - } + break; + + case Machine::ImmortalAllocation: + break; } if (t->heap == 0) { From a3c8a0460dc3fd2ed9a4df44229dce9033d1ffbe Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 24 Nov 2008 17:03:00 -0700 Subject: [PATCH 10/10] silence GCC 4.3.2 warning in Java_java_lang_Runtime_exec --- classpath/java-lang.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 5fd06cc8fe..8825b8ffa3 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -267,7 +267,7 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass, // Error if here char c = errno; - write(msg[1], &c, 1); + ssize_t rv UNUSED = write(msg[1], &c, 1); exit(127); } break;