mirror of
https://github.com/corda/corda.git
synced 2025-01-04 04:04:27 +00:00
implement fixed object support
This commit is contained in:
parent
6710ca85d7
commit
60072b9fdc
33
makefile
33
makefile
@ -28,7 +28,7 @@ src = src
|
|||||||
classpath = classpath
|
classpath = classpath
|
||||||
test = test
|
test = test
|
||||||
|
|
||||||
input = $(test-build)/Hello.class
|
input = $(test-build)/Enums.class
|
||||||
|
|
||||||
build-cxx = g++
|
build-cxx = g++
|
||||||
build-cc = gcc
|
build-cc = gcc
|
||||||
@ -192,11 +192,11 @@ ifeq ($(platform),darwin)
|
|||||||
classpath-object =
|
classpath-object =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
test-sources = $(shell find $(test) -name '*.java')
|
test-sources = $(wildcard $(test)/*.java)
|
||||||
test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
|
test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
|
||||||
|
|
||||||
class-name = $(patsubst $(1)/%.class,%,$(2))
|
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)
|
flags = -cp $(test-build)
|
||||||
args = $(flags) $(call class-name,$(test-build),$(input))
|
args = $(flags) $(call class-name,$(test-build),$(input))
|
||||||
@ -204,7 +204,15 @@ args = $(flags) $(call class-name,$(test-build),$(input))
|
|||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(interpreter) $(archive) $(classpath-classes) $(test-classes)
|
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
|
.PHONY: run
|
||||||
run: build
|
run: build
|
||||||
@ -221,7 +229,8 @@ vg: build
|
|||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: build
|
test: build
|
||||||
/bin/bash $(test)/test.sh 2>/dev/null \
|
/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
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@ -236,7 +245,7 @@ clean-native:
|
|||||||
gen-arg = $(shell echo $(1) | sed -e 's:$(native-build)/type-\(.*\)\.cpp:\1:')
|
gen-arg = $(shell echo $(1) | sed -e 's:$(native-build)/type-\(.*\)\.cpp:\1:')
|
||||||
$(generated-code): %.cpp: $(src)/types.def $(generator)
|
$(generated-code): %.cpp: $(src)/types.def $(generator)
|
||||||
@echo "generating $(@)"
|
@echo "generating $(@)"
|
||||||
@mkdir -p -m 1777 $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(generator) $(call gen-arg,$(@)) < $(<) > $(@)
|
$(generator) $(call gen-arg,$(@)) < $(<) > $(@)
|
||||||
|
|
||||||
$(native-build)/type-generator.o: \
|
$(native-build)/type-generator.o: \
|
||||||
@ -244,7 +253,7 @@ $(native-build)/type-generator.o: \
|
|||||||
|
|
||||||
define compile-class
|
define compile-class
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p -m 1777 $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
||||||
-d $(1) $(<)
|
-d $(1) $(<)
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
@ -252,21 +261,21 @@ endef
|
|||||||
|
|
||||||
$(classpath-build)/%.class: $(classpath)/%.java
|
$(classpath-build)/%.class: $(classpath)/%.java
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p -m 1777 $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
||||||
-d $(classpath-build) $(<)
|
-d $(classpath-build) $(<)
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
|
||||||
$(test-build)/%.class: $(test)/%.java
|
$(test-build)/%.class: $(test)/%.java
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p -m 1777 $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
||||||
-d $(test-build) $(<)
|
-d $(test-build) $(<)
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
|
||||||
define compile-object
|
define compile-object
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p -m 1777 $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cxx) $(cflags) -c $(<) -o $(@)
|
$(cxx) $(cflags) -c $(<) -o $(@)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
@ -293,12 +302,12 @@ $(classpath-object): $(build)/classpath.jar
|
|||||||
|
|
||||||
$(generator-objects): $(native-build)/%.o: $(src)/%.cpp
|
$(generator-objects): $(native-build)/%.o: $(src)/%.cpp
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p -m 1777 $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(build-cxx) -DPOINTER_SIZE=$(pointer-size) $(build-cflags) -c $(<) -o $(@)
|
$(build-cxx) -DPOINTER_SIZE=$(pointer-size) $(build-cflags) -c $(<) -o $(@)
|
||||||
|
|
||||||
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
|
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p -m 1777 $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cxx) $(jni-cflags) -c $(<) -o $(@)
|
$(cxx) $(jni-cflags) -c $(<) -o $(@)
|
||||||
|
|
||||||
$(archive): $(interpreter-objects) $(jni-objects) $(classpath-object)
|
$(archive): $(interpreter-objects) $(jni-objects) $(classpath-object)
|
||||||
|
@ -109,10 +109,10 @@ Java_java_lang_Object_clone(Thread* t, jclass, jobject o)
|
|||||||
object clone;
|
object clone;
|
||||||
|
|
||||||
if (classArrayElementSize(t, class_)) {
|
if (classArrayElementSize(t, class_)) {
|
||||||
clone = static_cast<object>(allocate(t, size));
|
clone = static_cast<object>(allocate(t, size, classObjectMask(t, class_)));
|
||||||
memcpy(clone, *o, size);
|
memcpy(clone, *o, size);
|
||||||
// clear any object header flags:
|
// clear any object header flags:
|
||||||
cast<object>(*o, 0) = objectClass(t, *o);
|
setObjectClass(t, *o, objectClass(t, *o));
|
||||||
} else {
|
} else {
|
||||||
clone = make(t, objectClass(t, *o));
|
clone = make(t, objectClass(t, *o));
|
||||||
memcpy(reinterpret_cast<void**>(clone) + 1,
|
memcpy(reinterpret_cast<void**>(clone) + 1,
|
||||||
|
@ -232,6 +232,10 @@ bitsToFloat(uint32_t bits)
|
|||||||
return f;
|
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 Machine;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
|
@ -674,7 +674,7 @@ class StackMapper {
|
|||||||
MyProtector(StackMapper* mapper): Protector(mapper->t), mapper(mapper) { }
|
MyProtector(StackMapper* mapper): Protector(mapper->t), mapper(mapper) { }
|
||||||
|
|
||||||
virtual void visit(Heap::Visitor* v) {
|
virtual void visit(Heap::Visitor* v) {
|
||||||
v->visit(&(mapper->method));
|
vm::visit(t, v, &(mapper->method));
|
||||||
}
|
}
|
||||||
|
|
||||||
StackMapper* mapper;
|
StackMapper* mapper;
|
||||||
@ -1073,14 +1073,14 @@ visitParameters(MyThread* t, Heap::Visitor* v, void* frame)
|
|||||||
|
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
if ((methodFlags(t, method) & ACC_STATIC) == 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();) {
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
||||||
switch (*it.next()) {
|
switch (*it.next()) {
|
||||||
case 'L':
|
case 'L':
|
||||||
case '[':
|
case '[':
|
||||||
v->visit(frameLocalObject(t, frame, index++));
|
visit(t, v, frameLocalObject(t, frame, index++));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'J':
|
case 'J':
|
||||||
@ -1122,7 +1122,7 @@ visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* frame)
|
|||||||
|
|
||||||
for (unsigned i = 0; i < count; ++i) {
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
if (getBit(stackMap, 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);
|
void* frame = frameStart(t);
|
||||||
|
|
||||||
if (frameValid(frame)) {
|
if (frameValid(frame)) {
|
||||||
v->visit(&frameMethod(frame));
|
visit(t, v, &frameMethod(frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; frameValid(frame); frame = frameNext(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.
|
// caller is native. Otherwise, the caller owns them.
|
||||||
void* next = frameNext(frame);
|
void* next = frameNext(frame);
|
||||||
if (frameValid(next)) {
|
if (frameValid(next)) {
|
||||||
v->visit(&frameMethod(next));
|
visit(t, v, &frameMethod(next));
|
||||||
|
|
||||||
if (methodFlags(t, frameMethod(next)) & ACC_NATIVE) {
|
if (methodFlags(t, frameMethod(next)) & ACC_NATIVE) {
|
||||||
visitParameters(t, v, frame);
|
visitParameters(t, v, frame);
|
||||||
@ -4573,10 +4573,10 @@ class JavaCompiler: public Compiler {
|
|||||||
MyProtector(JavaCompiler* c): Protector(c->t), c(c) { }
|
MyProtector(JavaCompiler* c): Protector(c->t), c(c) { }
|
||||||
|
|
||||||
virtual void visit(Heap::Visitor* v) {
|
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) {
|
for (unsigned i = 0; i < c->pool.length(); i += BytesPerWord) {
|
||||||
v->visit(reinterpret_cast<object*>(&(c->pool.getAddress(i))));
|
vm::visit(t, v, reinterpret_cast<object*>(&(c->pool.getAddress(i))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4799,7 +4799,7 @@ class ArgumentList {
|
|||||||
virtual void visit(Heap::Visitor* v) {
|
virtual void visit(Heap::Visitor* v) {
|
||||||
for (unsigned i = 0; i < list->position; ++i) {
|
for (unsigned i = 0; i < list->position; ++i) {
|
||||||
if (list->objectMask[i]) {
|
if (list->objectMask[i]) {
|
||||||
v->visit(reinterpret_cast<object*>(list->array + i));
|
vm::visit(t, v, reinterpret_cast<object*>(list->array + i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4984,7 +4984,7 @@ class MyProcessor: public Processor {
|
|||||||
|
|
||||||
if (t->m->active) {
|
if (t->m->active) {
|
||||||
for (Reference* r = t->reference; r; r = r->next) {
|
for (Reference* r = t->reference; r; r = r->next) {
|
||||||
v->visit(&(r->target));
|
visit(t, v, &(r->target));
|
||||||
}
|
}
|
||||||
|
|
||||||
visitStack(t, v);
|
visitStack(t, v);
|
||||||
|
@ -6,10 +6,6 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
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<unsigned>(0);
|
const unsigned Top = ~static_cast<unsigned>(0);
|
||||||
|
|
||||||
const unsigned InitialGen2CapacityInBytes = 4 * 1024 * 1024;
|
const unsigned InitialGen2CapacityInBytes = 4 * 1024 * 1024;
|
||||||
@ -648,6 +644,9 @@ update3(Context* c, void* o, bool* needsVisit)
|
|||||||
if (wasCollected(c, o)) {
|
if (wasCollected(c, o)) {
|
||||||
*needsVisit = false;
|
*needsVisit = false;
|
||||||
return follow(c, o);
|
return follow(c, o);
|
||||||
|
} else if (c->client->checkFixed(o)) {
|
||||||
|
*needsVisit = false;
|
||||||
|
return o;
|
||||||
} else {
|
} else {
|
||||||
*needsVisit = true;
|
*needsVisit = true;
|
||||||
return copy(c, o);
|
return copy(c, o);
|
||||||
|
@ -35,7 +35,7 @@ class Heap {
|
|||||||
public:
|
public:
|
||||||
virtual ~Client() { }
|
virtual ~Client() { }
|
||||||
virtual void visitRoots(Visitor*) = 0;
|
virtual void visitRoots(Visitor*) = 0;
|
||||||
virtual unsigned sizeInWords(void*) = 0;
|
virtual bool checkFixed(void*) = 0;
|
||||||
virtual unsigned copiedSizeInWords(void*) = 0;
|
virtual unsigned copiedSizeInWords(void*) = 0;
|
||||||
virtual void copy(void*, void*) = 0;
|
virtual void copy(void*, void*) = 0;
|
||||||
virtual void walk(void*, Walker*) = 0;
|
virtual void walk(void*, Walker*) = 0;
|
||||||
|
@ -2955,11 +2955,11 @@ class MyProcessor: public Processor {
|
|||||||
{
|
{
|
||||||
Thread* t = static_cast<Thread*>(vmt);
|
Thread* t = static_cast<Thread*>(vmt);
|
||||||
|
|
||||||
v->visit(&(t->code));
|
visit(t, v, &(t->code));
|
||||||
|
|
||||||
for (unsigned i = 0; i < t->sp; ++i) {
|
for (unsigned i = 0; i < t->sp; ++i) {
|
||||||
if (t->stack[i * 2] == ObjectTag) {
|
if (t->stack[i * 2] == ObjectTag) {
|
||||||
v->visit(t->stack + (i * 2) + 1);
|
visit(t, v, reinterpret_cast<object*>(t->stack + (i * 2) + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,11 @@ DestroyJavaVM(Machine* m)
|
|||||||
Processor* p = m->processor;
|
Processor* p = m->processor;
|
||||||
Heap* h = m->heap;
|
Heap* h = m->heap;
|
||||||
Finder* f = m->finder;
|
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();
|
m->dispose();
|
||||||
p->dispose();
|
p->dispose();
|
||||||
@ -1859,7 +1862,7 @@ extern "C" JNIEXPORT jint JNICALL
|
|||||||
JNI_GetDefaultJavaVMInitArgs(void* args)
|
JNI_GetDefaultJavaVMInitArgs(void* args)
|
||||||
{
|
{
|
||||||
JDK1_1InitArgs* a = static_cast<JDK1_1InitArgs*>(args);
|
JDK1_1InitArgs* a = static_cast<JDK1_1InitArgs*>(args);
|
||||||
a->maxHeapSize = 128 * 1024 * 1024;
|
a->maxHeapSize = 64 * 1024 * 1024;
|
||||||
a->classpath = ".";
|
a->classpath = ".";
|
||||||
a->properties = 0;
|
a->properties = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
480
src/machine.cpp
480
src/machine.cpp
@ -115,11 +115,6 @@ footprint(Thread* t)
|
|||||||
{
|
{
|
||||||
unsigned n = t->heapOffset + t->heapIndex;
|
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) {
|
for (Thread* c = t->child; c; c = c->peer) {
|
||||||
n += footprint(c);
|
n += footprint(c);
|
||||||
}
|
}
|
||||||
@ -131,8 +126,8 @@ void
|
|||||||
visitRoots(Thread* t, Heap::Visitor* v)
|
visitRoots(Thread* t, Heap::Visitor* v)
|
||||||
{
|
{
|
||||||
if (t->state != Thread::ZombieState) {
|
if (t->state != Thread::ZombieState) {
|
||||||
v->visit(&(t->javaThread));
|
visit(t, v, &(t->javaThread));
|
||||||
v->visit(&(t->exception));
|
visit(t, v, &(t->exception));
|
||||||
|
|
||||||
t->m->processor->visitObjects(t, v);
|
t->m->processor->visitObjects(t, v);
|
||||||
|
|
||||||
@ -147,9 +142,75 @@ visitRoots(Thread* t, Heap::Visitor* v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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<object>(t->m->heap->follow(objectClass(t, o)));
|
||||||
|
object objectMask = static_cast<object>
|
||||||
|
(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<uintptr_t>(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<uintptr_t>(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<uintptr_t>(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<uintptr_t>(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;
|
object finalizer = *p;
|
||||||
*p = finalizerNext(t, finalizer);
|
*p = finalizerNext(t, finalizer);
|
||||||
@ -158,14 +219,14 @@ finalizerTargetUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p)
|
||||||
{
|
{
|
||||||
if (DebugReferences) {
|
if (DebugReferences) {
|
||||||
fprintf(stderr, "target %p unreachable for reference %p\n",
|
fprintf(stderr, "target %p unreachable for reference %p\n",
|
||||||
jreferenceTarget(t, *p), *p);
|
jreferenceTarget(t, *p), *p);
|
||||||
}
|
}
|
||||||
|
|
||||||
v->visit(p);
|
visit(t, v, p);
|
||||||
jreferenceTarget(t, *p) = 0;
|
jreferenceTarget(t, *p) = 0;
|
||||||
|
|
||||||
if (jreferenceQueue(t, *p)
|
if (jreferenceQueue(t, *p)
|
||||||
@ -173,7 +234,7 @@ referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
|||||||
{
|
{
|
||||||
// queue is reachable - add the reference
|
// queue is reachable - add the reference
|
||||||
|
|
||||||
v->visit(&jreferenceQueue(t, *p));
|
visit(t, v, &jreferenceQueue(t, *p));
|
||||||
|
|
||||||
object q = jreferenceQueue(t, *p);
|
object q = jreferenceQueue(t, *p);
|
||||||
|
|
||||||
@ -192,7 +253,7 @@ referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
referenceUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
referenceUnreachable(Thread* t, Heap::Visitor* v, object* p)
|
||||||
{
|
{
|
||||||
if (DebugReferences) {
|
if (DebugReferences) {
|
||||||
fprintf(stderr, "reference %p unreachable (target %p)\n",
|
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)
|
and t->m->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable)
|
||||||
{
|
{
|
||||||
// queue is reachable - add the reference
|
// queue is reachable - add the reference
|
||||||
referenceTargetUnreachable(t, p, v);
|
referenceTargetUnreachable(t, v, p);
|
||||||
} else {
|
} else {
|
||||||
*p = jreferenceNext(t, *p);
|
*p = jreferenceNext(t, *p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
referenceTargetReachable(Thread* t, object* p, Heap::Visitor* v)
|
referenceTargetReachable(Thread* t, Heap::Visitor* v, object* p)
|
||||||
{
|
{
|
||||||
if (DebugReferences) {
|
if (DebugReferences) {
|
||||||
fprintf(stderr, "target %p reachable for reference %p\n",
|
fprintf(stderr, "target %p reachable for reference %p\n",
|
||||||
jreferenceTarget(t, *p), *p);
|
jreferenceTarget(t, *p), *p);
|
||||||
}
|
}
|
||||||
|
|
||||||
v->visit(p);
|
visit(t, v, p);
|
||||||
v->visit(&jreferenceTarget(t, *p));
|
visit(t, v, &jreferenceTarget(t, *p));
|
||||||
|
|
||||||
if (t->m->heap->status(jreferenceQueue(t, *p)) == Heap::Unreachable) {
|
if (t->m->heap->status(jreferenceQueue(t, *p)) == Heap::Unreachable) {
|
||||||
jreferenceQueue(t, *p) = 0;
|
jreferenceQueue(t, *p) = 0;
|
||||||
} else {
|
} 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<object>(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)
|
postVisit(Thread* t, Heap::Visitor* v)
|
||||||
{
|
{
|
||||||
Machine* m = t->m;
|
Machine* m = t->m;
|
||||||
|
bool major = m->heap->collectionType() == Heap::MajorCollection;
|
||||||
|
|
||||||
for (object* p = &(m->finalizeQueue); *p; p = &(finalizerNext(t, *p))) {
|
for (object* p = &(m->finalizeQueue); *p; p = &(finalizerNext(t, *p))) {
|
||||||
v->visit(p);
|
visit(t, v, p);
|
||||||
v->visit(&finalizerTarget(t, *p));
|
visit(t, v, &finalizerTarget(t, *p));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (object* p = &(m->finalizeQueue); *p; p = &(finalizerNext(t, *p))) {
|
for (object* p = &(m->finalizeQueue); *p; p = &(finalizerNext(t, *p))) {
|
||||||
v->visit(p);
|
visit(t, v, p);
|
||||||
v->visit(&finalizerTarget(t, *p));
|
visit(t, v, &finalizerTarget(t, *p));
|
||||||
}
|
}
|
||||||
|
|
||||||
object firstNewTenuredFinalizer = 0;
|
object firstNewTenuredFinalizer = 0;
|
||||||
object lastNewTenuredFinalizer = 0;
|
object lastNewTenuredFinalizer = 0;
|
||||||
|
|
||||||
for (object* p = &(m->finalizers); *p;) {
|
for (object* p = &(m->finalizers); *p;) {
|
||||||
v->visit(p);
|
visit(t, v, p);
|
||||||
|
|
||||||
if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) {
|
if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) {
|
||||||
// target is unreachable - queue it up for finalization
|
// target is unreachable - queue it up for finalization
|
||||||
finalizerTargetUnreachable(t, p, v);
|
finalizerTargetUnreachable(t, v, p);
|
||||||
} else {
|
} else {
|
||||||
// target is reachable
|
// target is reachable
|
||||||
v->visit(&finalizerTarget(t, *p));
|
visit(t, v, &finalizerTarget(t, *p));
|
||||||
|
|
||||||
if (m->heap->status(*p) == Heap::Tenured) {
|
if (m->heap->status(*p) == Heap::Tenured) {
|
||||||
// the finalizer is tenured, so we remove it from
|
// 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;) {
|
for (object* p = &(m->weakReferences); *p;) {
|
||||||
if (m->heap->status(*p) == Heap::Unreachable) {
|
if (m->heap->status(*p) == Heap::Unreachable) {
|
||||||
// reference is unreachable
|
// reference is unreachable
|
||||||
referenceUnreachable(t, p, v);
|
referenceUnreachable(t, v, p);
|
||||||
} else if (m->heap->status(jreferenceTarget(t, *p))
|
} else if (m->heap->status(jreferenceTarget(t, *p))
|
||||||
== Heap::Unreachable)
|
== Heap::Unreachable)
|
||||||
{
|
{
|
||||||
// target is unreachable
|
// target is unreachable
|
||||||
referenceTargetUnreachable(t, p, v);
|
referenceTargetUnreachable(t, v, p);
|
||||||
} else {
|
} else {
|
||||||
// both reference and target are reachable
|
// both reference and target are reachable
|
||||||
referenceTargetReachable(t, p, v);
|
referenceTargetReachable(t, v, p);
|
||||||
|
|
||||||
if (m->heap->status(*p) == Heap::Tenured) {
|
if (m->heap->status(*p) == Heap::Tenured) {
|
||||||
// the reference is tenured, so we remove it from
|
// 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;) {
|
for (object* p = &(m->tenuredFinalizers); *p;) {
|
||||||
v->visit(p);
|
visit(t, v, p);
|
||||||
|
|
||||||
if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) {
|
if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) {
|
||||||
// target is unreachable - queue it up for finalization
|
// target is unreachable - queue it up for finalization
|
||||||
finalizerTargetUnreachable(t, p, v);
|
finalizerTargetUnreachable(t, v, p);
|
||||||
} else {
|
} else {
|
||||||
// target is reachable
|
// target is reachable
|
||||||
v->visit(&finalizerTarget(t, *p));
|
visit(t, v, &finalizerTarget(t, *p));
|
||||||
p = &finalizerNext(t, *p);
|
p = &finalizerNext(t, *p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,15 +463,15 @@ postVisit(Thread* t, Heap::Visitor* v)
|
|||||||
for (object* p = &(m->tenuredWeakReferences); *p;) {
|
for (object* p = &(m->tenuredWeakReferences); *p;) {
|
||||||
if (m->heap->status(*p) == Heap::Unreachable) {
|
if (m->heap->status(*p) == Heap::Unreachable) {
|
||||||
// reference is unreachable
|
// reference is unreachable
|
||||||
referenceUnreachable(t, p, v);
|
referenceUnreachable(t, v, p);
|
||||||
} else if (m->heap->status(jreferenceTarget(t, *p))
|
} else if (m->heap->status(jreferenceTarget(t, *p))
|
||||||
== Heap::Unreachable)
|
== Heap::Unreachable)
|
||||||
{
|
{
|
||||||
// target is unreachable
|
// target is unreachable
|
||||||
referenceTargetUnreachable(t, p, v);
|
referenceTargetUnreachable(t, v, p);
|
||||||
} else {
|
} else {
|
||||||
// both reference and target are reachable
|
// both reference and target are reachable
|
||||||
referenceTargetReachable(t, p, v);
|
referenceTargetReachable(t, v, p);
|
||||||
p = &jreferenceNext(t, *p);
|
p = &jreferenceNext(t, *p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,11 +500,7 @@ postCollect(Thread* t)
|
|||||||
t->heap = t->defaultHeap;
|
t->heap = t->defaultHeap;
|
||||||
t->heapOffset = 0;
|
t->heapOffset = 0;
|
||||||
t->heapIndex = 0;
|
t->heapIndex = 0;
|
||||||
|
t->allocatedLarge = false;
|
||||||
if (t->large) {
|
|
||||||
t->m->system->free(t->large);
|
|
||||||
t->large = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Thread* c = t->child; c; c = c->peer) {
|
for (Thread* c = t->child; c; c = c->peer) {
|
||||||
postCollect(c);
|
postCollect(c);
|
||||||
@ -1234,7 +1368,8 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
|
|||||||
ENTER(t, Thread::ExclusiveState);
|
ENTER(t, Thread::ExclusiveState);
|
||||||
|
|
||||||
classFlags(t, bootstrapClass) = classFlags(t, class_);
|
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, ClassSuper, classSuper(t, class_));
|
||||||
set(t, bootstrapClass, ClassInterfaceTable, classInterfaceTable(t, class_));
|
set(t, bootstrapClass, ClassInterfaceTable, classInterfaceTable(t, class_));
|
||||||
@ -1404,6 +1539,11 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
|
|||||||
finalizeQueue(0),
|
finalizeQueue(0),
|
||||||
weakReferences(0),
|
weakReferences(0),
|
||||||
tenuredWeakReferences(0),
|
tenuredWeakReferences(0),
|
||||||
|
fixies(0),
|
||||||
|
tenuredFixies(0),
|
||||||
|
dirtyFixies(0),
|
||||||
|
markedFixies(0),
|
||||||
|
visitedFixies(0),
|
||||||
unsafe(false),
|
unsafe(false),
|
||||||
heapPoolIndex(0)
|
heapPoolIndex(0)
|
||||||
{
|
{
|
||||||
@ -1438,6 +1578,12 @@ Machine::dispose()
|
|||||||
r = r->next;
|
r = r->next;
|
||||||
system->free(t);
|
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):
|
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)),
|
peer((parent ? parent->child : 0)),
|
||||||
child(0),
|
child(0),
|
||||||
state(NoState),
|
state(NoState),
|
||||||
|
allocatedLarge(false),
|
||||||
criticalLevel(0),
|
criticalLevel(0),
|
||||||
systemThread(0),
|
systemThread(0),
|
||||||
javaThread(javaThread),
|
javaThread(javaThread),
|
||||||
exception(0),
|
exception(0),
|
||||||
large(0),
|
|
||||||
heapIndex(0),
|
heapIndex(0),
|
||||||
heapOffset(0),
|
heapOffset(0),
|
||||||
protector(0),
|
protector(0),
|
||||||
@ -1479,7 +1625,7 @@ Thread::init()
|
|||||||
|
|
||||||
Thread* t = this;
|
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);
|
memset(t->m->loader, 0, sizeof(void*) * 2);
|
||||||
|
|
||||||
#include "type-initializations.cpp"
|
#include "type-initializations.cpp"
|
||||||
@ -1589,20 +1735,11 @@ Thread::exit()
|
|||||||
void
|
void
|
||||||
Thread::dispose()
|
Thread::dispose()
|
||||||
{
|
{
|
||||||
if (large) {
|
|
||||||
m->system->free(large);
|
|
||||||
large = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (systemThread) {
|
if (systemThread) {
|
||||||
systemThread->dispose();
|
systemThread->dispose();
|
||||||
systemThread = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VM_STRESS
|
m->system->free(defaultHeap);
|
||||||
m->system->free(heap);
|
|
||||||
heap = 0;
|
|
||||||
#endif // VM_STRESS
|
|
||||||
|
|
||||||
m->system->free(this);
|
m->system->free(this);
|
||||||
}
|
}
|
||||||
@ -1632,6 +1769,10 @@ exit(Thread* t)
|
|||||||
function(t, finalizerTarget(t, f));
|
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);
|
disposeAll(t, t->m->rootThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1746,12 +1887,45 @@ enter(Thread* t, Thread::State s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
allocate2(Thread* t, unsigned sizeInBytes)
|
allocateFixed(Thread* t, unsigned sizeInBytes, bool objectMask)
|
||||||
{
|
{
|
||||||
if (sizeInBytes > Thread::HeapSizeInBytes and t->large == 0) {
|
ENTER(t, Thread::ExclusiveState);
|
||||||
return allocateLarge(t, sizeInBytes);
|
|
||||||
|
unsigned mask = objectMask
|
||||||
|
* ceiling(sizeInBytes / BytesPerWord, BytesPerWord)
|
||||||
|
* BytesPerWord;
|
||||||
|
unsigned total = sizeInBytes + FixedFootprint + mask;
|
||||||
|
|
||||||
|
uint8_t* p = static_cast<uint8_t*>(t->m->system->tryAllocate(total));
|
||||||
|
if (p == 0) {
|
||||||
|
collect(t, Heap::MajorCollection);
|
||||||
|
|
||||||
|
p = static_cast<uint8_t*>(t->m->system->allocate(total));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(p + FixedFootprint + sizeInBytes, 0, mask);
|
||||||
|
|
||||||
|
object o = reinterpret_cast<object>(p + FixedFootprint);
|
||||||
|
|
||||||
|
cast<uintptr_t>(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);
|
ACQUIRE_RAW(t, t->m->stateLock);
|
||||||
|
|
||||||
while (t->m->exclusive and t->m->exclusive != t) {
|
while (t->m->exclusive and t->m->exclusive != t) {
|
||||||
@ -1760,11 +1934,14 @@ allocate2(Thread* t, unsigned sizeInBytes)
|
|||||||
ENTER(t, Thread::IdleState);
|
ENTER(t, Thread::IdleState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
if (sizeInBytes <= Thread::HeapSizeInBytes
|
||||||
|
and t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||||
>= Thread::HeapSizeInWords)
|
>= Thread::HeapSizeInWords)
|
||||||
{
|
{
|
||||||
t->heap = 0;
|
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<uintptr_t*>
|
t->heap = static_cast<uintptr_t*>
|
||||||
(t->m->system->tryAllocate(Thread::HeapSizeInBytes));
|
(t->m->system->tryAllocate(Thread::HeapSizeInBytes));
|
||||||
if (t->heap) {
|
if (t->heap) {
|
||||||
@ -1781,7 +1958,7 @@ allocate2(Thread* t, unsigned sizeInBytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sizeInBytes > Thread::HeapSizeInBytes) {
|
if (sizeInBytes > Thread::HeapSizeInBytes) {
|
||||||
return allocateLarge(t, sizeInBytes);
|
return allocateLarge(t, sizeInBytes, objectMask);
|
||||||
} else {
|
} else {
|
||||||
return allocateSmall(t, sizeInBytes);
|
return allocateSmall(t, sizeInBytes);
|
||||||
}
|
}
|
||||||
@ -2533,38 +2710,53 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
Client(Machine* m): m(m) { }
|
Client(Machine* m): m(m) { }
|
||||||
|
|
||||||
virtual void visitRoots(Heap::Visitor* v) {
|
virtual void visitRoots(Heap::Visitor* v) {
|
||||||
v->visit(&(m->loader));
|
Thread* t = m->rootThread;
|
||||||
v->visit(&(m->bootstrapClassMap));
|
|
||||||
v->visit(&(m->monitorMap));
|
visit(t, v, &(m->loader));
|
||||||
v->visit(&(m->stringMap));
|
visit(t, v, &(m->bootstrapClassMap));
|
||||||
v->visit(&(m->types));
|
visit(t, v, &(m->monitorMap));
|
||||||
v->visit(&(m->jniInterfaceTable));
|
visit(t, v, &(m->stringMap));
|
||||||
|
visit(t, v, &(m->types));
|
||||||
|
visit(t, v, &(m->jniInterfaceTable));
|
||||||
|
|
||||||
for (Reference* r = m->jniReferences; r; r = r->next) {
|
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) {
|
for (Thread* t = m->rootThread; t; t = t->peer) {
|
||||||
::visitRoots(t, v);
|
::visitRoots(t, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m->heap->collectionType() == Heap::MinorCollection) {
|
||||||
|
visitDirtyFixies(t, v);
|
||||||
|
}
|
||||||
|
|
||||||
postVisit(m->rootThread, v);
|
postVisit(m->rootThread, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned sizeInWords(void* p) {
|
virtual bool checkFixed(void* p) {
|
||||||
Thread* t = m->rootThread;
|
Thread* t = m->rootThread;
|
||||||
|
object o = static_cast<object>(p);
|
||||||
|
|
||||||
object o = static_cast<object>(m->heap->follow(mask(p)));
|
if (objectFixed(t, o)) {
|
||||||
|
if ((not fixedMarked(t, o))
|
||||||
return extendedSize
|
and m->heap->collectionType() == Heap::MajorCollection
|
||||||
(t, o, baseSize(t, o, static_cast<object>
|
or fixedAge(t, o) < TenureThreshold)
|
||||||
(m->heap->follow(objectClass(t, o)))));
|
{
|
||||||
|
fixedMarked(t, o) = 1;
|
||||||
|
fixedMove(t, o, &(m->markedFixies));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned copiedSizeInWords(void* p) {
|
virtual unsigned copiedSizeInWords(void* p) {
|
||||||
Thread* t = m->rootThread;
|
Thread* t = m->rootThread;
|
||||||
|
|
||||||
object o = static_cast<object>(m->heap->follow(mask(p)));
|
object o = static_cast<object>(m->heap->follow(mask(p)));
|
||||||
|
assert(t, not objectFixed(t, o));
|
||||||
|
|
||||||
unsigned n = baseSize(t, o, static_cast<object>
|
unsigned n = baseSize(t, o, static_cast<object>
|
||||||
(m->heap->follow(objectClass(t, o))));
|
(m->heap->follow(objectClass(t, o))));
|
||||||
@ -2580,6 +2772,8 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
Thread* t = m->rootThread;
|
Thread* t = m->rootThread;
|
||||||
|
|
||||||
object src = static_cast<object>(m->heap->follow(mask(srcp)));
|
object src = static_cast<object>(m->heap->follow(mask(srcp)));
|
||||||
|
assert(t, not objectFixed(t, src));
|
||||||
|
|
||||||
object class_ = static_cast<object>
|
object class_ = static_cast<object>
|
||||||
(m->heap->follow(objectClass(t, src)));
|
(m->heap->follow(objectClass(t, src)));
|
||||||
|
|
||||||
@ -2601,67 +2795,9 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
Thread* t = m->rootThread;
|
Thread* t = m->rootThread;
|
||||||
|
|
||||||
object o = static_cast<object>(m->heap->follow(mask(p)));
|
object o = static_cast<object>(m->heap->follow(mask(p)));
|
||||||
object class_ = static_cast<object>(m->heap->follow(objectClass(t, o)));
|
assert(t, not objectFixed(t, o));
|
||||||
object objectMask = static_cast<object>
|
|
||||||
(m->heap->follow(classObjectMask(t, class_)));
|
|
||||||
|
|
||||||
if (objectMask) {
|
::walk(m->rootThread, o, w);
|
||||||
// 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 = ceiling(fixedSize, BytesPerWord);
|
|
||||||
unsigned arrayElementSizeInWords
|
|
||||||
= ceiling(arrayElementSize, BytesPerWord);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < fixedSizeInWords; ++i) {
|
|
||||||
if (mask[i / 32] & (static_cast<uintptr_t>(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<uintptr_t>(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<uintptr_t>(1) << (k % 32))) {
|
|
||||||
if (not w->visit
|
|
||||||
(fixedSizeInWords + (i * arrayElementSizeInWords) + j))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
w->visit(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -2687,6 +2823,8 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
m->system->free(m->heapPool[i]);
|
m->system->free(m->heapPool[i]);
|
||||||
}
|
}
|
||||||
m->heapPoolIndex = 0;
|
m->heapPoolIndex = 0;
|
||||||
|
|
||||||
|
sweepFixies(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2769,6 +2907,84 @@ makeTrace(Thread* t, uintptr_t start)
|
|||||||
return trace;
|
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<void*>(o, offset))) {
|
||||||
|
ACQUIRE_RAW(t, t->m->heapLock);
|
||||||
|
|
||||||
|
t->m->heap->mark(&cast<void*>(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<void*>(o, j))) {
|
||||||
|
t->m->heap->mark(&cast<void*>(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<object>(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
|
void
|
||||||
noop()
|
noop()
|
||||||
{ }
|
{ }
|
||||||
|
158
src/machine.h
158
src/machine.h
@ -34,6 +34,13 @@ const uintptr_t HashTakenMark = 1;
|
|||||||
const uintptr_t ExtendedMark = 2;
|
const uintptr_t ExtendedMark = 2;
|
||||||
const uintptr_t FixedMark = 3;
|
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 {
|
enum FieldCode {
|
||||||
VoidField,
|
VoidField,
|
||||||
ByteField,
|
ByteField,
|
||||||
@ -1147,6 +1154,11 @@ class Machine {
|
|||||||
object finalizeQueue;
|
object finalizeQueue;
|
||||||
object weakReferences;
|
object weakReferences;
|
||||||
object tenuredWeakReferences;
|
object tenuredWeakReferences;
|
||||||
|
object fixies;
|
||||||
|
object tenuredFixies;
|
||||||
|
object dirtyFixies;
|
||||||
|
object markedFixies;
|
||||||
|
object visitedFixies;
|
||||||
bool unsafe;
|
bool unsafe;
|
||||||
JavaVMVTable javaVMVTable;
|
JavaVMVTable javaVMVTable;
|
||||||
JNIEnvVTable jniEnvVTable;
|
JNIEnvVTable jniEnvVTable;
|
||||||
@ -1163,6 +1175,9 @@ threadInterrupted(Thread* t, object thread);
|
|||||||
void
|
void
|
||||||
enterActiveState(Thread* t);
|
enterActiveState(Thread* t);
|
||||||
|
|
||||||
|
void
|
||||||
|
visit(Thread* t, Heap::Visitor* v, object* p);
|
||||||
|
|
||||||
class Thread {
|
class Thread {
|
||||||
public:
|
public:
|
||||||
enum State {
|
enum State {
|
||||||
@ -1196,7 +1211,7 @@ class Thread {
|
|||||||
SingleProtector(Thread* t, object* p): Protector(t), p(p) { }
|
SingleProtector(Thread* t, object* p): Protector(t), p(p) { }
|
||||||
|
|
||||||
virtual void visit(Heap::Visitor* v) {
|
virtual void visit(Heap::Visitor* v) {
|
||||||
v->visit(p);
|
vm::visit(t, v, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
object* p;
|
object* p;
|
||||||
@ -1251,11 +1266,11 @@ class Thread {
|
|||||||
Thread* peer;
|
Thread* peer;
|
||||||
Thread* child;
|
Thread* child;
|
||||||
State state;
|
State state;
|
||||||
|
bool allocatedLarge;
|
||||||
unsigned criticalLevel;
|
unsigned criticalLevel;
|
||||||
System::Thread* systemThread;
|
System::Thread* systemThread;
|
||||||
object javaThread;
|
object javaThread;
|
||||||
object exception;
|
object exception;
|
||||||
object large;
|
|
||||||
unsigned heapIndex;
|
unsigned heapIndex;
|
||||||
unsigned heapOffset;
|
unsigned heapOffset;
|
||||||
Protector* protector;
|
Protector* protector;
|
||||||
@ -1406,25 +1421,23 @@ expect(Thread* t, bool v)
|
|||||||
expect(t->m->system, v);
|
expect(t->m->system, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
object
|
||||||
allocateLarge(Thread* t, unsigned sizeInBytes)
|
allocateFixed(Thread* t, unsigned sizeInBytes, bool objectMask);
|
||||||
{
|
|
||||||
return t->large = static_cast<object>(t->m->system->allocate(sizeInBytes));
|
object
|
||||||
}
|
allocate2(Thread* t, unsigned sizeInBytes, bool objectMask);
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
allocateSmall(Thread* t, unsigned sizeInBytes)
|
allocateSmall(Thread* t, unsigned sizeInBytes)
|
||||||
{
|
{
|
||||||
object o = reinterpret_cast<object>(t->heap + t->heapIndex);
|
object o = reinterpret_cast<object>(t->heap + t->heapIndex);
|
||||||
t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
|
t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
|
||||||
|
cast<object>(o, 0) = 0;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
|
||||||
allocate2(Thread* t, unsigned sizeInBytes);
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
allocate(Thread* t, unsigned sizeInBytes)
|
allocate(Thread* t, unsigned sizeInBytes, bool objectMask)
|
||||||
{
|
{
|
||||||
stress(t);
|
stress(t);
|
||||||
|
|
||||||
@ -1432,7 +1445,7 @@ allocate(Thread* t, unsigned sizeInBytes)
|
|||||||
>= Thread::HeapSizeInWords
|
>= Thread::HeapSizeInWords
|
||||||
or t->m->exclusive))
|
or t->m->exclusive))
|
||||||
{
|
{
|
||||||
return allocate2(t, sizeInBytes);
|
return allocate2(t, sizeInBytes, objectMask);
|
||||||
} else {
|
} else {
|
||||||
return allocateSmall(t, sizeInBytes);
|
return allocateSmall(t, sizeInBytes);
|
||||||
}
|
}
|
||||||
@ -1441,6 +1454,9 @@ allocate(Thread* t, unsigned sizeInBytes)
|
|||||||
void
|
void
|
||||||
mark(Thread* t, object target, unsigned offset);
|
mark(Thread* t, object target, unsigned offset);
|
||||||
|
|
||||||
|
void
|
||||||
|
mark(Thread* t, object target, unsigned offset, unsigned count);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
set(Thread* t, object target, unsigned offset, object value)
|
set(Thread* t, object target, unsigned offset, object value)
|
||||||
{
|
{
|
||||||
@ -1489,41 +1505,93 @@ baseSize(Thread* t, object o, object class_)
|
|||||||
BytesPerWord);
|
BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void*
|
||||||
mark(Thread* t, object target, unsigned offset, unsigned count)
|
fixedStart(Thread* t UNUSED, object o)
|
||||||
{
|
{
|
||||||
ACQUIRE_RAW(t, t->m->heapLock);
|
assert(t, objectFixed(t, o));
|
||||||
if (objectFixed(t, target)) {
|
return &cast<object>(o, - FixedFootprint);
|
||||||
unsigned size = baseSize(t, target, objectClass(t, target))
|
}
|
||||||
* BytesPerWord;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < count; ++i) {
|
inline uint8_t&
|
||||||
markBit(&cast<uintptr_t>(target, size), offset + (i * BytesPerWord));
|
fixedAge(Thread* t UNUSED, object o)
|
||||||
}
|
{
|
||||||
} else {
|
assert(t, objectFixed(t, o));
|
||||||
for (unsigned i = 0; i < count; ++i) {
|
return cast<uint8_t>(o, - (FixedFootprint - FixedAge));
|
||||||
unsigned j = offset + (i * BytesPerWord);
|
}
|
||||||
if (t->m->heap->needsMark(&cast<void*>(target, j))) {
|
|
||||||
t->m->heap->mark(&cast<void*>(target, j));
|
inline uint8_t&
|
||||||
}
|
fixedMarked(Thread* t UNUSED, object o)
|
||||||
}
|
{
|
||||||
|
assert(t, objectFixed(t, o));
|
||||||
|
return cast<uint8_t>(o, - (FixedFootprint - FixedMarked));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t&
|
||||||
|
fixedDirty(Thread* t UNUSED, object o)
|
||||||
|
{
|
||||||
|
assert(t, objectFixed(t, o));
|
||||||
|
return cast<uint8_t>(o, - (FixedFootprint - FixedDirty));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object*&
|
||||||
|
fixedHandle(Thread* t UNUSED, object o)
|
||||||
|
{
|
||||||
|
assert(t, objectFixed(t, o));
|
||||||
|
return cast<object*>(o, - (FixedFootprint - FixedHandle));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object&
|
||||||
|
fixedNext(Thread* t UNUSED, object o)
|
||||||
|
{
|
||||||
|
assert(t, objectFixed(t, o));
|
||||||
|
return cast<object>(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
|
inline void
|
||||||
mark(Thread* t, object target, unsigned offset)
|
fixedMove(Thread* t, object o, object* handle)
|
||||||
{
|
{
|
||||||
if (objectFixed(t, target)) {
|
fixedRemove(t, o);
|
||||||
unsigned size = baseSize(t, target, objectClass(t, target)) * BytesPerWord;
|
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<uintptr_t>(o, size * BytesPerWord);
|
||||||
|
}
|
||||||
|
|
||||||
markBit(&cast<uintptr_t>(target, size), offset);
|
inline uintptr_t*
|
||||||
} else if (t->m->heap->needsMark(&cast<void*>(target, offset))) {
|
fixedMask(Thread* t, object o)
|
||||||
ACQUIRE_RAW(t, t->m->heapLock);
|
{
|
||||||
|
return fixedMask(t, o, baseSize(t, o, objectClass(t, o)));
|
||||||
t->m->heap->mark(&cast<void*>(target, offset));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
@ -1664,10 +1732,10 @@ makeNew(Thread* t, object class_)
|
|||||||
{
|
{
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
unsigned sizeInBytes = pad(classFixedSize(t, class_));
|
unsigned sizeInBytes = pad(classFixedSize(t, class_));
|
||||||
object instance = allocate(t, sizeInBytes);
|
object instance = allocate(t, sizeInBytes, classObjectMask(t, class_));
|
||||||
cast<object>(instance, 0) = class_;
|
setObjectClass(t, instance, class_);
|
||||||
memset(&cast<object>(instance, 0) + 1, 0,
|
memset(&cast<object>(instance, BytesPerWord), 0,
|
||||||
sizeInBytes - sizeof(object));
|
sizeInBytes - BytesPerWord);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@ -1696,9 +1764,6 @@ make(Thread* t, object class_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
|
||||||
make(Thread* t, object class_);
|
|
||||||
|
|
||||||
object
|
object
|
||||||
makeByteArray(Thread* t, const char* format, ...);
|
makeByteArray(Thread* t, const char* format, ...);
|
||||||
|
|
||||||
@ -1738,9 +1803,10 @@ markHashTaken(Thread* t, object o)
|
|||||||
{
|
{
|
||||||
assert(t, not objectExtended(t, o));
|
assert(t, not objectExtended(t, o));
|
||||||
assert(t, not objectFixed(t, o));
|
assert(t, not objectFixed(t, o));
|
||||||
cast<uintptr_t>(o, 0) |= HashTakenMark;
|
|
||||||
|
|
||||||
ACQUIRE_RAW(t, t->m->heapLock);
|
ACQUIRE_RAW(t, t->m->heapLock);
|
||||||
|
|
||||||
|
cast<uintptr_t>(o, 0) |= HashTakenMark;
|
||||||
t->m->heap->pad(o, 1);
|
t->m->heap->pad(o, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
src/main.cpp
27
src/main.cpp
@ -7,6 +7,33 @@ extern "C" void __cxa_pure_virtual(void) { abort(); }
|
|||||||
|
|
||||||
void operator delete(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 {
|
namespace {
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -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*
|
const char*
|
||||||
obfuscate(const char* s)
|
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
|
void
|
||||||
writeConstructorInitializations(Output* out, Object* t)
|
writeConstructorInitializations(Output* out, Object* t)
|
||||||
{
|
{
|
||||||
@ -1361,6 +1400,28 @@ typeMemberCount(Object* o)
|
|||||||
return length(typeMembers(o)) + typeMemberCount(typeSuper(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
|
void
|
||||||
writeConstructorDeclarations(Output* out, Object* declarations)
|
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
|
void
|
||||||
writeConstructors(Output* out, Object* declarations)
|
writeConstructors(Output* out, Object* declarations)
|
||||||
{
|
{
|
||||||
@ -1390,7 +1482,7 @@ writeConstructors(Output* out, Object* declarations)
|
|||||||
Object* o = car(p);
|
Object* o = car(p);
|
||||||
switch (o->type) {
|
switch (o->type) {
|
||||||
case Object::Type: {
|
case Object::Type: {
|
||||||
out->write("object\nmake");
|
out->write("object make");
|
||||||
out->write(capitalize(typeName(o)));
|
out->write(capitalize(typeName(o)));
|
||||||
if (typeHideConstructor(o)) out->write("0");
|
if (typeHideConstructor(o)) out->write("0");
|
||||||
out->write("(Thread* t");
|
out->write("(Thread* t");
|
||||||
@ -1399,14 +1491,18 @@ writeConstructors(Output* out, Object* declarations)
|
|||||||
|
|
||||||
out->write(")\n{\n");
|
out->write(")\n{\n");
|
||||||
|
|
||||||
|
bool hasObjectMask = false;
|
||||||
for (MemberIterator it(o); it.hasMore();) {
|
for (MemberIterator it(o); it.hasMore();) {
|
||||||
Object* m = it.next();
|
Object* m = it.next();
|
||||||
if (m->type == Object::Scalar
|
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(" PROTECT(t, ");
|
||||||
out->write(obfuscate(memberName(m)));
|
out->write(obfuscate(memberName(m)));
|
||||||
out->write(");\n");
|
out->write(");\n");
|
||||||
|
|
||||||
|
hasObjectMask = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1438,14 +1534,19 @@ writeConstructors(Output* out, Object* declarations)
|
|||||||
|
|
||||||
out->write(" object o = allocate(t, ");
|
out->write(" object o = allocate(t, ");
|
||||||
writeOffset(out, typeOffset(o), true);
|
writeOffset(out, typeOffset(o), true);
|
||||||
|
if (hasObjectMask) {
|
||||||
|
out->write(", true");
|
||||||
|
} else {
|
||||||
|
out->write(", false");
|
||||||
|
}
|
||||||
out->write(");\n");
|
out->write(");\n");
|
||||||
|
|
||||||
out->write(" cast<object>(o, 0) ");
|
out->write(" init");
|
||||||
out->write("= arrayBody(t, t->m->types, Machine::");
|
|
||||||
out->write(capitalize(typeName(o)));
|
out->write(capitalize(typeName(o)));
|
||||||
out->write("Type);\n");
|
if (typeHideConstructor(o)) out->write("0");
|
||||||
|
out->write("(t, o");
|
||||||
writeConstructorInitializations(out, o);
|
writeConstructorArguments(out, o);
|
||||||
|
out->write(");\n");
|
||||||
|
|
||||||
out->write(" return o;\n}\n\n");
|
out->write(" return o;\n}\n\n");
|
||||||
} break;
|
} 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
|
unsigned
|
||||||
typeArrayElementSize(Object* type)
|
typeArrayElementSize(Object* type)
|
||||||
{
|
{
|
||||||
@ -1673,8 +1755,7 @@ writeInitializations(Output* out, Object* declarations)
|
|||||||
|
|
||||||
out->write("t->m->types = allocate(t, pad((");
|
out->write("t->m->types = allocate(t, pad((");
|
||||||
out->write(count);
|
out->write(count);
|
||||||
out->write(" * BytesPerWord) + (BytesPerWord * 2)));\n");
|
out->write(" * BytesPerWord) + (BytesPerWord * 2)), true);\n");
|
||||||
out->write("cast<object>(t->m->types, 0) = 0;\n");
|
|
||||||
out->write("arrayLength(t, t->m->types) = ");
|
out->write("arrayLength(t, t->m->types) = ");
|
||||||
out->write(count);
|
out->write(count);
|
||||||
out->write(";\n");
|
out->write(";\n");
|
||||||
@ -1763,10 +1844,12 @@ main(int ac, char** av)
|
|||||||
if (ac == 1 or equal(av[1], "declarations")) {
|
if (ac == 1 or equal(av[1], "declarations")) {
|
||||||
writePods(&out, declarations);
|
writePods(&out, declarations);
|
||||||
writeAccessors(&out, declarations);
|
writeAccessors(&out, declarations);
|
||||||
|
writeInitializerDeclarations(&out, declarations);
|
||||||
writeConstructorDeclarations(&out, declarations);
|
writeConstructorDeclarations(&out, declarations);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ac == 1 or equal(av[1], "constructors")) {
|
if (ac == 1 or equal(av[1], "constructors")) {
|
||||||
|
writeInitializers(&out, declarations);
|
||||||
writeConstructors(&out, declarations);
|
writeConstructors(&out, declarations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,13 @@ public class GC {
|
|||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
byte[] a = new byte[16 * 1024 * 1024];
|
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) {
|
public static void main(String[] args) {
|
||||||
|
Loading…
Reference in New Issue
Block a user