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; 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) diff --git a/makefile b/makefile index eab488d091..90ea95aecb 100644 --- a/makefile +++ b/makefile @@ -59,7 +59,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]\" diff --git a/src/compile.cpp b/src/compile.cpp index d0e4dcc2cb..055106f334 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5338,7 +5338,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/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* diff --git a/src/machine.cpp b/src/machine.cpp index 8e53e35d6a..ab1bff60f0 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; @@ -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); @@ -1703,7 +1697,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 +1723,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 +1864,7 @@ Thread::dispose() systemThread->dispose(); } - m->heap->free(defaultHeap, Thread::HeapSizeInBytes); + m->heap->free(defaultHeap, ThreadHeapSizeInBytes); m->processor->dispose(this); } @@ -2028,7 +2022,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 +2041,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); } @@ -2058,26 +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); } - - if (type == Machine::FixedAllocation) { - if (t->m->fixedFootprint + sizeInBytes - > Machine::FixedFootprintThresholdInBytes) + + switch (type) { + case Machine::MovableAllocation: + if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + > ThreadHeapSizeInWords) { t->heap = 0; - } - } else if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) - > Thread::HeapSizeInWords) - { - t->heap = 0; - if (t->m->heapPoolIndex < Machine::HeapPoolSize) { - t->heap = static_cast - (t->m->heap->tryAllocate(Thread::HeapSizeInBytes)); - if (t->heap) { - t->m->heapPool[t->m->heapPoolIndex++] = t->heap; - t->heapOffset += t->heapIndex; - t->heapIndex = 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::FixedAllocation: + if (t->m->fixedFootprint + sizeInBytes > FixedFootprintThresholdInBytes) { + t->heap = 0; + } + break; + + case Machine::ImmortalAllocation: + break; } if (t->heap == 0) { @@ -2758,7 +2759,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 2dab96f273..7b1e5a99ed 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 = 64; + +const unsigned FixedFootprintThresholdInBytes += ThreadHeapPoolSize * ThreadHeapSizeInBytes; + enum FieldCode { VoidField, ByteField, @@ -1144,10 +1152,6 @@ class Machine { dispose(); } - static const unsigned HeapPoolSize = 8; - - static const unsigned FixedFootprintThresholdInBytes = 256 * 1024; - void dispose(); JavaVMVTable* vtable; @@ -1184,7 +1188,7 @@ class Machine { bool unsafe; JavaVMVTable javaVMVTable; JNIEnvVTable jniEnvVTable; - uintptr_t* heapPool[HeapPoolSize]; + uintptr_t* heapPool[ThreadHeapPoolSize]; unsigned heapPoolIndex; }; @@ -1282,9 +1286,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(); @@ -1452,7 +1453,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 @@ -1484,7 +1485,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); diff --git a/src/types.def b/src/types.def index bfe450e16a..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) @@ -95,12 +90,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 219695a536..f149e9c2e2 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), true); + 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)), false); + 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), true); + 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)), false); + 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 } @@ -442,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) { @@ -541,16 +547,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..ea8fc8b09c 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,10 +89,58 @@ 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)); +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