mirror of
https://github.com/corda/corda.git
synced 2025-03-17 17:45:17 +00:00
Merge branch 'singleton'
This commit is contained in:
commit
bea4a73f54
@ -24,7 +24,7 @@ public final class Class <T> {
|
||||
private Method[] virtualTable;
|
||||
private Field[] fieldTable;
|
||||
private Method[] methodTable;
|
||||
private Object[] staticTable;
|
||||
private Object staticTable;
|
||||
private ClassLoader loader;
|
||||
|
||||
private Class() { }
|
||||
@ -49,7 +49,7 @@ public final class Class <T> {
|
||||
(replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false);
|
||||
}
|
||||
|
||||
public Object[] staticTable() {
|
||||
public Object staticTable() {
|
||||
return staticTable;
|
||||
}
|
||||
|
||||
|
@ -47,176 +47,108 @@ public class Field<T> extends AccessibleObject {
|
||||
}
|
||||
|
||||
public Object get(Object instance) throws IllegalAccessException {
|
||||
Object target;
|
||||
if ((flags & Modifier.STATIC) != 0) {
|
||||
Object v = class_.staticTable()[offset];
|
||||
switch (code) {
|
||||
case ByteField:
|
||||
return Byte.valueOf
|
||||
((byte) (v == null ? 0 : ((Integer) v).intValue()));
|
||||
|
||||
case BooleanField:
|
||||
return Boolean.valueOf
|
||||
(v == null ? false : ((Integer) v) != 0);
|
||||
|
||||
case CharField:
|
||||
return Character.valueOf
|
||||
((char) (v == null ? 0 : ((Integer) v).intValue()));
|
||||
|
||||
case ShortField:
|
||||
return Short.valueOf
|
||||
((short) (v == null ? 0 : ((Integer) v).intValue()));
|
||||
|
||||
case FloatField:
|
||||
return Float.valueOf
|
||||
(Float.intBitsToFloat(v == null ? 0 : (Integer) v));
|
||||
|
||||
case DoubleField:
|
||||
return Double.valueOf
|
||||
(Double.longBitsToDouble(v == null ? 0 : (Long) v));
|
||||
|
||||
case IntField:
|
||||
case LongField:
|
||||
case ObjectField:
|
||||
return v;
|
||||
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
target = class_.staticTable();
|
||||
} else if (class_.isInstance(instance)) {
|
||||
switch (code) {
|
||||
case ByteField:
|
||||
return Byte.valueOf((byte) getPrimitive(instance, code, offset));
|
||||
|
||||
case BooleanField:
|
||||
return Boolean.valueOf(getPrimitive(instance, code, offset) != 0);
|
||||
|
||||
case CharField:
|
||||
return Character.valueOf((char) getPrimitive(instance, code, offset));
|
||||
|
||||
case ShortField:
|
||||
return Short.valueOf((short) getPrimitive(instance, code, offset));
|
||||
|
||||
case IntField:
|
||||
return Integer.valueOf((int) getPrimitive(instance, code, offset));
|
||||
|
||||
case LongField:
|
||||
return Long.valueOf((int) getPrimitive(instance, code, offset));
|
||||
|
||||
case FloatField:
|
||||
return Float.valueOf
|
||||
(Float.intBitsToFloat((int) getPrimitive(instance, code, offset)));
|
||||
|
||||
case DoubleField:
|
||||
return Double.valueOf
|
||||
(Double.longBitsToDouble(getPrimitive(instance, code, offset)));
|
||||
|
||||
case ObjectField:
|
||||
return getObject(instance, offset);
|
||||
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
target = instance;
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case ByteField:
|
||||
return Byte.valueOf((byte) getPrimitive(target, code, offset));
|
||||
|
||||
case BooleanField:
|
||||
return Boolean.valueOf(getPrimitive(target, code, offset) != 0);
|
||||
|
||||
case CharField:
|
||||
return Character.valueOf((char) getPrimitive(target, code, offset));
|
||||
|
||||
case ShortField:
|
||||
return Short.valueOf((short) getPrimitive(target, code, offset));
|
||||
|
||||
case IntField:
|
||||
return Integer.valueOf((int) getPrimitive(target, code, offset));
|
||||
|
||||
case LongField:
|
||||
return Long.valueOf((int) getPrimitive(target, code, offset));
|
||||
|
||||
case FloatField:
|
||||
return Float.valueOf
|
||||
(Float.intBitsToFloat((int) getPrimitive(target, code, offset)));
|
||||
|
||||
case DoubleField:
|
||||
return Double.valueOf
|
||||
(Double.longBitsToDouble(getPrimitive(target, code, offset)));
|
||||
|
||||
case ObjectField:
|
||||
return getObject(target, offset);
|
||||
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
public void set(Object instance, Object value)
|
||||
throws IllegalAccessException
|
||||
{
|
||||
Object target;
|
||||
if ((flags & Modifier.STATIC) != 0) {
|
||||
Object[] a = class_.staticTable();
|
||||
switch (code) {
|
||||
case ByteField:
|
||||
a[offset] = Integer.valueOf((Byte) value);
|
||||
break;
|
||||
|
||||
case BooleanField:
|
||||
a[offset] = Integer.valueOf(((Boolean) value) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
a[offset] = Integer.valueOf((Character) value);
|
||||
break;
|
||||
|
||||
case ShortField:
|
||||
a[offset] = Integer.valueOf((Short) value);
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
a[offset] = Integer.valueOf(Float.floatToRawIntBits((Float) value));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
a[offset] = Long.valueOf(Double.doubleToRawLongBits((Double) value));
|
||||
break;
|
||||
|
||||
case IntField:
|
||||
case LongField:
|
||||
a[offset] = value;
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
if (getType().isInstance(value)) {
|
||||
a[offset] = value;
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
target = class_.staticTable();
|
||||
} else if (class_.isInstance(instance)) {
|
||||
switch (code) {
|
||||
case ByteField:
|
||||
setPrimitive(instance, code, offset, (Byte) value);
|
||||
break;
|
||||
|
||||
case BooleanField:
|
||||
setPrimitive(instance, code, offset, ((Boolean) value) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
setPrimitive(instance, code, offset, (Character) value);
|
||||
break;
|
||||
|
||||
case ShortField:
|
||||
setPrimitive(instance, code, offset, (Short) value);
|
||||
break;
|
||||
|
||||
case IntField:
|
||||
setPrimitive(instance, code, offset, (Integer) value);
|
||||
break;
|
||||
|
||||
case LongField:
|
||||
setPrimitive(instance, code, offset, (Long) value);
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
setPrimitive(instance, code, offset,
|
||||
Float.floatToRawIntBits((Float) value));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
setPrimitive(instance, code, offset,
|
||||
Double.doubleToRawLongBits((Double) value));
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
if (getType().isInstance(value)) {
|
||||
setObject(instance, offset, value);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
target = instance;
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case ByteField:
|
||||
setPrimitive(target, code, offset, (Byte) value);
|
||||
break;
|
||||
|
||||
case BooleanField:
|
||||
setPrimitive(target, code, offset, ((Boolean) value) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
setPrimitive(target, code, offset, (Character) value);
|
||||
break;
|
||||
|
||||
case ShortField:
|
||||
setPrimitive(target, code, offset, (Short) value);
|
||||
break;
|
||||
|
||||
case IntField:
|
||||
setPrimitive(target, code, offset, (Integer) value);
|
||||
break;
|
||||
|
||||
case LongField:
|
||||
setPrimitive(target, code, offset, (Long) value);
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
setPrimitive(target, code, offset,
|
||||
Float.floatToRawIntBits((Float) value));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
setPrimitive(target, code, offset,
|
||||
Double.doubleToRawLongBits((Double) value));
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
if (getType().isInstance(value)) {
|
||||
setObject(target, offset, value);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
private static native long getPrimitive
|
||||
|
@ -11,7 +11,7 @@ public class Method<T> extends AccessibleObject implements Member {
|
||||
private byte[] spec;
|
||||
private Class<T> class_;
|
||||
private Object code;
|
||||
private long compiled;
|
||||
private Object compiled;
|
||||
|
||||
private Method() { }
|
||||
|
||||
|
44
makefile
44
makefile
@ -28,7 +28,7 @@ src = src
|
||||
classpath = classpath
|
||||
test = test
|
||||
|
||||
input = $(test-build)/GC.class
|
||||
input = $(test-build)/Hello.class
|
||||
|
||||
build-cxx = g++
|
||||
build-cc = gcc
|
||||
@ -189,6 +189,7 @@ classpath-sources = $(shell find $(classpath) -name '*.java')
|
||||
classpath-classes = \
|
||||
$(call java-classes,$(classpath-sources),$(classpath),$(classpath-build))
|
||||
classpath-object = $(native-build)/classpath-jar.o
|
||||
classpath-dep = $(classpath-build)/dep
|
||||
|
||||
ifeq ($(platform),darwin)
|
||||
classpath-object =
|
||||
@ -196,6 +197,7 @@ endif
|
||||
|
||||
test-sources = $(wildcard $(test)/*.java)
|
||||
test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
|
||||
test-dep = $(test-build)/dep
|
||||
|
||||
class-name = $(patsubst $(1)/%.class,%,$(2))
|
||||
class-names = $(foreach x,$(2),$(call class-name,$(1),$(x)))
|
||||
@ -204,17 +206,9 @@ flags = -cp $(test-build)
|
||||
args = $(flags) $(call class-name,$(test-build),$(input))
|
||||
|
||||
.PHONY: build
|
||||
build: $(interpreter) $(archive) $(classpath-classes) $(test-classes)
|
||||
build: $(interpreter) $(archive) $(classpath-dep) $(test-dep)
|
||||
|
||||
.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)
|
||||
$(test-classes): $(classpath-dep)
|
||||
|
||||
.PHONY: run
|
||||
run: build
|
||||
@ -253,26 +247,24 @@ $(generated-code): %.cpp: $(src)/types.def $(generator)
|
||||
$(native-build)/type-generator.o: \
|
||||
$(generator-headers)
|
||||
|
||||
define compile-class
|
||||
@echo "compiling $(@)"
|
||||
@mkdir -p $(dir $(@))
|
||||
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
||||
-d $(1) $(<)
|
||||
@touch $(@)
|
||||
endef
|
||||
|
||||
$(classpath-build)/%.class: $(classpath)/%.java
|
||||
@echo "compiling $(@)"
|
||||
@echo $(<)
|
||||
|
||||
$(classpath-dep): $(classpath-sources)
|
||||
@echo "compiling classpath classes"
|
||||
@mkdir -p $(dir $(@))
|
||||
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
||||
-d $(classpath-build) $(<)
|
||||
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
|
||||
$(shell make -s $(classpath-classes))
|
||||
@touch $(@)
|
||||
|
||||
$(test-build)/%.class: $(test)/%.java
|
||||
@echo "compiling $(@)"
|
||||
@echo $(<)
|
||||
|
||||
$(test-dep): $(test-sources)
|
||||
@echo "compiling test classes"
|
||||
@mkdir -p $(dir $(@))
|
||||
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
||||
-d $(test-build) $(<)
|
||||
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
|
||||
$(shell make -s $(test-classes))
|
||||
@touch $(@)
|
||||
|
||||
define compile-object
|
||||
@ -291,7 +283,7 @@ $(interpreter-asm-objects): $(native-build)/%-asm.o: $(src)/%.S
|
||||
$(driver-object): $(native-build)/%.o: $(src)/%.cpp
|
||||
$(compile-object)
|
||||
|
||||
$(build)/classpath.jar: $(classpath-classes)
|
||||
$(build)/classpath.jar: $(classpath-dep)
|
||||
(wd=$$(pwd); \
|
||||
cd $(classpath-build); \
|
||||
$(jar) c0f $${wd}/$(@) $$(find . -name '*.class'))
|
||||
|
@ -733,6 +733,39 @@ findExceptionHandler(Thread* t, int frame)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
pushField(Thread* t, object target, object field)
|
||||
{
|
||||
switch (fieldCode(t, field)) {
|
||||
case ByteField:
|
||||
case BooleanField:
|
||||
pushInt(t, cast<int8_t>(target, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
case ShortField:
|
||||
pushInt(t, cast<int16_t>(target, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
case IntField:
|
||||
pushInt(t, cast<int32_t>(target, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
case LongField:
|
||||
pushLong(t, cast<int64_t>(target, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
pushObject(t, cast<object>(target, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
default:
|
||||
abort(t);
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
interpret(Thread* t)
|
||||
{
|
||||
@ -1399,36 +1432,7 @@ interpret(Thread* t)
|
||||
object field = resolveField(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
|
||||
object instance = popObject(t);
|
||||
|
||||
switch (fieldCode(t, field)) {
|
||||
case ByteField:
|
||||
case BooleanField:
|
||||
pushInt(t, cast<int8_t>(instance, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
case ShortField:
|
||||
pushInt(t, cast<int16_t>(instance, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
case IntField:
|
||||
pushInt(t, cast<int32_t>(instance, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
case LongField:
|
||||
pushLong(t, cast<int64_t>(instance, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
pushObject(t, cast<object>(instance, fieldOffset(t, field)));
|
||||
break;
|
||||
|
||||
default:
|
||||
abort(t);
|
||||
}
|
||||
pushField(t, popObject(t), field);
|
||||
} else {
|
||||
exception = makeNullPointerException(t);
|
||||
goto throw_;
|
||||
@ -1444,30 +1448,7 @@ interpret(Thread* t)
|
||||
|
||||
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
||||
|
||||
object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)),
|
||||
fieldOffset(t, field));
|
||||
|
||||
switch (fieldCode(t, field)) {
|
||||
case ByteField:
|
||||
case BooleanField:
|
||||
case CharField:
|
||||
case ShortField:
|
||||
case FloatField:
|
||||
case IntField:
|
||||
pushInt(t, v ? intValue(t, v) : 0);
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
case LongField:
|
||||
pushLong(t, v ? longValue(t, v) : 0);
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
pushObject(t, v);
|
||||
break;
|
||||
|
||||
default: abort(t);
|
||||
}
|
||||
pushField(t, classStaticTable(t, fieldClass(t, field)), field);
|
||||
} goto loop;
|
||||
|
||||
case goto_: {
|
||||
@ -2389,7 +2370,7 @@ interpret(Thread* t)
|
||||
|
||||
object field = resolveField(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
|
||||
|
||||
switch (fieldCode(t, field)) {
|
||||
case ByteField:
|
||||
case BooleanField:
|
||||
@ -2458,7 +2439,7 @@ interpret(Thread* t)
|
||||
|
||||
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
||||
|
||||
object v;
|
||||
object table = classStaticTable(t, fieldClass(t, field));
|
||||
|
||||
switch (fieldCode(t, field)) {
|
||||
case ByteField:
|
||||
@ -2467,23 +2448,36 @@ interpret(Thread* t)
|
||||
case ShortField:
|
||||
case FloatField:
|
||||
case IntField: {
|
||||
v = makeInt(t, popInt(t));
|
||||
int32_t value = popInt(t);
|
||||
switch (fieldCode(t, field)) {
|
||||
case ByteField:
|
||||
case BooleanField:
|
||||
cast<int8_t>(table, fieldOffset(t, field)) = value;
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
case ShortField:
|
||||
cast<int16_t>(table, fieldOffset(t, field)) = value;
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
case IntField:
|
||||
cast<int32_t>(table, fieldOffset(t, field)) = value;
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case DoubleField:
|
||||
case LongField: {
|
||||
v = makeLong(t, popLong(t));
|
||||
cast<int64_t>(table, fieldOffset(t, field)) = popLong(t);
|
||||
} break;
|
||||
|
||||
case ObjectField:
|
||||
v = popObject(t);
|
||||
break;
|
||||
case ObjectField: {
|
||||
set(t, table, fieldOffset(t, field), popObject(t));
|
||||
} break;
|
||||
|
||||
default: abort(t);
|
||||
}
|
||||
|
||||
set(t, classStaticTable(t, fieldClass(t, field)),
|
||||
ArrayBody + (fieldOffset(t, field) * BytesPerWord), v);
|
||||
} goto loop;
|
||||
|
||||
case ret: {
|
||||
@ -2658,35 +2652,10 @@ pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects,
|
||||
pushObject(t, this_);
|
||||
}
|
||||
|
||||
const char* s = spec;
|
||||
++ s; // skip '('
|
||||
while (*s and *s != ')') {
|
||||
switch (*s) {
|
||||
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
||||
switch (*it.next()) {
|
||||
case 'L':
|
||||
while (*s and *s != ';') ++ s;
|
||||
++ s;
|
||||
|
||||
if (indirectObjects) {
|
||||
object* v = va_arg(a, object*);
|
||||
pushObject(t, v ? *v : 0);
|
||||
} else {
|
||||
pushObject(t, va_arg(a, object));
|
||||
}
|
||||
break;
|
||||
|
||||
case '[':
|
||||
while (*s == '[') ++ s;
|
||||
switch (*s) {
|
||||
case 'L':
|
||||
while (*s and *s != ';') ++ s;
|
||||
++ s;
|
||||
break;
|
||||
|
||||
default:
|
||||
++ s;
|
||||
break;
|
||||
}
|
||||
|
||||
if (indirectObjects) {
|
||||
object* v = va_arg(a, object*);
|
||||
pushObject(t, v ? *v : 0);
|
||||
@ -2697,19 +2666,16 @@ pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects,
|
||||
|
||||
case 'J':
|
||||
case 'D':
|
||||
++ s;
|
||||
pushLong(t, va_arg(a, uint64_t));
|
||||
break;
|
||||
|
||||
case 'F': {
|
||||
++ s;
|
||||
pushFloat(t, va_arg(a, double));
|
||||
} break;
|
||||
|
||||
|
||||
default:
|
||||
++ s;
|
||||
pushInt(t, va_arg(a, uint32_t));
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2722,41 +2688,23 @@ pushArguments(Thread* t, object this_, const char* spec, object a)
|
||||
}
|
||||
|
||||
unsigned index = 0;
|
||||
const char* s = spec;
|
||||
++ s; // skip '('
|
||||
while (*s and *s != ')') {
|
||||
switch (*s) {
|
||||
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
||||
switch (*it.next()) {
|
||||
case 'L':
|
||||
while (*s and *s != ';') ++ s;
|
||||
++ s;
|
||||
pushObject(t, objectArrayBody(t, a, index++));
|
||||
break;
|
||||
|
||||
case '[':
|
||||
while (*s == '[') ++ s;
|
||||
switch (*s) {
|
||||
case 'L':
|
||||
while (*s and *s != ';') ++ s;
|
||||
++ s;
|
||||
break;
|
||||
|
||||
default:
|
||||
++ s;
|
||||
break;
|
||||
}
|
||||
pushObject(t, objectArrayBody(t, a, index++));
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
case 'D':
|
||||
++ s;
|
||||
pushLong(t, cast<int64_t>(objectArrayBody(t, a, index++), BytesPerWord));
|
||||
pushLong(t, cast<int64_t>(objectArrayBody(t, a, index++),
|
||||
BytesPerWord));
|
||||
break;
|
||||
|
||||
default:
|
||||
++ s;
|
||||
pushInt(t, cast<int32_t>(objectArrayBody(t, a, index++), BytesPerWord));
|
||||
break;
|
||||
pushInt(t, cast<int32_t>(objectArrayBody(t, a, index++),
|
||||
BytesPerWord));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2886,56 +2834,33 @@ class MyProcessor: public Processor {
|
||||
return t;
|
||||
}
|
||||
|
||||
virtual void*
|
||||
virtual object
|
||||
methodStub(vm::Thread*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void*
|
||||
virtual object
|
||||
nativeInvoker(vm::Thread*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned
|
||||
parameterFootprint(vm::Thread*, const char* s, bool static_)
|
||||
parameterFootprint(vm::Thread* t, const char* s, bool static_)
|
||||
{
|
||||
unsigned footprint = 0;
|
||||
++ s; // skip '('
|
||||
while (*s and *s != ')') {
|
||||
switch (*s) {
|
||||
case 'L':
|
||||
while (*s and *s != ';') ++ s;
|
||||
++ s;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
while (*s == '[') ++ s;
|
||||
switch (*s) {
|
||||
case 'L':
|
||||
while (*s and *s != ';') ++ s;
|
||||
++ s;
|
||||
break;
|
||||
|
||||
default:
|
||||
++ s;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
for (MethodSpecIterator it(t, s); it.hasNext();) {
|
||||
switch (*it.next()) {
|
||||
case 'J':
|
||||
case 'D':
|
||||
++ s;
|
||||
++ footprint;
|
||||
footprint += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
++ s;
|
||||
break;
|
||||
++ footprint;
|
||||
break;
|
||||
}
|
||||
|
||||
++ footprint;
|
||||
}
|
||||
|
||||
if (not static_) {
|
||||
|
206
src/machine.cpp
206
src/machine.cpp
@ -142,65 +142,77 @@ visitRoots(Thread* t, Heap::Visitor* v)
|
||||
}
|
||||
|
||||
void
|
||||
walk(Thread* t, object o, Heap::Walker* w)
|
||||
walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
|
||||
unsigned arrayElementSize, unsigned arrayLength)
|
||||
{
|
||||
unsigned fixedSizeInWords = ceiling(fixedSize, BytesPerWord);
|
||||
unsigned arrayElementSizeInWords
|
||||
= ceiling(arrayElementSize, BytesPerWord);
|
||||
|
||||
for (unsigned i = 0; i < fixedSizeInWords; ++i) {
|
||||
if (mask[i / 32] & (static_cast<uint32_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<uint32_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<uint32_t>(1) << (k % 32))) {
|
||||
if (not w->visit
|
||||
(fixedSizeInWords + (i * arrayElementSizeInWords) + j))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
walk(Thread* t, Heap::Walker* w, object o)
|
||||
{
|
||||
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)];
|
||||
uint32_t 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]);
|
||||
walk(t, w, mask, fixedSize, arrayElementSize, arrayLength);
|
||||
} else if (classVmFlags(t, class_) & SingletonFlag) {
|
||||
unsigned length = singletonLength(t, o);
|
||||
if (length) {
|
||||
unsigned maskSize = ceiling(length + 2, BitsPerWord + 1);
|
||||
|
||||
unsigned fixedSizeInWords = ceiling(fixedSize, BytesPerWord);
|
||||
unsigned arrayElementSizeInWords
|
||||
= ceiling(arrayElementSize, BytesPerWord);
|
||||
uint32_t mask[maskSize * (BytesPerWord / 4)];
|
||||
memcpy(mask, &singletonBody(t, o, length - maskSize),
|
||||
maskSize * 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
walk(t, w, mask, (length + 2) * BytesPerWord, 0, 0);
|
||||
} else {
|
||||
w->visit(0);
|
||||
}
|
||||
} else {
|
||||
w->visit(0);
|
||||
@ -830,7 +842,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
||||
|
||||
unsigned count = s.read2();
|
||||
if (count) {
|
||||
unsigned staticOffset = 0;
|
||||
unsigned staticOffset = BytesPerWord * 2;
|
||||
unsigned staticCount = 0;
|
||||
|
||||
object fieldTable = makeArray(t, count, true);
|
||||
PROTECT(t, fieldTable);
|
||||
@ -838,6 +851,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
||||
object staticValueTable = makeArray(t, count, true);
|
||||
PROTECT(t, staticValueTable);
|
||||
|
||||
uint8_t staticTypes[count];
|
||||
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
unsigned flags = s.read2();
|
||||
unsigned name = s.read2();
|
||||
@ -860,10 +875,13 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned code = fieldCode
|
||||
(t, byteArrayBody(t, arrayBody(t, pool, spec - 1), 0));
|
||||
|
||||
object field = makeField
|
||||
(t,
|
||||
0, // vm flags
|
||||
fieldCode(t, byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)),
|
||||
code,
|
||||
flags,
|
||||
0, // offset
|
||||
arrayBody(t, pool, name - 1),
|
||||
@ -871,21 +889,32 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
||||
class_);
|
||||
|
||||
if (flags & ACC_STATIC) {
|
||||
set(t, staticValueTable, ArrayBody + (staticOffset * BytesPerWord),
|
||||
unsigned size = fieldSize(t, code);
|
||||
unsigned excess = staticOffset % size;
|
||||
if (excess) {
|
||||
staticOffset += BytesPerWord - excess;
|
||||
}
|
||||
|
||||
fieldOffset(t, field) = staticOffset;
|
||||
|
||||
staticOffset += size;
|
||||
|
||||
set(t, staticValueTable, ArrayBody + (staticCount * BytesPerWord),
|
||||
value);
|
||||
fieldOffset(t, field) = staticOffset++;
|
||||
|
||||
staticTypes[staticCount++] = code;
|
||||
} else {
|
||||
if (value) {
|
||||
abort(t); // todo: handle non-static field initializers
|
||||
}
|
||||
|
||||
unsigned excess = memberOffset % fieldSize(t, field);
|
||||
unsigned excess = memberOffset % fieldSize(t, code);
|
||||
if (excess) {
|
||||
memberOffset += BytesPerWord - excess;
|
||||
}
|
||||
|
||||
fieldOffset(t, field) = memberOffset;
|
||||
memberOffset += fieldSize(t, field);
|
||||
memberOffset += fieldSize(t, code);
|
||||
}
|
||||
|
||||
set(t, fieldTable, ArrayBody + (i * BytesPerWord), field);
|
||||
@ -893,11 +922,69 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
||||
|
||||
set(t, class_, ClassFieldTable, fieldTable);
|
||||
|
||||
if (staticOffset) {
|
||||
object staticTable = makeArray(t, staticOffset, false);
|
||||
memcpy(&arrayBody(t, staticTable, 0),
|
||||
&arrayBody(t, staticValueTable, 0),
|
||||
staticOffset * BytesPerWord);
|
||||
if (staticCount) {
|
||||
unsigned footprint = ceiling(staticOffset - (BytesPerWord * 2),
|
||||
BytesPerWord);
|
||||
unsigned maskSize = ceiling(footprint + 2, BitsPerWord);
|
||||
object staticTable = makeSingleton(t, footprint + maskSize, false);
|
||||
|
||||
uint8_t* body = reinterpret_cast<uint8_t*>
|
||||
(&singletonBody(t, staticTable, 0));
|
||||
|
||||
uint32_t* mask = reinterpret_cast<uint32_t*>
|
||||
(&singletonBody(t, staticTable, footprint));
|
||||
|
||||
memset(mask, 0, maskSize * BytesPerWord);
|
||||
|
||||
mask[0] |= 1;
|
||||
|
||||
for (unsigned i = 0, offset = 0; i < staticCount; ++i) {
|
||||
unsigned size = fieldSize(t, staticTypes[i]);
|
||||
unsigned excess = offset % size;
|
||||
if (excess) {
|
||||
offset += BytesPerWord - excess;
|
||||
}
|
||||
|
||||
object value = arrayBody(t, staticValueTable, i);
|
||||
if (value) {
|
||||
switch (staticTypes[i]) {
|
||||
case ByteField:
|
||||
case BooleanField:
|
||||
body[offset] = intValue(t, value);
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
case ShortField:
|
||||
*reinterpret_cast<uint16_t*>(body + offset) = intValue(t, value);
|
||||
break;
|
||||
|
||||
case IntField:
|
||||
case FloatField:
|
||||
*reinterpret_cast<uint32_t*>(body + offset) = intValue(t, value);
|
||||
break;
|
||||
|
||||
case LongField:
|
||||
case DoubleField:
|
||||
memcpy(body + offset, &longValue(t, value), 8);
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
memcpy(body + offset, &value, BytesPerWord);
|
||||
break;
|
||||
|
||||
default: abort(t);
|
||||
}
|
||||
} else {
|
||||
memset(body + offset, 0, size);
|
||||
}
|
||||
|
||||
if (staticTypes[i] == ObjectField) {
|
||||
unsigned index = (offset / BytesPerWord) + 2;
|
||||
mask[index / 32] |= static_cast<uint32_t>(1) << (index % 32);
|
||||
}
|
||||
|
||||
offset += size;
|
||||
}
|
||||
|
||||
set(t, class_, ClassStaticTable, staticTable);
|
||||
}
|
||||
@ -1116,11 +1203,11 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
||||
unsigned parameterFootprint = t->m->processor->parameterFootprint
|
||||
(t, specString, flags & ACC_STATIC);
|
||||
|
||||
Compiled* compiled;
|
||||
object compiled;
|
||||
if (flags & ACC_NATIVE) {
|
||||
compiled = static_cast<Compiled*>(t->m->processor->nativeInvoker(t));
|
||||
compiled = t->m->processor->nativeInvoker(t);
|
||||
} else {
|
||||
compiled = static_cast<Compiled*>(t->m->processor->methodStub(t));
|
||||
compiled = t->m->processor->methodStub(t);
|
||||
}
|
||||
|
||||
object method = makeMethod(t,
|
||||
@ -1134,7 +1221,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
||||
arrayBody(t, pool, spec - 1),
|
||||
class_,
|
||||
code,
|
||||
reinterpret_cast<uint64_t>(compiled));
|
||||
compiled);
|
||||
PROTECT(t, method);
|
||||
|
||||
if (flags & ACC_STATIC) {
|
||||
@ -1511,7 +1598,7 @@ class HeapClient: public Heap::Client {
|
||||
|
||||
virtual void walk(void* p, Heap::Walker* w) {
|
||||
object o = static_cast<object>(m->heap->follow(mask(p)));
|
||||
::walk(m->rootThread, o, w);
|
||||
::walk(m->rootThread, w, o);
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
@ -1663,6 +1750,9 @@ Thread::init()
|
||||
|
||||
m->unsafe = false;
|
||||
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|
||||
|= SingletonFlag;
|
||||
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|
||||
|= ReferenceFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|
||||
|
@ -62,6 +62,7 @@ const unsigned NeedInitFlag = 1 << 2;
|
||||
const unsigned InitFlag = 1 << 3;
|
||||
const unsigned PrimitiveFlag = 1 << 4;
|
||||
const unsigned BootstrapFlag = 1 << 5;
|
||||
const unsigned SingletonFlag = 1 << 6;
|
||||
|
||||
// method flags:
|
||||
const unsigned ClassInitFlag = 1 << 0;
|
||||
@ -1963,9 +1964,8 @@ unsigned
|
||||
primitiveSize(Thread* t, unsigned code);
|
||||
|
||||
inline unsigned
|
||||
fieldSize(Thread* t, object field)
|
||||
fieldSize(Thread* t, unsigned code)
|
||||
{
|
||||
unsigned code = fieldCode(t, field);
|
||||
if (code == ObjectField) {
|
||||
return BytesPerWord;
|
||||
} else {
|
||||
@ -1973,6 +1973,12 @@ fieldSize(Thread* t, object field)
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
fieldSize(Thread* t, object field)
|
||||
{
|
||||
return fieldSize(t, fieldCode(t, field));
|
||||
}
|
||||
|
||||
object
|
||||
findLoadedClass(Thread* t, object spec);
|
||||
|
||||
|
@ -14,10 +14,10 @@ class Processor {
|
||||
virtual Thread*
|
||||
makeThread(Machine* m, object javaThread, Thread* parent) = 0;
|
||||
|
||||
virtual void*
|
||||
virtual object
|
||||
methodStub(Thread* t) = 0;
|
||||
|
||||
virtual void*
|
||||
virtual object
|
||||
nativeInvoker(Thread* t) = 0;
|
||||
|
||||
virtual unsigned
|
||||
|
@ -786,9 +786,9 @@ namesPointer(const char* s)
|
||||
unsigned
|
||||
sizeOf(const char* type, Object* declarations)
|
||||
{
|
||||
if (equal(type, "object")) {
|
||||
return BytesPerWord;
|
||||
} else if (equal(type, "intptr_t")) {
|
||||
if (equal(type, "object")
|
||||
or equal(type, "intptr_t") or equal(type, "uintptr_t"))
|
||||
{
|
||||
return BytesPerWord;
|
||||
} else if (equal(type, "unsigned") or equal(type, "int")) {
|
||||
return sizeof(int);
|
||||
|
@ -17,6 +17,9 @@
|
||||
(object staticTable)
|
||||
(object loader))
|
||||
|
||||
(type singleton
|
||||
(array uintptr_t body))
|
||||
|
||||
(type classLoader java/lang/ClassLoader
|
||||
(extends jobject)
|
||||
(object parent))
|
||||
@ -60,7 +63,7 @@
|
||||
(object spec)
|
||||
(object class)
|
||||
(object code)
|
||||
(uint64_t compiled))
|
||||
(object compiled))
|
||||
|
||||
(type nativeMethodData
|
||||
(void* function)
|
||||
|
Loading…
x
Reference in New Issue
Block a user