diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index 66904a26ca..0419877acc 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -266,7 +266,7 @@ doAccept(JNIEnv* e, int s) int r = ::accept(s, &address, &length); if (r >= 0) { return r; - } else { + } else if (errno != EINTR) { throwIOException(e); } return -1; diff --git a/classpath/java/nio/channels/ServerSocketChannel.java b/classpath/java/nio/channels/ServerSocketChannel.java index 178e0bbed1..0410d47e44 100644 --- a/classpath/java/nio/channels/ServerSocketChannel.java +++ b/classpath/java/nio/channels/ServerSocketChannel.java @@ -47,7 +47,14 @@ public class ServerSocketChannel extends SelectableChannel { } private int doAccept() throws IOException { - return natDoAccept(channel.socket); + while (true) { + int s = natDoAccept(channel.socket); + if (s != -1) { + return s; + } + // todo: throw ClosedByInterruptException if this thread was + // interrupted during the accept call + } } private int doListen(String host, int port) throws IOException { diff --git a/classpath/java/util/ArrayList.java b/classpath/java/util/ArrayList.java index faabdebb5c..4ab5603bec 100644 --- a/classpath/java/util/ArrayList.java +++ b/classpath/java/util/ArrayList.java @@ -38,8 +38,6 @@ public class ArrayList extends AbstractList { private void shrink() { if (array.length / 2 >= MinimumCapacity && size <= array.length / 3) { resize(array.length / 2); - } else if (size == 0) { - resize(0); } } diff --git a/classpath/java/util/HashMap.java b/classpath/java/util/HashMap.java index ecae9a01f1..2f707ba489 100644 --- a/classpath/java/util/HashMap.java +++ b/classpath/java/util/HashMap.java @@ -66,8 +66,6 @@ public class HashMap implements Map { private void shrink() { if (array.length / 2 >= MinimumCapacity && size <= array.length / 3) { resize(array.length / 2); - } else if (size == 0) { - resize(0); } } diff --git a/makefile b/makefile index b6ce200fba..7006194a35 100644 --- a/makefile +++ b/makefile @@ -159,6 +159,18 @@ ifeq ($(platform),darwin) strip-all = -S -x so-suffix = .jnilib shared = -dynamiclib + + ifeq ($(arch),powerpc) + cflags += -arch ppc + asmflags += -arch ppc + lflags += -arch ppc + endif + + ifeq ($(arch),i386) + cflags += -arch i386 + asmflags += -arch i386 + lflags += -arch i386 + endif endif ifeq ($(platform),windows) @@ -228,6 +240,11 @@ ifeq ($(mode),small) cflags += -Os -g3 -DNDEBUG endif +ifeq ($(arch),i386) +# this is necessary to support __sync_bool_compare_and_swap: + cflags += -march=i486 +endif + output = -o $(1) as := $(cc) ld := $(cc) diff --git a/src/common.h b/src/common.h index b9990a674f..535e231b6c 100644 --- a/src/common.h +++ b/src/common.h @@ -325,6 +325,14 @@ markBit(uintptr_t* map, unsigned i) map[wordOf(i)] |= static_cast(1) << bitOf(i); } +inline void +markBitAtomic(uintptr_t* map, unsigned i) +{ + uintptr_t* p = map + wordOf(i); + uintptr_t v = static_cast(1) << bitOf(i); + while (not __sync_bool_compare_and_swap(p, *p, *p | v)) { } +} + inline void clearBit(uintptr_t* map, unsigned i) { diff --git a/src/heap.cpp b/src/heap.cpp index 5067909498..11c3c4ceda 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -303,6 +303,13 @@ class Segment { if (child) child->set(p, v); } + void markAtomic(void* p) { + assert(segment->context, bitsPerRecord == 1); + markBitAtomic(data, indexOf(p)); + assert(segment->context, getBit(data, indexOf(p))); + if (child) child->markAtomic(p); + } + unsigned get(void* p) { return getBits(data, bitsPerRecord, indexOf(p)); } @@ -1013,8 +1020,12 @@ void markDirty(Context* c, Fixie* f) { if (not f->dirty) { - f->dirty = true; - f->move(c, &(c->dirtyTenuredFixies)); + ACQUIRE(c->lock); + + if (not f->dirty) { + f->dirty = true; + f->move(c, &(c->dirtyTenuredFixies)); + } } } @@ -1784,7 +1795,7 @@ class MyHeap: public Heap { Fixie(&c, sizeInWords, objectMask, 0, true))->body(); } - virtual bool needsMark(void* p) { + bool needsMark(void* p) { assert(&c, c.client->isFixed(p) or (not immortalHeapContains(&c, p))); if (c.client->isFixed(p)) { @@ -1794,11 +1805,6 @@ class MyHeap: public Heap { } } - virtual bool needsMark(void* p, unsigned offset) { - return needsMark(p) and targetNeedsMark - (mask(*(static_cast(p) + offset))); - } - bool targetNeedsMark(void* target) { return target and not c.gen2.contains(target) @@ -1809,38 +1815,41 @@ class MyHeap: public Heap { } virtual void mark(void* p, unsigned offset, unsigned count) { - if (c.client->isFixed(p)) { - Fixie* f = fixie(p); - assert(&c, offset == 0 or f->hasMask); + if (needsMark(p)) { + if (c.client->isFixed(p)) { + Fixie* f = fixie(p); + assert(&c, offset == 0 or f->hasMask); - bool dirty = false; - for (unsigned i = 0; i < count; ++i) { - void** target = static_cast(p) + offset + i; - if (targetNeedsMark(mask(*target))) { - if (DebugFixies) { - fprintf(stderr, "dirty fixie %p at %d (%p): %p\n", - f, offset, f->body() + offset, mask(*target)); + bool dirty = false; + for (unsigned i = 0; i < count; ++i) { + void** target = static_cast(p) + offset + i; + if (targetNeedsMark(mask(*target))) { + if (DebugFixies) { + fprintf(stderr, "dirty fixie %p at %d (%p): %p\n", + f, offset, f->body() + offset, mask(*target)); + } + + dirty = true; + markBitAtomic(f->mask(), offset + i); + assert(&c, getBit(f->mask(), offset + i)); } - - dirty = true; - markBit(f->mask(), offset + i); } - } - if (dirty) markDirty(&c, f); - } else { - Segment::Map* map; - if (c.gen2.contains(p)) { - map = &(c.heapMap); + if (dirty) markDirty(&c, f); } else { - assert(&c, c.nextGen2.contains(p)); - map = &(c.nextHeapMap); - } + Segment::Map* map; + if (c.gen2.contains(p)) { + map = &(c.heapMap); + } else { + assert(&c, c.nextGen2.contains(p)); + map = &(c.nextHeapMap); + } - for (unsigned i = 0; i < count; ++i) { - void** target = static_cast(p) + offset + i; - if (targetNeedsMark(mask(*target))) { - map->set(target); + for (unsigned i = 0; i < count; ++i) { + void** target = static_cast(p) + offset + i; + if (targetNeedsMark(mask(*target))) { + map->markAtomic(target); + } } } } diff --git a/src/heap.h b/src/heap.h index 28f1533d8f..769bc1ec4b 100644 --- a/src/heap.h +++ b/src/heap.h @@ -59,8 +59,6 @@ class Heap: public Allocator { virtual void* allocateImmortalFixed(Allocator* allocator, unsigned sizeInWords, bool objectMask, unsigned* totalInBytes) = 0; - virtual bool needsMark(void* p) = 0; - virtual bool needsMark(void* p, unsigned offset) = 0; virtual void mark(void* p, unsigned offset, unsigned count) = 0; virtual void pad(void* p) = 0; virtual void* follow(void* p) = 0; diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 391938180a..d0e7aebaa5 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -195,6 +195,8 @@ GetArrayLength(Thread* t, jarray array) jstring JNICALL NewString(Thread* t, const jchar* chars, jsize size) { + if (chars == 0) return 0; + ENTER(t, Thread::ActiveState); object a = 0; @@ -210,6 +212,8 @@ NewString(Thread* t, const jchar* chars, jsize size) jstring JNICALL NewStringUTF(Thread* t, const char* chars) { + if (chars == 0) return 0; + ENTER(t, Thread::ActiveState); object a = 0; @@ -2169,7 +2173,10 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) System* s = makeSystem(crashDumpDirectory); Heap* h = makeHeap(s, heapLimit); Finder* f = makeFinder(s, RUNTIME_ARRAY_BODY(classpathBuffer), bootLibrary); - Processor* p = makeProcessor(s, h, true); + Processor* p = makeProcessor(s, h, false); // change back to true + // once use of SSE is + // fixed on 32-bit + // systems const char** properties = static_cast (h->allocate(sizeof(const char*) * propertyCount)); diff --git a/src/machine.h b/src/machine.h index 1bc04a9e9e..598a72e424 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1584,19 +1584,13 @@ allocate(Thread* t, unsigned sizeInBytes, bool objectMask) inline void mark(Thread* t, object o, unsigned offset, unsigned count) { - if (t->m->heap->needsMark(o)) { - ACQUIRE_RAW(t, t->m->heapLock); - t->m->heap->mark(o, offset / BytesPerWord, count); - } + t->m->heap->mark(o, offset / BytesPerWord, count); } inline void mark(Thread* t, object o, unsigned offset) { - if (t->m->heap->needsMark(o, offset / BytesPerWord)) { - ACQUIRE_RAW(t, t->m->heapLock); - t->m->heap->mark(o, offset / BytesPerWord, 1); - } + t->m->heap->mark(o, offset / BytesPerWord, 1); } inline void diff --git a/src/x86.cpp b/src/x86.cpp index 97e85dfb41..310aa8350f 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -2931,7 +2931,7 @@ class MyArchitecture: public Assembler::Architecture { break; case Int2Float: - if (useSSE(&c)) { + if (useSSE(&c) and (aSize <= BytesPerWord)) { *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); *aRegisterMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); diff --git a/test/Floats.java b/test/Floats.java index 33c30145fd..bd85a74d10 100644 --- a/test/Floats.java +++ b/test/Floats.java @@ -46,11 +46,13 @@ public class Floats { expect(subtract(0.5d, 0.1d) == 0.4d); - double d = 1d; - expect(((int) d) == 1); + { double d = 1d; + expect(((int) d) == 1); + } - float f = 1f; - expect(((int) f) == 1); + { float f = 1f; + expect(((int) f) == 1); + } expect(Math.round(0.4f) == 0); expect(Math.round(0.5f) == 1); @@ -62,8 +64,14 @@ public class Floats { expect(Math.round(1.0d) == 1); expect(Math.round(1.9d) == 2); - float b = 1.0f; - int blue = (int)(b * 255 + 0.5); - expect(blue == 255); + { float b = 1.0f; + int blue = (int)(b * 255 + 0.5); + expect(blue == 255); + } + + { long z = 6553311036568663L; + double d = (double) z; + expect(d == 6553311036568663.0); + } } }