From 4670055b03c57bffc12575dc5e600066085a37ea Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 15 Jul 2007 19:03:02 -0600 Subject: [PATCH] implement primitive testing framework and provide for GC stress testing --- makefile | 194 ++++------- src/machine.cpp | 303 +++++++++--------- src/machine.h | 44 ++- src/main.cpp | 10 +- src/run.cpp | 7 +- src/run.h | 2 +- .../Exceptions.java | 2 +- classpath/TestGC.java => test/GC.java | 2 +- {classpath => test}/Hello.java | 0 .../TestThreads.java => test/Threads.java | 5 +- test/test.sh | 26 ++ 11 files changed, 298 insertions(+), 297 deletions(-) rename classpath/TestExceptions.java => test/Exceptions.java (92%) rename classpath/TestGC.java => test/GC.java (96%) rename {classpath => test}/Hello.java (100%) rename classpath/TestThreads.java => test/Threads.java (92%) create mode 100644 test/test.sh diff --git a/makefile b/makefile index e88946668a..fe0763ec0f 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -MAKEFLAGS = -s +#MAKEFLAGS = -s arch = $(shell uname -m) ifeq ($(arch),i586) @@ -8,9 +8,13 @@ ifeq ($(arch),i686) arch = i386 endif -bld = build/$(arch) +mode = debug + +bld = build/$(arch)/$(mode) +cls = build/classes src = src classpath = classpath +test = test cxx = g++ cc = gcc @@ -21,32 +25,37 @@ javac = javac warnings = -Wall -Wextra -Werror -Wold-style-cast -Wunused-parameter \ -Winit-self -Wconversion -slow = -O0 -g3 -fast = -Os -DNDEBUG - -#thread-cflags = -DNO_THREADS thread-cflags = -pthread thread-lflags = -lpthread cflags = $(warnings) -fPIC -fno-rtti -fno-exceptions -fvisibility=hidden \ -I$(src) -I$(bld) $(thread-cflags) -D__STDC_LIMIT_MACROS + +ifeq ($(mode),debug) +cflags += -O0 -g3 +endif +ifeq ($(mode),stress) +cflags += -O0 -g3 -DVM_STRESS +endif +ifeq ($(mode),stress-major) +cflags += -O0 -g3 -DVM_STRESS -DVM_STRESS_MAJOR +endif +ifeq ($(mode),fast) +fast = -Os -DNDEBUG +endif + lflags = $(thread-lflags) -ldl -test-cflags = -DDEBUG_MEMORY -stress-cflags = -DDEBUG_MEMORY -DDEBUG_MEMORY_MAJOR cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(bld)/%.o,$(x))) asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(bld)/%.o,$(x))) -java-classes = \ - $(foreach x,$(1),$(patsubst $(2)/%.java,$(bld)/classes/%.class,$(x))) +java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(cls)/%.class,$(x))) stdcpp-sources = $(src)/stdc++.cpp stdcpp-objects = $(call cpp-objects,$(stdcpp-sources),$(src)) -stdcpp-cflags = $(fast) $(cflags) jni-sources = $(classpath)/java/lang/System.cpp jni-objects = $(call cpp-objects,$(jni-sources),$(classpath)) -jni-cflags = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux \ - $(slow) $(cflags) +jni-cflags = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux $(cflags) jni-library = $(bld)/libnatives.so generated-code = \ @@ -91,7 +100,6 @@ interpreter-asm-objects = \ interpreter-objects = \ $(interpreter-cpp-objects) \ $(interpreter-asm-objects) -interpreter-cflags = $(slow) $(cflags) generator-headers = \ $(src)/input.h \ @@ -100,53 +108,31 @@ generator-sources = \ $(src)/type-generator.cpp generator-objects = $(call cpp-objects,$(generator-sources),$(src)) generator-executable = $(bld)/generator -generator-cflags = $(slow) $(cflags) executable = $(bld)/vm -test-cpp-objects = \ - $(patsubst $(bld)/%,$(bld)/test-%,$(interpreter-cpp-objects)) -test-asm-objects = \ - $(patsubst $(bld)/%,$(bld)/test-%,$(interpreter-asm-objects)) -test-objects = \ - $(test-cpp-objects) \ - $(test-asm-objects) -test-executable = $(bld)/test-vm - -stress-cpp-objects = \ - $(patsubst $(bld)/%,$(bld)/stress-%,$(interpreter-cpp-objects)) -stress-asm-objects = \ - $(patsubst $(bld)/%,$(bld)/stress-%,$(interpreter-asm-objects)) -stress-objects = \ - $(stress-cpp-objects) \ - $(stress-asm-objects) -stress-executable = $(bld)/stress-vm - -fast-cpp-objects = \ - $(patsubst $(bld)/%,$(bld)/fast-%,$(interpreter-cpp-objects)) -fast-asm-objects = \ - $(patsubst $(bld)/%,$(bld)/fast-%,$(interpreter-asm-objects)) -fast-objects = \ - $(fast-cpp-objects) \ - $(fast-asm-objects) -fast-executable = $(bld)/fast-vm -fast-cflags = $(fast) $(cflags) - -classpath-sources = $(shell find $(classpath)/java -name '*.java') +classpath-sources = $(shell find $(classpath) -name '*.java') classpath-classes = $(call java-classes,$(classpath-sources),$(classpath)) -input = $(bld)/classes/TestExceptions.class -input-depends = \ - $(classpath-classes) \ - $(jni-library) +classpath-objects = $(classpath-classes) $(jni-library) -gen-run-arg = $(shell echo $(1) | sed -e 's:$(bld)/classes/\(.*\)\.class:\1:') -args = -cp $(bld)/classes -hs 67108864 $(call gen-run-arg,$(input)) +test-sources = $(shell find $(test) -name '*.java') +test-classes = $(call java-classes,$(test-sources),$(test)) + +input = $(cls)/Hello.class + +classpath-objects = $(classpath-classes) $(jni-library) + +class-name = $(patsubst $(cls)/%.class,%,$(1)) +class-names = $(foreach x,$(1),$(call class-name,$(x))) + +flags = -cp $(cls) -hs 67108864 +args = $(flags) $(call class-name,$(input)) .PHONY: build build: $(executable) -$(input): $(input-depends) +$(input): $(classpath-objects) .PHONY: run run: $(executable) $(input) @@ -156,37 +142,14 @@ run: $(executable) $(input) debug: $(executable) $(input) LD_LIBRARY_PATH=$(bld) gdb --args $(<) $(args) -.PHONY: fast -fast: $(fast-executable) - ls -lh $(<) - .PHONY: vg vg: $(executable) $(input) LD_LIBRARY_PATH=$(bld) $(vg) $(<) $(args) .PHONY: test -test: $(test-executable) $(input) - LD_LIBRARY_PATH=$(bld) $(vg) $(<) $(args) - -.PHONY: stress -stress: $(stress-executable) $(input) - LD_LIBRARY_PATH=$(bld) $(vg) $(<) $(args) - -.PHONY: run-all -run-all: $(executable) - set -e; for x in $(all-input); do echo "$$x:"; $(<) $$x; echo; done - -.PHONY: vg-all -vg-all: $(executable) - set -e; for x in $(all-input); do echo "$$x:"; $(vg) -q $(<) $$x; done - -.PHONY: test-all -test-all: $(test-executable) - set -e; for x in $(all-input); do echo "$$x:"; $(vg) -q $(<) $$x; done - -.PHONY: stress-all -stress-all: $(stress-executable) - set -e; for x in $(all-input); do echo "$$x:"; $(vg) -q $(<) $$x; done +test: $(executable) $(classpath-objects) $(test-classes) + LD_LIBRARY_PATH=$(bld) /bin/bash $(test)/test.sh \ + $(<) "$(flags)" $(call class-names,$(test-classes)) .PHONY: clean clean: @@ -201,61 +164,35 @@ $(generated-code): %.cpp: $(src)/types.def $(generator-executable) $(bld)/type-generator.o: \ $(generator-headers) -$(bld)/classes/%.class: $(classpath)/%.java +define compile-class @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(javac) -bootclasspath $(classpath) -classpath $(classpath) \ - -d $(bld)/classes $(<) + $(javac) -bootclasspath $(classpath) -classpath $(classpath) -d $(cls) $(<) +endef + +$(cls)/%.class: $(classpath)/%.java + $(compile-class) + +$(cls)/%.class: $(test)/%.java + $(compile-class) + +define compile-object + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) -c $(<) -o $(@) +endef $(stdcpp-objects): $(bld)/%.o: $(src)/%.cpp - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(stdcpp-cflags) -c $(<) -o $(@) + $(compile-object) $(interpreter-cpp-objects): $(bld)/%.o: $(src)/%.cpp $(interpreter-depends) - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(interpreter-cflags) -c $(<) -o $(@) + $(compile-object) $(interpreter-asm-objects): $(bld)/%.o: $(src)/%.S - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(interpreter-cflags) -c $(<) -o $(@) - -$(test-cpp-objects): $(bld)/test-%.o: $(src)/%.cpp $(interpreter-depends) - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(interpreter-cflags) $(test-cflags) -c $(<) -o $(@) - -$(test-asm-objects): $(bld)/test-%.o: $(src)/%.S - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(interpreter-cflags) $(test-cflags) -c $(<) -o $(@) - -$(stress-cpp-objects): $(bld)/stress-%.o: $(src)/%.cpp $(interpreter-depends) - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(interpreter-cflags) $(stress-cflags) -c $(<) -o $(@) - -$(stress-asm-objects): $(bld)/stress-%.o: $(src)/%.S - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(interpreter-cflags) $(stress-cflags) -c $(<) -o $(@) + $(compile-object) $(generator-objects): $(bld)/%.o: $(src)/%.cpp - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(generator-cflags) -c $(<) -o $(@) - -$(fast-cpp-objects): $(bld)/fast-%.o: $(src)/%.cpp $(interpreter-depends) - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(fast-cflags) -c $(<) -o $(@) - -$(fast-asm-objects): $(bld)/fast-%.o: $(src)/%.S - @echo "compiling $(@)" - @mkdir -p $(dir $(@)) - $(cxx) $(fast-cflags) -c $(<) -o $(@) + $(compile-object) $(jni-objects): $(bld)/%.o: $(classpath)/%.cpp @echo "compiling $(@)" @@ -270,19 +207,6 @@ $(executable): $(interpreter-objects) $(stdcpp-objects) @echo "linking $(@)" $(cc) $(lflags) $(^) -o $(@) -$(test-executable): $(test-objects) $(stdcpp-objects) - @echo "linking $(@)" - $(cc) $(lflags) $(^) -o $(@) - -$(stress-executable): $(stress-objects) $(stdcpp-objects) - @echo "linking $(@)" - $(cc) $(lflags) $(^) -o $(@) - -$(fast-executable): $(fast-objects) $(stdcpp-objects) - @echo "linking $(@)" - $(cc) $(lflags) $(^) -o $(@) - strip --strip-all $(@) - .PHONY: generator generator: $(generator-executable) diff --git a/src/machine.cpp b/src/machine.cpp index 882f26d15a..2e5bde5466 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -281,155 +281,6 @@ postCollect(Thread* t) } } -void -collect(Thread* t, Heap::CollectionType type) -{ - Machine* m = t->vm; - - class Client: public Heap::Client { - public: - Client(Machine* m): m(m) { } - - virtual void visitRoots(Heap::Visitor* v) { - v->visit(&(m->classMap)); - v->visit(&(m->bootstrapClassMap)); - v->visit(&(m->builtinMap)); - v->visit(&(m->monitorMap)); - v->visit(&(m->types)); - - for (Thread* t = m->rootThread; t; t = t->peer) { - ::visitRoots(t, v); - } - - postVisit(m->rootThread, v); - } - - virtual unsigned sizeInWords(object o) { - Thread* t = m->rootThread; - - o = m->heap->follow(mask(o)); - - return extendedSize - (t, o, baseSize(t, o, m->heap->follow(objectClass(t, o)))); - } - - virtual unsigned copiedSizeInWords(object o) { - Thread* t = m->rootThread; - - o = m->heap->follow(mask(o)); - - unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o))); - - if (objectExtended(t, o) or hashTaken(t, o)) { - ++ n; - } - - return n; - } - - virtual void copy(object o, object dst) { - Thread* t = m->rootThread; - - o = m->heap->follow(mask(o)); - object class_ = m->heap->follow(objectClass(t, o)); - - unsigned base = baseSize(t, o, class_); - unsigned n = extendedSize(t, o, base); - - memcpy(dst, o, n * BytesPerWord); - - if (hashTaken(t, o)) { - cast(dst, 0) &= PointerMask; - cast(dst, 0) |= ExtendedMark; - extendedWord(t, dst, base) = takeHash(t, o); - } - } - - virtual void walk(void* p, Heap::Walker* w) { - Thread* t = m->rootThread; - - p = m->heap->follow(mask(p)); - object class_ = m->heap->follow(objectClass(t, p)); - object objectMask = 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(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 = divide(fixedSize, BytesPerWord); - unsigned arrayElementSizeInWords - = divide(arrayElementSize, BytesPerWord); - - for (unsigned i = 0; i < fixedSizeInWords; ++i) { - if (mask[wordOf(i)] & (static_cast(1) << bitOf(i))) { - if (not w->visit(i)) { - return; - } - } - } - - bool arrayObjectElements = false; - for (unsigned j = 0; j < arrayElementSizeInWords; ++j) { - unsigned k = fixedSizeInWords + j; - if (mask[wordOf(k)] & (static_cast(1) << bitOf(k))) { - 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[wordOf(k)] & (static_cast(1) << bitOf(k))) { - if (not w->visit - (fixedSizeInWords + (i * arrayElementSizeInWords) + j)) - { - return; - } - } - } - } - } - } else { - w->visit(0); - } - } - - private: - Machine* m; - } it(m); - - m->unsafe = true; - m->heap->collect(type, &it); - m->unsafe = false; - - postCollect(m->rootThread); - - for (object f = m->finalizeQueue; f; f = finalizerNext(t, f)) { - reinterpret_cast(finalizerFinalize(t, f)) - (t, finalizerTarget(t, f)); - } - m->finalizeQueue = 0; - - killZombies(t, m->rootThread); -} - object makeByteArray(Thread* t, const char* format, va_list a) { @@ -1467,6 +1318,9 @@ Thread::Thread(Machine* m, Allocator* allocator, object javaThread, peer((parent ? parent->child : 0)), child(0), state(NoState), +#ifdef VM_STRESS + stress(false), +#endif // VM_STRESS systemThread(0), javaThread(javaThread), code(0), @@ -1585,6 +1439,8 @@ exit(Thread* t) void enter(Thread* t, Thread::State s) { + stress(t); + if (s == t->state) return; ACQUIRE_RAW(t, t->vm->stateLock); @@ -2198,6 +2054,155 @@ objectMonitor(Thread* t, object o) } } +void +collect(Thread* t, Heap::CollectionType type) +{ + Machine* m = t->vm; + + class Client: public Heap::Client { + public: + Client(Machine* m): m(m) { } + + virtual void visitRoots(Heap::Visitor* v) { + v->visit(&(m->classMap)); + v->visit(&(m->bootstrapClassMap)); + v->visit(&(m->builtinMap)); + v->visit(&(m->monitorMap)); + v->visit(&(m->types)); + + for (Thread* t = m->rootThread; t; t = t->peer) { + ::visitRoots(t, v); + } + + postVisit(m->rootThread, v); + } + + virtual unsigned sizeInWords(object o) { + Thread* t = m->rootThread; + + o = m->heap->follow(mask(o)); + + return extendedSize + (t, o, baseSize(t, o, m->heap->follow(objectClass(t, o)))); + } + + virtual unsigned copiedSizeInWords(object o) { + Thread* t = m->rootThread; + + o = m->heap->follow(mask(o)); + + unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o))); + + if (objectExtended(t, o) or hashTaken(t, o)) { + ++ n; + } + + return n; + } + + virtual void copy(object o, object dst) { + Thread* t = m->rootThread; + + o = m->heap->follow(mask(o)); + object class_ = m->heap->follow(objectClass(t, o)); + + unsigned base = baseSize(t, o, class_); + unsigned n = extendedSize(t, o, base); + + memcpy(dst, o, n * BytesPerWord); + + if (hashTaken(t, o)) { + cast(dst, 0) &= PointerMask; + cast(dst, 0) |= ExtendedMark; + extendedWord(t, dst, base) = takeHash(t, o); + } + } + + virtual void walk(void* p, Heap::Walker* w) { + Thread* t = m->rootThread; + + p = m->heap->follow(mask(p)); + object class_ = m->heap->follow(objectClass(t, p)); + object objectMask = 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(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 = divide(fixedSize, BytesPerWord); + unsigned arrayElementSizeInWords + = divide(arrayElementSize, BytesPerWord); + + for (unsigned i = 0; i < fixedSizeInWords; ++i) { + if (mask[wordOf(i)] & (static_cast(1) << bitOf(i))) { + if (not w->visit(i)) { + return; + } + } + } + + bool arrayObjectElements = false; + for (unsigned j = 0; j < arrayElementSizeInWords; ++j) { + unsigned k = fixedSizeInWords + j; + if (mask[wordOf(k)] & (static_cast(1) << bitOf(k))) { + 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[wordOf(k)] & (static_cast(1) << bitOf(k))) { + if (not w->visit + (fixedSizeInWords + (i * arrayElementSizeInWords) + j)) + { + return; + } + } + } + } + } + } else { + w->visit(0); + } + } + + private: + Machine* m; + } it(m); + + m->unsafe = true; + m->heap->collect(type, &it); + m->unsafe = false; + + postCollect(m->rootThread); + + for (object f = m->finalizeQueue; f; f = finalizerNext(t, f)) { + reinterpret_cast(finalizerFinalize(t, f)) + (t, finalizerTarget(t, f)); + } + m->finalizeQueue = 0; + + killZombies(t, m->rootThread); +} + void noop() { } diff --git a/src/machine.h b/src/machine.h index 32326c1636..1854f99e28 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1172,6 +1172,9 @@ class Thread { Thread* peer; Thread* child; State state; +#ifdef VM_STRESS + bool stress; +#endif // VM_STRESS System::Thread* systemThread; object javaThread; object code; @@ -1192,7 +1195,8 @@ objectClass(Thread*, object o) return mask(cast(o, 0)); } -void enter(Thread* t, Thread::State state); +void +enter(Thread* t, Thread::State state); class StateResource { public: @@ -1207,9 +1211,41 @@ class StateResource { Thread::State oldState; }; +void +collect(Thread* t, Heap::CollectionType type); + +#ifdef VM_STRESS + +inline void +stress(Thread* t) +{ + if ((not t->stress) and t->state != Thread::NoState) { + t->stress = true; + ENTER(t, Thread::ExclusiveState); + +# ifdef VM_STRESS_MAJOR + collect(t, Heap::MajorCollection); +# else // not VM_STRESS_MAJOR + collect(t, Heap::MinorCollection); +# endif // not VM_STRESS_MAJOR + + t->stress = false; + } +} + +#else // not VM_STRESS + +inline void +stress(Thread*) +{ } + +#endif // not VM_STRESS + class MonitorResource { public: MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) { + stress(t); + if (not m->tryAcquire(t)) { ENTER(t, Thread::IdleState); m->acquire(t); @@ -1274,6 +1310,8 @@ allocate2(Thread* t, unsigned sizeInBytes); inline object allocate(Thread* t, unsigned sizeInBytes) { + stress(t); + if (UNLIKELY(t->heapIndex + divide(sizeInBytes, BytesPerWord) >= Thread::HeapSizeInWords or t->vm->exclusive)) @@ -1883,6 +1921,8 @@ objectMonitor(Thread* t, object o); inline void acquire(Thread* t, object o) { + stress(t); + System::Monitor* m = objectMonitor(t, o); if (DebugMonitors) { @@ -1912,6 +1952,8 @@ release(Thread* t, object o) inline void wait(Thread* t, object o, int64_t milliseconds) { + stress(t); + System::Monitor* m = objectMonitor(t, o); if (DebugMonitors) { diff --git a/src/main.cpp b/src/main.cpp index c2439b0b56..120ad63106 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -524,7 +524,7 @@ parsePath(vm::System* s, const char* path) return v; } -void +int run(unsigned heapSize, const char* path, const char* class_, int argc, const char** argv) { @@ -535,7 +535,7 @@ run(unsigned heapSize, const char* path, const char* class_, int argc, Heap* heap = makeHeap(&s); - run(&s, heap, &cf, class_, argc, argv); + int exitCode = run(&s, heap, &cf, class_, argc, argv); heap->dispose(); @@ -544,6 +544,8 @@ run(unsigned heapSize, const char* path, const char* class_, int argc, } s.free(pathv); + + return exitCode; } void @@ -584,7 +586,5 @@ main(int ac, const char** av) usageAndExit(av[0]); } - run(heapSize, path, class_, argc, argv); - - return 0; + return run(heapSize, path, class_, argc, argv); } diff --git a/src/run.cpp b/src/run.cpp index 789a275833..679e598b47 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -2339,7 +2339,7 @@ run(Thread* t, const char* className, const char* methodName, return ::run(t); } -void +int run(System* system, Heap* heap, ClassFinder* classFinder, const char* className, int argc, const char** argv) { @@ -2350,7 +2350,12 @@ run(System* system, Heap* heap, ClassFinder* classFinder, ::run(&t, className, argc, argv); + int exitCode = 0; + if (t.exception) exitCode = -1; + exit(&t); + + return exitCode; } } diff --git a/src/run.h b/src/run.h index e5c8e88298..929320f597 100644 --- a/src/run.h +++ b/src/run.h @@ -12,7 +12,7 @@ object run(Thread* t, const char* className, const char* methodName, const char* methodSpec, ...); -void +int run(System* sys, Heap* heap, ClassFinder* classFinder, const char* className, int argc, const char** argv); diff --git a/classpath/TestExceptions.java b/test/Exceptions.java similarity index 92% rename from classpath/TestExceptions.java rename to test/Exceptions.java index fb12e9f7bc..5983db1c31 100644 --- a/classpath/TestExceptions.java +++ b/test/Exceptions.java @@ -1,4 +1,4 @@ -public class TestExceptions { +public class Exceptions { private static void evenMoreDangerous() { throw new RuntimeException("chaos! panic! overwhelming anxiety!"); diff --git a/classpath/TestGC.java b/test/GC.java similarity index 96% rename from classpath/TestGC.java rename to test/GC.java index f6db02a03e..19befeff1b 100644 --- a/classpath/TestGC.java +++ b/test/GC.java @@ -1,4 +1,4 @@ -public class TestGC { +public class GC { private static void small() { for (int i = 0; i < 1024; ++i) { diff --git a/classpath/Hello.java b/test/Hello.java similarity index 100% rename from classpath/Hello.java rename to test/Hello.java diff --git a/classpath/TestThreads.java b/test/Threads.java similarity index 92% rename from classpath/TestThreads.java rename to test/Threads.java index b4a2366f9f..c411c8c61c 100644 --- a/classpath/TestThreads.java +++ b/test/Threads.java @@ -1,7 +1,6 @@ -public class TestThreads implements Runnable { - +public class Threads implements Runnable { public static void main(String[] args) { - TestThreads test = new TestThreads(); + Threads test = new Threads(); Thread thread = new Thread(test); try { diff --git a/test/test.sh b/test/test.sh new file mode 100644 index 0000000000..d9c47453eb --- /dev/null +++ b/test/test.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +log=build/log.txt + +vm=${1}; shift +flags=${1}; shift +tests=${@} + +echo -n "" >${log} + +for test in ${tests}; do + printf "${test}: " + + ${vm} ${flags} ${test} >>${log} 2>&1 + + if (( ${?} == 0 )); then + echo "success" + else + echo "fail" + trouble=1 + fi +done + +if [ -n "${trouble}" ]; then + printf "\nsee ${log} for output\n" +fi