From 60072b9fdc4e102e9b4e01de71bfd12fb1d755a9 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 27 Oct 2007 19:54:30 -0600 Subject: [PATCH] implement fixed object support --- makefile | 33 ++- src/builtin.cpp | 4 +- src/common.h | 4 + src/compile.cpp | 20 +- src/heap.cpp | 7 +- src/heap.h | 2 +- src/interpret.cpp | 4 +- src/jnienv.cpp | 7 +- src/machine.cpp | 480 ++++++++++++++++++++++--------- src/machine.h | 158 +++++++--- src/main.cpp | 27 ++ src/type-generator.cpp | 139 +++++++-- test/GC.java | 7 + test/{ => extra}/Memory.java | 0 test/{ => extra}/SendFile.java | 0 test/{ => extra}/SendServer.java | 0 16 files changed, 653 insertions(+), 239 deletions(-) rename test/{ => extra}/Memory.java (100%) rename test/{ => extra}/SendFile.java (100%) rename test/{ => extra}/SendServer.java (100%) diff --git a/makefile b/makefile index 84b1123dd9..34f65964bb 100644 --- a/makefile +++ b/makefile @@ -28,7 +28,7 @@ src = src classpath = classpath test = test -input = $(test-build)/Hello.class +input = $(test-build)/Enums.class build-cxx = g++ build-cc = gcc @@ -192,11 +192,11 @@ ifeq ($(platform),darwin) classpath-object = endif -test-sources = $(shell find $(test) -name '*.java') +test-sources = $(wildcard $(test)/*.java) test-classes = $(call java-classes,$(test-sources),$(test),$(test-build)) class-name = $(patsubst $(1)/%.class,%,$(2)) -class-names = $(foreach x,$(1),$(call class-name,$(x))) +class-names = $(foreach x,$(2),$(call class-name,$(1),$(x))) flags = -cp $(test-build) args = $(flags) $(call class-name,$(test-build),$(input)) @@ -204,7 +204,15 @@ args = $(flags) $(call class-name,$(test-build),$(input)) .PHONY: build build: $(interpreter) $(archive) $(classpath-classes) $(test-classes) -$(input): $(classpath-classes) +.PHONY: classes +classes: + @mkdir -p $(classpath-build) + $(javac) -d $(classpath-build) -bootclasspath $(classpath) \ + $(classpath-sources) + @mkdir -p $(test-build) + $(javac) -d $(test-build) -bootclasspath $(classpath-build) $(test-sources) + +$(test-classes): $(classpath-classes) .PHONY: run run: build @@ -221,7 +229,8 @@ vg: build .PHONY: test test: build /bin/bash $(test)/test.sh 2>/dev/null \ - $(interpreter) $(mode) "$(flags)" $(call class-names,$(test-classes)) + $(interpreter) $(mode) "$(flags)" \ + $(call class-names,$(test-build),$(test-classes)) .PHONY: clean clean: @@ -236,7 +245,7 @@ clean-native: gen-arg = $(shell echo $(1) | sed -e 's:$(native-build)/type-\(.*\)\.cpp:\1:') $(generated-code): %.cpp: $(src)/types.def $(generator) @echo "generating $(@)" - @mkdir -p -m 1777 $(dir $(@)) + @mkdir -p $(dir $(@)) $(generator) $(call gen-arg,$(@)) < $(<) > $(@) $(native-build)/type-generator.o: \ @@ -244,7 +253,7 @@ $(native-build)/type-generator.o: \ define compile-class @echo "compiling $(@)" - @mkdir -p -m 1777 $(dir $(@)) + @mkdir -p $(dir $(@)) $(javac) -bootclasspath $(classpath) -classpath $(classpath) \ -d $(1) $(<) @touch $(@) @@ -252,21 +261,21 @@ endef $(classpath-build)/%.class: $(classpath)/%.java @echo "compiling $(@)" - @mkdir -p -m 1777 $(dir $(@)) + @mkdir -p $(dir $(@)) $(javac) -bootclasspath $(classpath) -classpath $(classpath) \ -d $(classpath-build) $(<) @touch $(@) $(test-build)/%.class: $(test)/%.java @echo "compiling $(@)" - @mkdir -p -m 1777 $(dir $(@)) + @mkdir -p $(dir $(@)) $(javac) -bootclasspath $(classpath) -classpath $(classpath) \ -d $(test-build) $(<) @touch $(@) define compile-object @echo "compiling $(@)" - @mkdir -p -m 1777 $(dir $(@)) + @mkdir -p $(dir $(@)) $(cxx) $(cflags) -c $(<) -o $(@) endef @@ -293,12 +302,12 @@ $(classpath-object): $(build)/classpath.jar $(generator-objects): $(native-build)/%.o: $(src)/%.cpp @echo "compiling $(@)" - @mkdir -p -m 1777 $(dir $(@)) + @mkdir -p $(dir $(@)) $(build-cxx) -DPOINTER_SIZE=$(pointer-size) $(build-cflags) -c $(<) -o $(@) $(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp @echo "compiling $(@)" - @mkdir -p -m 1777 $(dir $(@)) + @mkdir -p $(dir $(@)) $(cxx) $(jni-cflags) -c $(<) -o $(@) $(archive): $(interpreter-objects) $(jni-objects) $(classpath-object) diff --git a/src/builtin.cpp b/src/builtin.cpp index 2223221714..11d645527b 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -109,10 +109,10 @@ Java_java_lang_Object_clone(Thread* t, jclass, jobject o) object clone; if (classArrayElementSize(t, class_)) { - clone = static_cast(allocate(t, size)); + clone = static_cast(allocate(t, size, classObjectMask(t, class_))); memcpy(clone, *o, size); // clear any object header flags: - cast(*o, 0) = objectClass(t, *o); + setObjectClass(t, *o, objectClass(t, *o)); } else { clone = make(t, objectClass(t, *o)); memcpy(reinterpret_cast(clone) + 1, diff --git a/src/common.h b/src/common.h index 625cf2c076..9eced04931 100644 --- a/src/common.h +++ b/src/common.h @@ -232,6 +232,10 @@ bitsToFloat(uint32_t bits) return f; } +// an object must survive TenureThreshold + 2 garbage collections +// before being copied to gen2 (muat be at least 1): +const unsigned TenureThreshold = 3; + class Machine; class Thread; diff --git a/src/compile.cpp b/src/compile.cpp index d3b6582911..0696afd16e 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -674,7 +674,7 @@ class StackMapper { MyProtector(StackMapper* mapper): Protector(mapper->t), mapper(mapper) { } virtual void visit(Heap::Visitor* v) { - v->visit(&(mapper->method)); + vm::visit(t, v, &(mapper->method)); } StackMapper* mapper; @@ -1073,14 +1073,14 @@ visitParameters(MyThread* t, Heap::Visitor* v, void* frame) unsigned index = 0; if ((methodFlags(t, method) & ACC_STATIC) == 0) { - v->visit(frameLocalObject(t, frame, index++)); + visit(t, v, frameLocalObject(t, frame, index++)); } for (MethodSpecIterator it(t, spec); it.hasNext();) { switch (*it.next()) { case 'L': case '[': - v->visit(frameLocalObject(t, frame, index++)); + visit(t, v, frameLocalObject(t, frame, index++)); break; case 'J': @@ -1122,7 +1122,7 @@ visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* frame) for (unsigned i = 0; i < count; ++i) { if (getBit(stackMap, i)) { - v->visit(frameLocalObject(t, frame, i + parameterFootprint)); + visit(t, v, frameLocalObject(t, frame, i + parameterFootprint)); } } } @@ -1134,7 +1134,7 @@ visitStack(MyThread* t, Heap::Visitor* v) void* frame = frameStart(t); if (frameValid(frame)) { - v->visit(&frameMethod(frame)); + visit(t, v, &frameMethod(frame)); } for (; frameValid(frame); frame = frameNext(frame)) { @@ -1142,7 +1142,7 @@ visitStack(MyThread* t, Heap::Visitor* v) // caller is native. Otherwise, the caller owns them. void* next = frameNext(frame); if (frameValid(next)) { - v->visit(&frameMethod(next)); + visit(t, v, &frameMethod(next)); if (methodFlags(t, frameMethod(next)) & ACC_NATIVE) { visitParameters(t, v, frame); @@ -4573,10 +4573,10 @@ class JavaCompiler: public Compiler { MyProtector(JavaCompiler* c): Protector(c->t), c(c) { } virtual void visit(Heap::Visitor* v) { - v->visit(&(c->method)); + vm::visit(t, v, &(c->method)); for (unsigned i = 0; i < c->pool.length(); i += BytesPerWord) { - v->visit(reinterpret_cast(&(c->pool.getAddress(i)))); + vm::visit(t, v, reinterpret_cast(&(c->pool.getAddress(i)))); } } @@ -4799,7 +4799,7 @@ class ArgumentList { virtual void visit(Heap::Visitor* v) { for (unsigned i = 0; i < list->position; ++i) { if (list->objectMask[i]) { - v->visit(reinterpret_cast(list->array + i)); + vm::visit(t, v, reinterpret_cast(list->array + i)); } } } @@ -4984,7 +4984,7 @@ class MyProcessor: public Processor { if (t->m->active) { for (Reference* r = t->reference; r; r = r->next) { - v->visit(&(r->target)); + visit(t, v, &(r->target)); } visitStack(t, v); diff --git a/src/heap.cpp b/src/heap.cpp index 409edda161..5e8f76830d 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -6,10 +6,6 @@ using namespace vm; namespace { -// an object must survive TenureThreshold + 2 garbage collections -// before being copied to gen2 (muat be at least 1): -const unsigned TenureThreshold = 3; - const unsigned Top = ~static_cast(0); const unsigned InitialGen2CapacityInBytes = 4 * 1024 * 1024; @@ -648,6 +644,9 @@ update3(Context* c, void* o, bool* needsVisit) if (wasCollected(c, o)) { *needsVisit = false; return follow(c, o); + } else if (c->client->checkFixed(o)) { + *needsVisit = false; + return o; } else { *needsVisit = true; return copy(c, o); diff --git a/src/heap.h b/src/heap.h index 3e0a77c97d..9610827e95 100644 --- a/src/heap.h +++ b/src/heap.h @@ -35,7 +35,7 @@ class Heap { public: virtual ~Client() { } virtual void visitRoots(Visitor*) = 0; - virtual unsigned sizeInWords(void*) = 0; + virtual bool checkFixed(void*) = 0; virtual unsigned copiedSizeInWords(void*) = 0; virtual void copy(void*, void*) = 0; virtual void walk(void*, Walker*) = 0; diff --git a/src/interpret.cpp b/src/interpret.cpp index 2b9dd58c49..79bb29d5f5 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -2955,11 +2955,11 @@ class MyProcessor: public Processor { { Thread* t = static_cast(vmt); - v->visit(&(t->code)); + visit(t, v, &(t->code)); for (unsigned i = 0; i < t->sp; ++i) { if (t->stack[i * 2] == ObjectTag) { - v->visit(t->stack + (i * 2) + 1); + visit(t, v, reinterpret_cast(t->stack + (i * 2) + 1)); } } } diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 12913ef8fe..0778437970 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -24,8 +24,11 @@ DestroyJavaVM(Machine* m) Processor* p = m->processor; Heap* h = m->heap; Finder* f = m->finder; + Thread* t = m->rootThread; - int exitCode = (m->rootThread->exception ? -1 : 0); + int exitCode = (t->exception ? -1 : 0); + enter(t, Thread::ActiveState); + t->exit(); m->dispose(); p->dispose(); @@ -1859,7 +1862,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_GetDefaultJavaVMInitArgs(void* args) { JDK1_1InitArgs* a = static_cast(args); - a->maxHeapSize = 128 * 1024 * 1024; + a->maxHeapSize = 64 * 1024 * 1024; a->classpath = "."; a->properties = 0; return 0; diff --git a/src/machine.cpp b/src/machine.cpp index af83697c7a..e662d7f99b 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -115,11 +115,6 @@ footprint(Thread* t) { unsigned n = t->heapOffset + t->heapIndex; - if (t->large) { - n += extendedSize - (t, t->large, baseSize(t, t->large, objectClass(t, t->large))); - } - for (Thread* c = t->child; c; c = c->peer) { n += footprint(c); } @@ -131,8 +126,8 @@ void visitRoots(Thread* t, Heap::Visitor* v) { if (t->state != Thread::ZombieState) { - v->visit(&(t->javaThread)); - v->visit(&(t->exception)); + visit(t, v, &(t->javaThread)); + visit(t, v, &(t->exception)); t->m->processor->visitObjects(t, v); @@ -147,9 +142,75 @@ visitRoots(Thread* t, Heap::Visitor* v) } void -finalizerTargetUnreachable(Thread* t, object* p, Heap::Visitor* v) +walk(Thread* t, object o, Heap::Walker* w) { - v->visit(&finalizerTarget(t, *p)); + object class_ = static_cast(t->m->heap->follow(objectClass(t, o))); + object objectMask = static_cast + (t->m->heap->follow(classObjectMask(t, class_))); + + if (objectMask) { + // fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n", + // p, class_, objectMask, intArrayLength(t, objectMask)); + + unsigned fixedSize = classFixedSize(t, class_); + unsigned arrayElementSize = classArrayElementSize(t, class_); + unsigned arrayLength + = (arrayElementSize ? + cast(o, fixedSize - BytesPerWord) : 0); + + int mask[intArrayLength(t, objectMask)]; + memcpy(mask, &intArrayBody(t, objectMask, 0), + intArrayLength(t, objectMask) * 4); + + // fprintf + // (stderr, + // "fixed size: %d; array length: %d; element size: %d; mask: %x\n", + // fixedSize, arrayLength, arrayElementSize, mask[0]); + + unsigned fixedSizeInWords = ceiling(fixedSize, BytesPerWord); + unsigned arrayElementSizeInWords + = ceiling(arrayElementSize, BytesPerWord); + + for (unsigned i = 0; i < fixedSizeInWords; ++i) { + if (mask[i / 32] & (static_cast(1) << (i % 32))) { + if (not w->visit(i)) { + return; + } + } + } + + bool arrayObjectElements = false; + for (unsigned j = 0; j < arrayElementSizeInWords; ++j) { + unsigned k = fixedSizeInWords + j; + if (mask[k / 32] & (static_cast(1) << (k % 32))) { + arrayObjectElements = true; + break; + } + } + + if (arrayObjectElements) { + for (unsigned i = 0; i < arrayLength; ++i) { + for (unsigned j = 0; j < arrayElementSizeInWords; ++j) { + unsigned k = fixedSizeInWords + j; + if (mask[k / 32] & (static_cast(1) << (k % 32))) { + if (not w->visit + (fixedSizeInWords + (i * arrayElementSizeInWords) + j)) + { + return; + } + } + } + } + } + } else { + w->visit(0); + } +} + +void +finalizerTargetUnreachable(Thread* t, Heap::Visitor* v, object* p) +{ + visit(t, v, &finalizerTarget(t, *p)); object finalizer = *p; *p = finalizerNext(t, finalizer); @@ -158,14 +219,14 @@ finalizerTargetUnreachable(Thread* t, object* p, Heap::Visitor* v) } void -referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v) +referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p) { if (DebugReferences) { fprintf(stderr, "target %p unreachable for reference %p\n", jreferenceTarget(t, *p), *p); } - v->visit(p); + visit(t, v, p); jreferenceTarget(t, *p) = 0; if (jreferenceQueue(t, *p) @@ -173,7 +234,7 @@ referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v) { // queue is reachable - add the reference - v->visit(&jreferenceQueue(t, *p)); + visit(t, v, &jreferenceQueue(t, *p)); object q = jreferenceQueue(t, *p); @@ -192,7 +253,7 @@ referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v) } void -referenceUnreachable(Thread* t, object* p, Heap::Visitor* v) +referenceUnreachable(Thread* t, Heap::Visitor* v, object* p) { if (DebugReferences) { fprintf(stderr, "reference %p unreachable (target %p)\n", @@ -203,27 +264,103 @@ referenceUnreachable(Thread* t, object* p, Heap::Visitor* v) and t->m->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable) { // queue is reachable - add the reference - referenceTargetUnreachable(t, p, v); + referenceTargetUnreachable(t, v, p); } else { *p = jreferenceNext(t, *p); } } void -referenceTargetReachable(Thread* t, object* p, Heap::Visitor* v) +referenceTargetReachable(Thread* t, Heap::Visitor* v, object* p) { if (DebugReferences) { fprintf(stderr, "target %p reachable for reference %p\n", jreferenceTarget(t, *p), *p); } - v->visit(p); - v->visit(&jreferenceTarget(t, *p)); + visit(t, v, p); + visit(t, v, &jreferenceTarget(t, *p)); if (t->m->heap->status(jreferenceQueue(t, *p)) == Heap::Unreachable) { jreferenceQueue(t, *p) = 0; } else { - v->visit(&jreferenceQueue(t, *p)); + visit(t, v, &jreferenceQueue(t, *p)); + } +} + +void +freeFixies(Thread* t, object* fixies) +{ + for (object* p = fixies; *p;) { + object o = *p; + *p = fixedNext(t, o); + + t->m->system->free(fixedStart(t, o)); + } +} + +void +sweepFixies(Thread* t) +{ + Machine* m = t->m; + + assert(t, m->markedFixies == 0); + + if (m->heap->collectionType() == Heap::MajorCollection) { + freeFixies(t, &(m->tenuredFixies)); + freeFixies(t, &(m->dirtyFixies)); + } + freeFixies(t, &(m->fixies)); + + for (object* p = &(m->visitedFixies); *p;) { + object o = *p; + *p = fixedNext(t, o); + + fixedAge(t, o) = (fixedAge(t, o) + 1); + if (fixedAge(t, o) > TenureThreshold) { + fixedAge(t, o) = TenureThreshold; + } + + if (fixedAge(t, o) == TenureThreshold) { + fixedMove(t, o, &(m->tenuredFixies)); + + if (fixedDirty(t, o)) { + unsigned size = baseSize(t, o, objectClass(t, o)); + uintptr_t* mask = fixedMask(t, o, size); + memset(mask, 0, ceiling(size, BytesPerWord) * BytesPerWord); + fixedDirty(t, o) = 0; + } + } else { + fixedMove(t, o, &(m->fixies)); + } + + fixedMarked(t, o) = 0; + } +} + +void +visitDirtyFixies(Thread* t, Heap::Visitor* v) +{ + for (object* p = &(t->m->dirtyFixies); *p;) { + object o = *p; + *p = fixedNext(t, o); + + unsigned size = baseSize(t, o, objectClass(t, o)); + uintptr_t* mask = fixedMask(t, o, size); + for (unsigned word = 0; word < wordOf(size); ++ word) { + if (mask[word]) { + for (unsigned bit = 0; bit < bitOf(size); ++ bit) { + unsigned index = indexOf(word, bit); + if (getBit(mask, index)) { + visit(t, v, &cast(o, index)); + } + } + } + } + + memset(mask, 0, ceiling(size, BytesPerWord) * BytesPerWord); + fixedDirty(t, o) = 0; + fixedMove(t, o, &(t->m->tenuredFixies)); } } @@ -231,29 +368,30 @@ void postVisit(Thread* t, Heap::Visitor* v) { Machine* m = t->m; + bool major = m->heap->collectionType() == Heap::MajorCollection; for (object* p = &(m->finalizeQueue); *p; p = &(finalizerNext(t, *p))) { - v->visit(p); - v->visit(&finalizerTarget(t, *p)); + visit(t, v, p); + visit(t, v, &finalizerTarget(t, *p)); } for (object* p = &(m->finalizeQueue); *p; p = &(finalizerNext(t, *p))) { - v->visit(p); - v->visit(&finalizerTarget(t, *p)); + visit(t, v, p); + visit(t, v, &finalizerTarget(t, *p)); } object firstNewTenuredFinalizer = 0; object lastNewTenuredFinalizer = 0; for (object* p = &(m->finalizers); *p;) { - v->visit(p); + visit(t, v, p); if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) { // target is unreachable - queue it up for finalization - finalizerTargetUnreachable(t, p, v); + finalizerTargetUnreachable(t, v, p); } else { // target is reachable - v->visit(&finalizerTarget(t, *p)); + visit(t, v, &finalizerTarget(t, *p)); if (m->heap->status(*p) == Heap::Tenured) { // the finalizer is tenured, so we remove it from @@ -279,15 +417,15 @@ postVisit(Thread* t, Heap::Visitor* v) for (object* p = &(m->weakReferences); *p;) { if (m->heap->status(*p) == Heap::Unreachable) { // reference is unreachable - referenceUnreachable(t, p, v); + referenceUnreachable(t, v, p); } else if (m->heap->status(jreferenceTarget(t, *p)) == Heap::Unreachable) { // target is unreachable - referenceTargetUnreachable(t, p, v); + referenceTargetUnreachable(t, v, p); } else { // both reference and target are reachable - referenceTargetReachable(t, p, v); + referenceTargetReachable(t, v, p); if (m->heap->status(*p) == Heap::Tenured) { // the reference is tenured, so we remove it from @@ -308,16 +446,16 @@ postVisit(Thread* t, Heap::Visitor* v) } } - if (m->heap->collectionType() == Heap::MajorCollection) { + if (major) { for (object* p = &(m->tenuredFinalizers); *p;) { - v->visit(p); + visit(t, v, p); if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) { // target is unreachable - queue it up for finalization - finalizerTargetUnreachable(t, p, v); + finalizerTargetUnreachable(t, v, p); } else { // target is reachable - v->visit(&finalizerTarget(t, *p)); + visit(t, v, &finalizerTarget(t, *p)); p = &finalizerNext(t, *p); } } @@ -325,15 +463,15 @@ postVisit(Thread* t, Heap::Visitor* v) for (object* p = &(m->tenuredWeakReferences); *p;) { if (m->heap->status(*p) == Heap::Unreachable) { // reference is unreachable - referenceUnreachable(t, p, v); + referenceUnreachable(t, v, p); } else if (m->heap->status(jreferenceTarget(t, *p)) == Heap::Unreachable) { // target is unreachable - referenceTargetUnreachable(t, p, v); + referenceTargetUnreachable(t, v, p); } else { // both reference and target are reachable - referenceTargetReachable(t, p, v); + referenceTargetReachable(t, v, p); p = &jreferenceNext(t, *p); } } @@ -362,11 +500,7 @@ postCollect(Thread* t) t->heap = t->defaultHeap; t->heapOffset = 0; t->heapIndex = 0; - - if (t->large) { - t->m->system->free(t->large); - t->large = 0; - } + t->allocatedLarge = false; for (Thread* c = t->child; c; c = c->peer) { postCollect(c); @@ -1234,7 +1368,8 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_) ENTER(t, Thread::ExclusiveState); classFlags(t, bootstrapClass) = classFlags(t, class_); - classVmFlags(t, bootstrapClass) |= classVmFlags(t, class_); + classVmFlags(t, bootstrapClass) + |= (classVmFlags(t, class_) & ~BootstrapFlag); set(t, bootstrapClass, ClassSuper, classSuper(t, class_)); set(t, bootstrapClass, ClassInterfaceTable, classInterfaceTable(t, class_)); @@ -1404,6 +1539,11 @@ Machine::Machine(System* system, Heap* heap, Finder* finder, finalizeQueue(0), weakReferences(0), tenuredWeakReferences(0), + fixies(0), + tenuredFixies(0), + dirtyFixies(0), + markedFixies(0), + visitedFixies(0), unsafe(false), heapPoolIndex(0) { @@ -1438,6 +1578,12 @@ Machine::dispose() r = r->next; system->free(t); } + + for (unsigned i = 0; i < heapPoolIndex; ++i) { + system->free(heapPool[i]); + } + + system->free(this); } Thread::Thread(Machine* m, object javaThread, Thread* parent): @@ -1447,11 +1593,11 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): peer((parent ? parent->child : 0)), child(0), state(NoState), + allocatedLarge(false), criticalLevel(0), systemThread(0), javaThread(javaThread), exception(0), - large(0), heapIndex(0), heapOffset(0), protector(0), @@ -1479,7 +1625,7 @@ Thread::init() Thread* t = this; - t->m->loader = allocate(t, sizeof(void*) * 3); + t->m->loader = allocate(t, sizeof(void*) * 3, true); memset(t->m->loader, 0, sizeof(void*) * 2); #include "type-initializations.cpp" @@ -1589,20 +1735,11 @@ Thread::exit() void Thread::dispose() { - if (large) { - m->system->free(large); - large = 0; - } - if (systemThread) { systemThread->dispose(); - systemThread = 0; } -#ifdef VM_STRESS - m->system->free(heap); - heap = 0; -#endif // VM_STRESS + m->system->free(defaultHeap); m->system->free(this); } @@ -1632,6 +1769,10 @@ exit(Thread* t) function(t, finalizerTarget(t, f)); } + freeFixies(t, &(t->m->tenuredFixies)); + freeFixies(t, &(t->m->dirtyFixies)); + freeFixies(t, &(t->m->fixies)); + disposeAll(t, t->m->rootThread); } @@ -1746,12 +1887,45 @@ enter(Thread* t, Thread::State s) } object -allocate2(Thread* t, unsigned sizeInBytes) +allocateFixed(Thread* t, unsigned sizeInBytes, bool objectMask) { - if (sizeInBytes > Thread::HeapSizeInBytes and t->large == 0) { - return allocateLarge(t, sizeInBytes); + ENTER(t, Thread::ExclusiveState); + + unsigned mask = objectMask + * ceiling(sizeInBytes / BytesPerWord, BytesPerWord) + * BytesPerWord; + unsigned total = sizeInBytes + FixedFootprint + mask; + + uint8_t* p = static_cast(t->m->system->tryAllocate(total)); + if (p == 0) { + collect(t, Heap::MajorCollection); + + p = static_cast(t->m->system->allocate(total)); } + memset(p + FixedFootprint + sizeInBytes, 0, mask); + + object o = reinterpret_cast(p + FixedFootprint); + + cast(o, 0) = FixedMark; + fixedAge(t, o) = 0; + fixedMarked(t, o) = 0; + fixedDirty(t, o) = 0; + fixedAdd(t, o, &(t->m->fixies)); + + return o; +} + +object +allocateLarge(Thread* t, unsigned sizeInBytes, bool objectMask) +{ + t->allocatedLarge = true; + return allocateFixed(t, sizeInBytes, objectMask); +} + +object +allocate2(Thread* t, unsigned sizeInBytes, bool objectMask) +{ ACQUIRE_RAW(t, t->m->stateLock); while (t->m->exclusive and t->m->exclusive != t) { @@ -1760,11 +1934,14 @@ allocate2(Thread* t, unsigned sizeInBytes) ENTER(t, Thread::IdleState); } - if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + if (sizeInBytes <= Thread::HeapSizeInBytes + and t->heapIndex + ceiling(sizeInBytes, BytesPerWord) >= Thread::HeapSizeInWords) { t->heap = 0; - if (t->large == 0 and t->m->heapPoolIndex < Machine::HeapPoolSize) { + if ((not t->allocatedLarge) + and t->m->heapPoolIndex < Machine::HeapPoolSize) + { t->heap = static_cast (t->m->system->tryAllocate(Thread::HeapSizeInBytes)); if (t->heap) { @@ -1781,7 +1958,7 @@ allocate2(Thread* t, unsigned sizeInBytes) } if (sizeInBytes > Thread::HeapSizeInBytes) { - return allocateLarge(t, sizeInBytes); + return allocateLarge(t, sizeInBytes, objectMask); } else { return allocateSmall(t, sizeInBytes); } @@ -2533,38 +2710,53 @@ collect(Thread* t, Heap::CollectionType type) Client(Machine* m): m(m) { } virtual void visitRoots(Heap::Visitor* v) { - v->visit(&(m->loader)); - v->visit(&(m->bootstrapClassMap)); - v->visit(&(m->monitorMap)); - v->visit(&(m->stringMap)); - v->visit(&(m->types)); - v->visit(&(m->jniInterfaceTable)); + Thread* t = m->rootThread; + + visit(t, v, &(m->loader)); + visit(t, v, &(m->bootstrapClassMap)); + visit(t, v, &(m->monitorMap)); + visit(t, v, &(m->stringMap)); + visit(t, v, &(m->types)); + visit(t, v, &(m->jniInterfaceTable)); for (Reference* r = m->jniReferences; r; r = r->next) { - v->visit(&(r->target)); + visit(t, v, &(r->target)); } for (Thread* t = m->rootThread; t; t = t->peer) { ::visitRoots(t, v); } + if (m->heap->collectionType() == Heap::MinorCollection) { + visitDirtyFixies(t, v); + } + postVisit(m->rootThread, v); } - virtual unsigned sizeInWords(void* p) { + virtual bool checkFixed(void* p) { Thread* t = m->rootThread; + object o = static_cast(p); - object o = static_cast(m->heap->follow(mask(p))); - - return extendedSize - (t, o, baseSize(t, o, static_cast - (m->heap->follow(objectClass(t, o))))); + if (objectFixed(t, o)) { + if ((not fixedMarked(t, o)) + and m->heap->collectionType() == Heap::MajorCollection + or fixedAge(t, o) < TenureThreshold) + { + fixedMarked(t, o) = 1; + fixedMove(t, o, &(m->markedFixies)); + } + return true; + } else { + return false; + } } virtual unsigned copiedSizeInWords(void* p) { Thread* t = m->rootThread; object o = static_cast(m->heap->follow(mask(p))); + assert(t, not objectFixed(t, o)); unsigned n = baseSize(t, o, static_cast (m->heap->follow(objectClass(t, o)))); @@ -2580,6 +2772,8 @@ collect(Thread* t, Heap::CollectionType type) Thread* t = m->rootThread; object src = static_cast(m->heap->follow(mask(srcp))); + assert(t, not objectFixed(t, src)); + object class_ = static_cast (m->heap->follow(objectClass(t, src))); @@ -2601,67 +2795,9 @@ collect(Thread* t, Heap::CollectionType type) Thread* t = m->rootThread; object o = static_cast(m->heap->follow(mask(p))); - object class_ = static_cast(m->heap->follow(objectClass(t, o))); - object objectMask = static_cast - (m->heap->follow(classObjectMask(t, class_))); + assert(t, not objectFixed(t, o)); - if (objectMask) { -// fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n", -// p, class_, objectMask, intArrayLength(t, objectMask)); - - unsigned fixedSize = classFixedSize(t, class_); - unsigned arrayElementSize = classArrayElementSize(t, class_); - unsigned arrayLength - = (arrayElementSize ? - cast(p, fixedSize - BytesPerWord) : 0); - - int mask[intArrayLength(t, objectMask)]; - memcpy(mask, &intArrayBody(t, objectMask, 0), - intArrayLength(t, objectMask) * 4); - -// fprintf -// (stderr, -// "fixed size: %d; array length: %d; element size: %d; mask: %x\n", -// fixedSize, arrayLength, arrayElementSize, mask[0]); - - unsigned fixedSizeInWords = ceiling(fixedSize, BytesPerWord); - unsigned arrayElementSizeInWords - = ceiling(arrayElementSize, BytesPerWord); - - for (unsigned i = 0; i < fixedSizeInWords; ++i) { - if (mask[i / 32] & (static_cast(1) << (i % 32))) { - if (not w->visit(i)) { - return; - } - } - } - - bool arrayObjectElements = false; - for (unsigned j = 0; j < arrayElementSizeInWords; ++j) { - unsigned k = fixedSizeInWords + j; - if (mask[k / 32] & (static_cast(1) << (k % 32))) { - arrayObjectElements = true; - break; - } - } - - if (arrayObjectElements) { - for (unsigned i = 0; i < arrayLength; ++i) { - for (unsigned j = 0; j < arrayElementSizeInWords; ++j) { - unsigned k = fixedSizeInWords + j; - if (mask[k / 32] & (static_cast(1) << (k % 32))) { - if (not w->visit - (fixedSizeInWords + (i * arrayElementSizeInWords) + j)) - { - return; - } - } - } - } - } - } else { - w->visit(0); - } + ::walk(m->rootThread, o, w); } private: @@ -2687,6 +2823,8 @@ collect(Thread* t, Heap::CollectionType type) m->system->free(m->heapPool[i]); } m->heapPoolIndex = 0; + + sweepFixies(t); } void @@ -2769,6 +2907,84 @@ makeTrace(Thread* t, uintptr_t start) return trace; } +void +mark(Thread* t, object o, unsigned offset) +{ + if (objectFixed(t, o)) { + if (fixedAge(t, o) == TenureThreshold) { + ACQUIRE_RAW(t, t->m->heapLock); + + markBit(fixedMask(t, o), offset / BytesPerWord); + + fixedDirty(t, o) = 1; + fixedMove(t, o, &(t->m->dirtyFixies)); + } + } else if (t->m->heap->needsMark(&cast(o, offset))) { + ACQUIRE_RAW(t, t->m->heapLock); + + t->m->heap->mark(&cast(o, offset)); + } +} + +void +mark(Thread* t, object o, unsigned offset, unsigned count) +{ + if (objectFixed(t, o)) { + if (fixedAge(t, o) == TenureThreshold) { + ACQUIRE_RAW(t, t->m->heapLock); + + uintptr_t* mask = fixedMask(t, o); + + for (unsigned i = 0; i < count; ++i) { + markBit(mask, (offset / BytesPerWord) + i); + } + + fixedDirty(t, o) = 1; + fixedMove(t, o, &(t->m->dirtyFixies)); + } + } else { + ACQUIRE_RAW(t, t->m->heapLock); + + for (unsigned i = 0; i < count; ++i) { + unsigned j = offset + (i * BytesPerWord); + if (t->m->heap->needsMark(&cast(o, j))) { + t->m->heap->mark(&cast(o, j)); + } + } + } +} + +void +visit(Thread* t, Heap::Visitor* v, object* p) +{ + v->visit(p); + + for (object* p = &(t->m->markedFixies); *p;) { + object o = *p; + *p = fixedNext(t, o); + + class Walker: public Heap::Walker { + public: + Walker(Thread* t, Heap::Visitor* v, object o): + t(t), v(v), o(o) + { } + + virtual bool visit(unsigned offset) { + ::visit(t, v, &cast(o, offset * BytesPerWord)); + return true; + } + + Thread* t; + Heap::Visitor* v; + object o; + } w(t, v, o); + + walk(t, o, &w); + + fixedMove(t, o, &(t->m->visitedFixies)); + } +} + void noop() { } diff --git a/src/machine.h b/src/machine.h index 4b0840ea2a..94890201fd 100644 --- a/src/machine.h +++ b/src/machine.h @@ -34,6 +34,13 @@ const uintptr_t HashTakenMark = 1; const uintptr_t ExtendedMark = 2; const uintptr_t FixedMark = 3; +const unsigned FixedAge = 0; +const unsigned FixedMarked = 1; +const unsigned FixedDirty = 2; +const unsigned FixedHandle = BytesPerWord; +const unsigned FixedNext = BytesPerWord * 2; +const unsigned FixedFootprint = BytesPerWord * 3; + enum FieldCode { VoidField, ByteField, @@ -1147,6 +1154,11 @@ class Machine { object finalizeQueue; object weakReferences; object tenuredWeakReferences; + object fixies; + object tenuredFixies; + object dirtyFixies; + object markedFixies; + object visitedFixies; bool unsafe; JavaVMVTable javaVMVTable; JNIEnvVTable jniEnvVTable; @@ -1163,6 +1175,9 @@ threadInterrupted(Thread* t, object thread); void enterActiveState(Thread* t); +void +visit(Thread* t, Heap::Visitor* v, object* p); + class Thread { public: enum State { @@ -1196,7 +1211,7 @@ class Thread { SingleProtector(Thread* t, object* p): Protector(t), p(p) { } virtual void visit(Heap::Visitor* v) { - v->visit(p); + vm::visit(t, v, p); } object* p; @@ -1251,11 +1266,11 @@ class Thread { Thread* peer; Thread* child; State state; + bool allocatedLarge; unsigned criticalLevel; System::Thread* systemThread; object javaThread; object exception; - object large; unsigned heapIndex; unsigned heapOffset; Protector* protector; @@ -1406,25 +1421,23 @@ expect(Thread* t, bool v) expect(t->m->system, v); } -inline object -allocateLarge(Thread* t, unsigned sizeInBytes) -{ - return t->large = static_cast(t->m->system->allocate(sizeInBytes)); -} +object +allocateFixed(Thread* t, unsigned sizeInBytes, bool objectMask); + +object +allocate2(Thread* t, unsigned sizeInBytes, bool objectMask); inline object allocateSmall(Thread* t, unsigned sizeInBytes) { object o = reinterpret_cast(t->heap + t->heapIndex); t->heapIndex += ceiling(sizeInBytes, BytesPerWord); + cast(o, 0) = 0; return o; } -object -allocate2(Thread* t, unsigned sizeInBytes); - inline object -allocate(Thread* t, unsigned sizeInBytes) +allocate(Thread* t, unsigned sizeInBytes, bool objectMask) { stress(t); @@ -1432,7 +1445,7 @@ allocate(Thread* t, unsigned sizeInBytes) >= Thread::HeapSizeInWords or t->m->exclusive)) { - return allocate2(t, sizeInBytes); + return allocate2(t, sizeInBytes, objectMask); } else { return allocateSmall(t, sizeInBytes); } @@ -1441,6 +1454,9 @@ allocate(Thread* t, unsigned sizeInBytes) void mark(Thread* t, object target, unsigned offset); +void +mark(Thread* t, object target, unsigned offset, unsigned count); + inline void set(Thread* t, object target, unsigned offset, object value) { @@ -1489,41 +1505,93 @@ baseSize(Thread* t, object o, object class_) BytesPerWord); } -inline void -mark(Thread* t, object target, unsigned offset, unsigned count) +inline void* +fixedStart(Thread* t UNUSED, object o) { - ACQUIRE_RAW(t, t->m->heapLock); - if (objectFixed(t, target)) { - unsigned size = baseSize(t, target, objectClass(t, target)) - * BytesPerWord; + assert(t, objectFixed(t, o)); + return &cast(o, - FixedFootprint); +} - for (unsigned i = 0; i < count; ++i) { - markBit(&cast(target, size), offset + (i * BytesPerWord)); - } - } else { - for (unsigned i = 0; i < count; ++i) { - unsigned j = offset + (i * BytesPerWord); - if (t->m->heap->needsMark(&cast(target, j))) { - t->m->heap->mark(&cast(target, j)); - } - } +inline uint8_t& +fixedAge(Thread* t UNUSED, object o) +{ + assert(t, objectFixed(t, o)); + return cast(o, - (FixedFootprint - FixedAge)); +} + +inline uint8_t& +fixedMarked(Thread* t UNUSED, object o) +{ + assert(t, objectFixed(t, o)); + return cast(o, - (FixedFootprint - FixedMarked)); +} + +inline uint8_t& +fixedDirty(Thread* t UNUSED, object o) +{ + assert(t, objectFixed(t, o)); + return cast(o, - (FixedFootprint - FixedDirty)); +} + +inline object*& +fixedHandle(Thread* t UNUSED, object o) +{ + assert(t, objectFixed(t, o)); + return cast(o, - (FixedFootprint - FixedHandle)); +} + +inline object& +fixedNext(Thread* t UNUSED, object o) +{ + assert(t, objectFixed(t, o)); + return cast(o, - (FixedFootprint - FixedNext)); +} + +inline void +fixedAdd(Thread* t, object o, object* handle) +{ +// fprintf(stderr, "add %p to %s\n", o, +// handle == &(t->m->fixies) ? "fixies" : +// handle == &(t->m->tenuredFixies) ? "tenured" : +// handle == &(t->m->dirtyFixies) ? "dirty" : +// handle == &(t->m->markedFixies) ? "marked" : +// handle == &(t->m->visitedFixies) ? "visited" : "unknown"); + + fixedHandle(t, o) = handle; + fixedNext(t, o) = *handle; + if (*handle) { + fixedHandle(t, *handle) = &fixedNext(t, o); + } + *handle = o; +} + +inline void +fixedRemove(Thread* t, object o) +{ + *fixedHandle(t, o) = fixedNext(t, o); + if (fixedNext(t, o)) { + fixedHandle(t, fixedNext(t, o)) = fixedHandle(t, o); } } inline void -mark(Thread* t, object target, unsigned offset) +fixedMove(Thread* t, object o, object* handle) { - if (objectFixed(t, target)) { - unsigned size = baseSize(t, target, objectClass(t, target)) * BytesPerWord; + fixedRemove(t, o); + fixedAdd(t, o, handle); +} - ACQUIRE_RAW(t, t->m->heapLock); +inline uintptr_t* +fixedMask(Thread* t UNUSED, object o, unsigned size) +{ + assert(t, objectFixed(t, o)); + return &cast(o, size * BytesPerWord); +} - markBit(&cast(target, size), offset); - } else if (t->m->heap->needsMark(&cast(target, offset))) { - ACQUIRE_RAW(t, t->m->heapLock); - - t->m->heap->mark(&cast(target, offset)); - } +inline uintptr_t* +fixedMask(Thread* t, object o) +{ + return fixedMask(t, o, baseSize(t, o, objectClass(t, o))); } object @@ -1664,10 +1732,10 @@ makeNew(Thread* t, object class_) { PROTECT(t, class_); unsigned sizeInBytes = pad(classFixedSize(t, class_)); - object instance = allocate(t, sizeInBytes); - cast(instance, 0) = class_; - memset(&cast(instance, 0) + 1, 0, - sizeInBytes - sizeof(object)); + object instance = allocate(t, sizeInBytes, classObjectMask(t, class_)); + setObjectClass(t, instance, class_); + memset(&cast(instance, BytesPerWord), 0, + sizeInBytes - BytesPerWord); return instance; } @@ -1696,9 +1764,6 @@ make(Thread* t, object class_) } } -object -make(Thread* t, object class_); - object makeByteArray(Thread* t, const char* format, ...); @@ -1738,9 +1803,10 @@ markHashTaken(Thread* t, object o) { assert(t, not objectExtended(t, o)); assert(t, not objectFixed(t, o)); - cast(o, 0) |= HashTakenMark; ACQUIRE_RAW(t, t->m->heapLock); + + cast(o, 0) |= HashTakenMark; t->m->heap->pad(o, 1); } diff --git a/src/main.cpp b/src/main.cpp index 323a2cac62..44dc9472f7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,33 @@ extern "C" void __cxa_pure_virtual(void) { abort(); } void operator delete(void*) { abort(); } +#ifdef JNI_VERSION_1_6 +// todo: use JavaVMInitArgs instead +typedef struct JDK1_1InitArgs { + jint version; + + char **properties; + jint checkSource; + jint nativeStackSize; + jint javaStackSize; + jint minHeapSize; + jint maxHeapSize; + jint verifyMode; + char *classpath; + + jint (JNICALL *vfprintf)(FILE *fp, const char *format, va_list args); + void (JNICALL *exit)(jint code); + void (JNICALL *abort)(void); + + jint enableClassGC; + jint enableVerboseGC; + jint disableAsyncGC; + jint verbose; + jboolean debugging; + jint debugPort; +} JDK1_1InitArgs; +#endif + namespace { void diff --git a/src/type-generator.cpp b/src/type-generator.cpp index df16cd50df..d840ff5f7b 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1284,6 +1284,25 @@ writeAccessors(Output* out, Object* declarations) } } +unsigned +typeFixedSize(Object* type) +{ + unsigned length = BytesPerWord; + for (MemberIterator it(type); it.hasMore();) { + Object* m = it.next(); + switch (m->type) { + case Object::Scalar: { + length = pad(it.offset() + it.size()); + } break; + + case Object::Array: break; + + default: UNREACHABLE; + } + } + return length; +} + const char* obfuscate(const char* s) { @@ -1324,6 +1343,26 @@ writeConstructorParameters(Output* out, Object* t) } } +void +writeConstructorArguments(Output* out, Object* t) +{ + for (MemberIterator it(t); it.hasMore();) { + Object* m = it.next(); + switch (m->type) { + case Object::Scalar: { + out->write(", "); + out->write(obfuscate(memberName(m))); + } break; + + case Object::Array: { + out->write(", clear"); + } break; + + default: break; + } + } +} + void writeConstructorInitializations(Output* out, Object* t) { @@ -1361,6 +1400,28 @@ typeMemberCount(Object* o) return length(typeMembers(o)) + typeMemberCount(typeSuper(o)); } +void +writeInitializerDeclarations(Output* out, Object* declarations) +{ + for (Object* p = declarations; p; p = cdr(p)) { + Object* o = car(p); + switch (o->type) { + case Object::Type: { + out->write("void init"); + out->write(capitalize(typeName(o))); + if (typeHideConstructor(o)) out->write("0"); + out->write("(Thread* t, object o"); + + writeConstructorParameters(out, o); + + out->write(");\n\n"); + } break; + + default: break; + } + } +} + void writeConstructorDeclarations(Output* out, Object* declarations) { @@ -1383,6 +1444,37 @@ writeConstructorDeclarations(Output* out, Object* declarations) } } +void +writeInitializers(Output* out, Object* declarations) +{ + for (Object* p = declarations; p; p = cdr(p)) { + Object* o = car(p); + switch (o->type) { + case Object::Type: { + out->write("void\ninit"); + out->write(capitalize(typeName(o))); + if (typeHideConstructor(o)) out->write("0"); + out->write("(Thread* t, object o"); + + writeConstructorParameters(out, o); + + out->write(")\n{\n"); + + out->write(" setObjectClass(t, o, "); + out->write("arrayBody(t, t->m->types, Machine::"); + out->write(capitalize(typeName(o))); + out->write("Type));\n"); + + writeConstructorInitializations(out, o); + + out->write("}\n\n"); + } break; + + default: break; + } + } +} + void writeConstructors(Output* out, Object* declarations) { @@ -1390,7 +1482,7 @@ writeConstructors(Output* out, Object* declarations) Object* o = car(p); switch (o->type) { case Object::Type: { - out->write("object\nmake"); + out->write("object make"); out->write(capitalize(typeName(o))); if (typeHideConstructor(o)) out->write("0"); out->write("(Thread* t"); @@ -1399,14 +1491,18 @@ writeConstructors(Output* out, Object* declarations) out->write(")\n{\n"); + bool hasObjectMask = false; for (MemberIterator it(o); it.hasMore();) { Object* m = it.next(); if (m->type == Object::Scalar - and equal(memberTypeName(m), "object")) + and equal(memberTypeName(m), "object") + and not memberNoGC(m)) { out->write(" PROTECT(t, "); out->write(obfuscate(memberName(m))); out->write(");\n"); + + hasObjectMask = true; } } @@ -1438,14 +1534,19 @@ writeConstructors(Output* out, Object* declarations) out->write(" object o = allocate(t, "); writeOffset(out, typeOffset(o), true); + if (hasObjectMask) { + out->write(", true"); + } else { + out->write(", false"); + } out->write(");\n"); - out->write(" cast(o, 0) "); - out->write("= arrayBody(t, t->m->types, Machine::"); + out->write(" init"); out->write(capitalize(typeName(o))); - out->write("Type);\n"); - - writeConstructorInitializations(out, o); + if (typeHideConstructor(o)) out->write("0"); + out->write("(t, o"); + writeConstructorArguments(out, o); + out->write(");\n"); out->write(" return o;\n}\n\n"); } break; @@ -1502,25 +1603,6 @@ set(uint32_t* mask, unsigned index) } } -unsigned -typeFixedSize(Object* type) -{ - unsigned length = BytesPerWord; - for (MemberIterator it(type); it.hasMore();) { - Object* m = it.next(); - switch (m->type) { - case Object::Scalar: { - length = pad(it.offset() + it.size()); - } break; - - case Object::Array: break; - - default: UNREACHABLE; - } - } - return length; -} - unsigned typeArrayElementSize(Object* type) { @@ -1673,8 +1755,7 @@ writeInitializations(Output* out, Object* declarations) out->write("t->m->types = allocate(t, pad(("); out->write(count); - out->write(" * BytesPerWord) + (BytesPerWord * 2)));\n"); - out->write("cast(t->m->types, 0) = 0;\n"); + out->write(" * BytesPerWord) + (BytesPerWord * 2)), true);\n"); out->write("arrayLength(t, t->m->types) = "); out->write(count); out->write(";\n"); @@ -1763,10 +1844,12 @@ main(int ac, char** av) if (ac == 1 or equal(av[1], "declarations")) { writePods(&out, declarations); writeAccessors(&out, declarations); + writeInitializerDeclarations(&out, declarations); writeConstructorDeclarations(&out, declarations); } if (ac == 1 or equal(av[1], "constructors")) { + writeInitializers(&out, declarations); writeConstructors(&out, declarations); } diff --git a/test/GC.java b/test/GC.java index 19befeff1b..286e64f8b4 100644 --- a/test/GC.java +++ b/test/GC.java @@ -19,6 +19,13 @@ public class GC { for (int i = 0; i < 8; ++i) { byte[] a = new byte[16 * 1024 * 1024]; } + + for (int i = 0; i < 8; ++i) { + byte[] a = new byte[16 * 1024 * 1024]; + for (int j = 0; j < 32; ++j) { + byte[] b = new byte[32 * 1024]; + } + } } public static void main(String[] args) { diff --git a/test/Memory.java b/test/extra/Memory.java similarity index 100% rename from test/Memory.java rename to test/extra/Memory.java diff --git a/test/SendFile.java b/test/extra/SendFile.java similarity index 100% rename from test/SendFile.java rename to test/extra/SendFile.java diff --git a/test/SendServer.java b/test/extra/SendServer.java similarity index 100% rename from test/SendServer.java rename to test/extra/SendServer.java