mirror of
https://github.com/corda/corda.git
synced 2025-01-14 16:59:52 +00:00
implement primitive testing framework and provide for GC stress testing
This commit is contained in:
parent
3121002ffd
commit
4670055b03
194
makefile
194
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)
|
||||
|
||||
|
303
src/machine.cpp
303
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<uintptr_t>(dst, 0) &= PointerMask;
|
||||
cast<uintptr_t>(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<uintptr_t>(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<uintptr_t>(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<uintptr_t>(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<uintptr_t>(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<void (*)(Thread*, object)>(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<uintptr_t>(dst, 0) &= PointerMask;
|
||||
cast<uintptr_t>(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<uintptr_t>(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<uintptr_t>(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<uintptr_t>(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<uintptr_t>(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<void (*)(Thread*, object)>(finalizerFinalize(t, f))
|
||||
(t, finalizerTarget(t, f));
|
||||
}
|
||||
m->finalizeQueue = 0;
|
||||
|
||||
killZombies(t, m->rootThread);
|
||||
}
|
||||
|
||||
void
|
||||
noop()
|
||||
{ }
|
||||
|
@ -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<object>(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) {
|
||||
|
10
src/main.cpp
10
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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
public class TestExceptions {
|
||||
public class Exceptions {
|
||||
|
||||
private static void evenMoreDangerous() {
|
||||
throw new RuntimeException("chaos! panic! overwhelming anxiety!");
|
@ -1,4 +1,4 @@
|
||||
public class TestGC {
|
||||
public class GC {
|
||||
|
||||
private static void small() {
|
||||
for (int i = 0; i < 1024; ++i) {
|
@ -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 {
|
26
test/test.sh
Normal file
26
test/test.sh
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user