Merge branch 'master' of oss.readytalk.com:/var/local/git/avian into bootimage

Conflicts:

	src/compile.cpp
	src/machine.h
	src/util.h
This commit is contained in:
Joel Dice 2008-11-23 17:02:34 -07:00
commit 035aa0ecd4
11 changed files with 279 additions and 125 deletions

View File

@ -26,6 +26,7 @@
# include <errno.h>
# include <netdb.h>
# include <sys/select.h>
# include <netinet/tcp.h>
#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<jbyte*>(e->GetPrimitiveArrayCritical(a, 0));
throwSocketException(e, reinterpret_cast<const char*>(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<char*>(&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,

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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)

View File

@ -5347,8 +5347,9 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
PROTECT(t, node);
methodTree(t) = treeInsertNode
(t, methodTree(t), reinterpret_cast<intptr_t>(compiled), node,
methodTreeSentinal(t), compareIpToMethodBounds);
(t, &(context.zone), methodTree(t),
reinterpret_cast<intptr_t>(compiled), node, methodTreeSentinal(t),
compareIpToMethodBounds);
}
methodCompiled(t, method) = reinterpret_cast<intptr_t>(compiled);

View File

@ -450,9 +450,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<uintptr_t*>
(t->m->heap->allocate(Thread::HeapSizeInBytes));
(t->m->heap->allocate(ThreadHeapSizeInBytes));
#endif
t->heap = t->defaultHeap;
@ -1665,7 +1665,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);
@ -1691,7 +1691,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
protector(0),
runnable(this),
defaultHeap(static_cast<uintptr_t*>
(m->heap->allocate(HeapSizeInBytes))),
(m->heap->allocate(ThreadHeapSizeInBytes))),
heap(defaultHeap),
backupHeap(0),
backupHeapIndex(0),
@ -1832,7 +1832,7 @@ Thread::dispose()
systemThread->dispose();
}
m->heap->free(defaultHeap, Thread::HeapSizeInBytes);
m->heap->free(defaultHeap, ThreadHeapSizeInBytes);
m->processor->dispose(this);
}
@ -1990,7 +1990,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);
}
@ -2009,7 +2009,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);
}
@ -2020,26 +2020,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<uintptr_t*>
(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<uintptr_t*>
(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) {
@ -2720,7 +2727,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;

View File

@ -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,
@ -1128,10 +1136,6 @@ class Machine {
dispose();
}
static const unsigned HeapPoolSize = 64;
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<uintptr_t*>
@ -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);

View File

@ -90,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)

View File

@ -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
}
@ -507,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

View File

@ -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));
@ -106,8 +107,10 @@ class HashMapIterator: public Thread::Protector {
if (arrayBody(t, array, i)) {
node = arrayBody(t, array, i);
index = i + 1;
return;
}
}
node = 0;
}
bool hasMore() {