mirror of
https://github.com/corda/corda.git
synced 2025-01-15 01:10:33 +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)
|
arch = $(shell uname -m)
|
||||||
ifeq ($(arch),i586)
|
ifeq ($(arch),i586)
|
||||||
@ -8,9 +8,13 @@ ifeq ($(arch),i686)
|
|||||||
arch = i386
|
arch = i386
|
||||||
endif
|
endif
|
||||||
|
|
||||||
bld = build/$(arch)
|
mode = debug
|
||||||
|
|
||||||
|
bld = build/$(arch)/$(mode)
|
||||||
|
cls = build/classes
|
||||||
src = src
|
src = src
|
||||||
classpath = classpath
|
classpath = classpath
|
||||||
|
test = test
|
||||||
|
|
||||||
cxx = g++
|
cxx = g++
|
||||||
cc = gcc
|
cc = gcc
|
||||||
@ -21,32 +25,37 @@ javac = javac
|
|||||||
warnings = -Wall -Wextra -Werror -Wold-style-cast -Wunused-parameter \
|
warnings = -Wall -Wextra -Werror -Wold-style-cast -Wunused-parameter \
|
||||||
-Winit-self -Wconversion
|
-Winit-self -Wconversion
|
||||||
|
|
||||||
slow = -O0 -g3
|
|
||||||
fast = -Os -DNDEBUG
|
|
||||||
|
|
||||||
#thread-cflags = -DNO_THREADS
|
|
||||||
thread-cflags = -pthread
|
thread-cflags = -pthread
|
||||||
thread-lflags = -lpthread
|
thread-lflags = -lpthread
|
||||||
|
|
||||||
cflags = $(warnings) -fPIC -fno-rtti -fno-exceptions -fvisibility=hidden \
|
cflags = $(warnings) -fPIC -fno-rtti -fno-exceptions -fvisibility=hidden \
|
||||||
-I$(src) -I$(bld) $(thread-cflags) -D__STDC_LIMIT_MACROS
|
-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
|
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)))
|
cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(bld)/%.o,$(x)))
|
||||||
asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(bld)/%.o,$(x)))
|
asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(bld)/%.o,$(x)))
|
||||||
java-classes = \
|
java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(cls)/%.class,$(x)))
|
||||||
$(foreach x,$(1),$(patsubst $(2)/%.java,$(bld)/classes/%.class,$(x)))
|
|
||||||
|
|
||||||
stdcpp-sources = $(src)/stdc++.cpp
|
stdcpp-sources = $(src)/stdc++.cpp
|
||||||
stdcpp-objects = $(call cpp-objects,$(stdcpp-sources),$(src))
|
stdcpp-objects = $(call cpp-objects,$(stdcpp-sources),$(src))
|
||||||
stdcpp-cflags = $(fast) $(cflags)
|
|
||||||
|
|
||||||
jni-sources = $(classpath)/java/lang/System.cpp
|
jni-sources = $(classpath)/java/lang/System.cpp
|
||||||
jni-objects = $(call cpp-objects,$(jni-sources),$(classpath))
|
jni-objects = $(call cpp-objects,$(jni-sources),$(classpath))
|
||||||
jni-cflags = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux \
|
jni-cflags = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux $(cflags)
|
||||||
$(slow) $(cflags)
|
|
||||||
jni-library = $(bld)/libnatives.so
|
jni-library = $(bld)/libnatives.so
|
||||||
|
|
||||||
generated-code = \
|
generated-code = \
|
||||||
@ -91,7 +100,6 @@ interpreter-asm-objects = \
|
|||||||
interpreter-objects = \
|
interpreter-objects = \
|
||||||
$(interpreter-cpp-objects) \
|
$(interpreter-cpp-objects) \
|
||||||
$(interpreter-asm-objects)
|
$(interpreter-asm-objects)
|
||||||
interpreter-cflags = $(slow) $(cflags)
|
|
||||||
|
|
||||||
generator-headers = \
|
generator-headers = \
|
||||||
$(src)/input.h \
|
$(src)/input.h \
|
||||||
@ -100,53 +108,31 @@ generator-sources = \
|
|||||||
$(src)/type-generator.cpp
|
$(src)/type-generator.cpp
|
||||||
generator-objects = $(call cpp-objects,$(generator-sources),$(src))
|
generator-objects = $(call cpp-objects,$(generator-sources),$(src))
|
||||||
generator-executable = $(bld)/generator
|
generator-executable = $(bld)/generator
|
||||||
generator-cflags = $(slow) $(cflags)
|
|
||||||
|
|
||||||
executable = $(bld)/vm
|
executable = $(bld)/vm
|
||||||
|
|
||||||
test-cpp-objects = \
|
classpath-sources = $(shell find $(classpath) -name '*.java')
|
||||||
$(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-classes = $(call java-classes,$(classpath-sources),$(classpath))
|
classpath-classes = $(call java-classes,$(classpath-sources),$(classpath))
|
||||||
|
|
||||||
input = $(bld)/classes/TestExceptions.class
|
classpath-objects = $(classpath-classes) $(jni-library)
|
||||||
input-depends = \
|
|
||||||
$(classpath-classes) \
|
|
||||||
$(jni-library)
|
|
||||||
|
|
||||||
gen-run-arg = $(shell echo $(1) | sed -e 's:$(bld)/classes/\(.*\)\.class:\1:')
|
test-sources = $(shell find $(test) -name '*.java')
|
||||||
args = -cp $(bld)/classes -hs 67108864 $(call gen-run-arg,$(input))
|
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
|
.PHONY: build
|
||||||
build: $(executable)
|
build: $(executable)
|
||||||
|
|
||||||
$(input): $(input-depends)
|
$(input): $(classpath-objects)
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: $(executable) $(input)
|
run: $(executable) $(input)
|
||||||
@ -156,37 +142,14 @@ run: $(executable) $(input)
|
|||||||
debug: $(executable) $(input)
|
debug: $(executable) $(input)
|
||||||
LD_LIBRARY_PATH=$(bld) gdb --args $(<) $(args)
|
LD_LIBRARY_PATH=$(bld) gdb --args $(<) $(args)
|
||||||
|
|
||||||
.PHONY: fast
|
|
||||||
fast: $(fast-executable)
|
|
||||||
ls -lh $(<)
|
|
||||||
|
|
||||||
.PHONY: vg
|
.PHONY: vg
|
||||||
vg: $(executable) $(input)
|
vg: $(executable) $(input)
|
||||||
LD_LIBRARY_PATH=$(bld) $(vg) $(<) $(args)
|
LD_LIBRARY_PATH=$(bld) $(vg) $(<) $(args)
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: $(test-executable) $(input)
|
test: $(executable) $(classpath-objects) $(test-classes)
|
||||||
LD_LIBRARY_PATH=$(bld) $(vg) $(<) $(args)
|
LD_LIBRARY_PATH=$(bld) /bin/bash $(test)/test.sh \
|
||||||
|
$(<) "$(flags)" $(call class-names,$(test-classes))
|
||||||
.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
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@ -201,61 +164,35 @@ $(generated-code): %.cpp: $(src)/types.def $(generator-executable)
|
|||||||
$(bld)/type-generator.o: \
|
$(bld)/type-generator.o: \
|
||||||
$(generator-headers)
|
$(generator-headers)
|
||||||
|
|
||||||
$(bld)/classes/%.class: $(classpath)/%.java
|
define compile-class
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
$(javac) -bootclasspath $(classpath) -classpath $(classpath) -d $(cls) $(<)
|
||||||
-d $(bld)/classes $(<)
|
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
|
$(stdcpp-objects): $(bld)/%.o: $(src)/%.cpp
|
||||||
@echo "compiling $(@)"
|
$(compile-object)
|
||||||
@mkdir -p $(dir $(@))
|
|
||||||
$(cxx) $(stdcpp-cflags) -c $(<) -o $(@)
|
|
||||||
|
|
||||||
$(interpreter-cpp-objects): $(bld)/%.o: $(src)/%.cpp $(interpreter-depends)
|
$(interpreter-cpp-objects): $(bld)/%.o: $(src)/%.cpp $(interpreter-depends)
|
||||||
@echo "compiling $(@)"
|
$(compile-object)
|
||||||
@mkdir -p $(dir $(@))
|
|
||||||
$(cxx) $(interpreter-cflags) -c $(<) -o $(@)
|
|
||||||
|
|
||||||
$(interpreter-asm-objects): $(bld)/%.o: $(src)/%.S
|
$(interpreter-asm-objects): $(bld)/%.o: $(src)/%.S
|
||||||
@echo "compiling $(@)"
|
$(compile-object)
|
||||||
@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 $(@)
|
|
||||||
|
|
||||||
$(generator-objects): $(bld)/%.o: $(src)/%.cpp
|
$(generator-objects): $(bld)/%.o: $(src)/%.cpp
|
||||||
@echo "compiling $(@)"
|
$(compile-object)
|
||||||
@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 $(@)
|
|
||||||
|
|
||||||
$(jni-objects): $(bld)/%.o: $(classpath)/%.cpp
|
$(jni-objects): $(bld)/%.o: $(classpath)/%.cpp
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@ -270,19 +207,6 @@ $(executable): $(interpreter-objects) $(stdcpp-objects)
|
|||||||
@echo "linking $(@)"
|
@echo "linking $(@)"
|
||||||
$(cc) $(lflags) $(^) -o $(@)
|
$(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
|
.PHONY: generator
|
||||||
generator: $(generator-executable)
|
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
|
object
|
||||||
makeByteArray(Thread* t, const char* format, va_list a)
|
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)),
|
peer((parent ? parent->child : 0)),
|
||||||
child(0),
|
child(0),
|
||||||
state(NoState),
|
state(NoState),
|
||||||
|
#ifdef VM_STRESS
|
||||||
|
stress(false),
|
||||||
|
#endif // VM_STRESS
|
||||||
systemThread(0),
|
systemThread(0),
|
||||||
javaThread(javaThread),
|
javaThread(javaThread),
|
||||||
code(0),
|
code(0),
|
||||||
@ -1585,6 +1439,8 @@ exit(Thread* t)
|
|||||||
void
|
void
|
||||||
enter(Thread* t, Thread::State s)
|
enter(Thread* t, Thread::State s)
|
||||||
{
|
{
|
||||||
|
stress(t);
|
||||||
|
|
||||||
if (s == t->state) return;
|
if (s == t->state) return;
|
||||||
|
|
||||||
ACQUIRE_RAW(t, t->vm->stateLock);
|
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
|
void
|
||||||
noop()
|
noop()
|
||||||
{ }
|
{ }
|
||||||
|
@ -1172,6 +1172,9 @@ class Thread {
|
|||||||
Thread* peer;
|
Thread* peer;
|
||||||
Thread* child;
|
Thread* child;
|
||||||
State state;
|
State state;
|
||||||
|
#ifdef VM_STRESS
|
||||||
|
bool stress;
|
||||||
|
#endif // VM_STRESS
|
||||||
System::Thread* systemThread;
|
System::Thread* systemThread;
|
||||||
object javaThread;
|
object javaThread;
|
||||||
object code;
|
object code;
|
||||||
@ -1192,7 +1195,8 @@ objectClass(Thread*, object o)
|
|||||||
return mask(cast<object>(o, 0));
|
return mask(cast<object>(o, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void enter(Thread* t, Thread::State state);
|
void
|
||||||
|
enter(Thread* t, Thread::State state);
|
||||||
|
|
||||||
class StateResource {
|
class StateResource {
|
||||||
public:
|
public:
|
||||||
@ -1207,9 +1211,41 @@ class StateResource {
|
|||||||
Thread::State oldState;
|
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 {
|
class MonitorResource {
|
||||||
public:
|
public:
|
||||||
MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
|
MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
|
||||||
|
stress(t);
|
||||||
|
|
||||||
if (not m->tryAcquire(t)) {
|
if (not m->tryAcquire(t)) {
|
||||||
ENTER(t, Thread::IdleState);
|
ENTER(t, Thread::IdleState);
|
||||||
m->acquire(t);
|
m->acquire(t);
|
||||||
@ -1274,6 +1310,8 @@ allocate2(Thread* t, unsigned sizeInBytes);
|
|||||||
inline object
|
inline object
|
||||||
allocate(Thread* t, unsigned sizeInBytes)
|
allocate(Thread* t, unsigned sizeInBytes)
|
||||||
{
|
{
|
||||||
|
stress(t);
|
||||||
|
|
||||||
if (UNLIKELY(t->heapIndex + divide(sizeInBytes, BytesPerWord)
|
if (UNLIKELY(t->heapIndex + divide(sizeInBytes, BytesPerWord)
|
||||||
>= Thread::HeapSizeInWords
|
>= Thread::HeapSizeInWords
|
||||||
or t->vm->exclusive))
|
or t->vm->exclusive))
|
||||||
@ -1883,6 +1921,8 @@ objectMonitor(Thread* t, object o);
|
|||||||
inline void
|
inline void
|
||||||
acquire(Thread* t, object o)
|
acquire(Thread* t, object o)
|
||||||
{
|
{
|
||||||
|
stress(t);
|
||||||
|
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
@ -1912,6 +1952,8 @@ release(Thread* t, object o)
|
|||||||
inline void
|
inline void
|
||||||
wait(Thread* t, object o, int64_t milliseconds)
|
wait(Thread* t, object o, int64_t milliseconds)
|
||||||
{
|
{
|
||||||
|
stress(t);
|
||||||
|
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
|
10
src/main.cpp
10
src/main.cpp
@ -524,7 +524,7 @@ parsePath(vm::System* s, const char* path)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
run(unsigned heapSize, const char* path, const char* class_, int argc,
|
run(unsigned heapSize, const char* path, const char* class_, int argc,
|
||||||
const char** argv)
|
const char** argv)
|
||||||
{
|
{
|
||||||
@ -535,7 +535,7 @@ run(unsigned heapSize, const char* path, const char* class_, int argc,
|
|||||||
|
|
||||||
Heap* heap = makeHeap(&s);
|
Heap* heap = makeHeap(&s);
|
||||||
|
|
||||||
run(&s, heap, &cf, class_, argc, argv);
|
int exitCode = run(&s, heap, &cf, class_, argc, argv);
|
||||||
|
|
||||||
heap->dispose();
|
heap->dispose();
|
||||||
|
|
||||||
@ -544,6 +544,8 @@ run(unsigned heapSize, const char* path, const char* class_, int argc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.free(pathv);
|
s.free(pathv);
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -584,7 +586,5 @@ main(int ac, const char** av)
|
|||||||
usageAndExit(av[0]);
|
usageAndExit(av[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
run(heapSize, path, class_, argc, argv);
|
return run(heapSize, path, class_, argc, argv);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -2339,7 +2339,7 @@ run(Thread* t, const char* className, const char* methodName,
|
|||||||
return ::run(t);
|
return ::run(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
run(System* system, Heap* heap, ClassFinder* classFinder,
|
run(System* system, Heap* heap, ClassFinder* classFinder,
|
||||||
const char* className, int argc, const char** argv)
|
const char* className, int argc, const char** argv)
|
||||||
{
|
{
|
||||||
@ -2350,7 +2350,12 @@ run(System* system, Heap* heap, ClassFinder* classFinder,
|
|||||||
|
|
||||||
::run(&t, className, argc, argv);
|
::run(&t, className, argc, argv);
|
||||||
|
|
||||||
|
int exitCode = 0;
|
||||||
|
if (t.exception) exitCode = -1;
|
||||||
|
|
||||||
exit(&t);
|
exit(&t);
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ object
|
|||||||
run(Thread* t, const char* className, const char* methodName,
|
run(Thread* t, const char* className, const char* methodName,
|
||||||
const char* methodSpec, ...);
|
const char* methodSpec, ...);
|
||||||
|
|
||||||
void
|
int
|
||||||
run(System* sys, Heap* heap, ClassFinder* classFinder,
|
run(System* sys, Heap* heap, ClassFinder* classFinder,
|
||||||
const char* className, int argc, const char** argv);
|
const char* className, int argc, const char** argv);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
public class TestExceptions {
|
public class Exceptions {
|
||||||
|
|
||||||
private static void evenMoreDangerous() {
|
private static void evenMoreDangerous() {
|
||||||
throw new RuntimeException("chaos! panic! overwhelming anxiety!");
|
throw new RuntimeException("chaos! panic! overwhelming anxiety!");
|
@ -1,4 +1,4 @@
|
|||||||
public class TestGC {
|
public class GC {
|
||||||
|
|
||||||
private static void small() {
|
private static void small() {
|
||||||
for (int i = 0; i < 1024; ++i) {
|
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) {
|
public static void main(String[] args) {
|
||||||
TestThreads test = new TestThreads();
|
Threads test = new Threads();
|
||||||
Thread thread = new Thread(test);
|
Thread thread = new Thread(test);
|
||||||
|
|
||||||
try {
|
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