mirror of
https://github.com/corda/corda.git
synced 2025-01-17 10:20:02 +00:00
sketch of singleton support
This commit is contained in:
parent
80775f6cf8
commit
e820b6a8a4
@ -24,7 +24,7 @@ public final class Class <T> {
|
|||||||
private Method[] virtualTable;
|
private Method[] virtualTable;
|
||||||
private Field[] fieldTable;
|
private Field[] fieldTable;
|
||||||
private Method[] methodTable;
|
private Method[] methodTable;
|
||||||
private Object[] staticTable;
|
private Object staticTable;
|
||||||
private ClassLoader loader;
|
private ClassLoader loader;
|
||||||
|
|
||||||
private Class() { }
|
private Class() { }
|
||||||
@ -49,7 +49,7 @@ public final class Class <T> {
|
|||||||
(replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false);
|
(replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object[] staticTable() {
|
public Object staticTable() {
|
||||||
return staticTable;
|
return staticTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,68 +47,41 @@ public class Field<T> extends AccessibleObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Object get(Object instance) throws IllegalAccessException {
|
public Object get(Object instance) throws IllegalAccessException {
|
||||||
|
Object target;
|
||||||
if ((flags & Modifier.STATIC) != 0) {
|
if ((flags & Modifier.STATIC) != 0) {
|
||||||
Object v = class_.staticTable()[offset];
|
target = class_.staticTable();
|
||||||
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();
|
|
||||||
}
|
|
||||||
} else if (class_.isInstance(instance)) {
|
} else if (class_.isInstance(instance)) {
|
||||||
|
target = instance;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case ByteField:
|
case ByteField:
|
||||||
return Byte.valueOf((byte) getPrimitive(instance, code, offset));
|
return Byte.valueOf((byte) getPrimitive(target, code, offset));
|
||||||
|
|
||||||
case BooleanField:
|
case BooleanField:
|
||||||
return Boolean.valueOf(getPrimitive(instance, code, offset) != 0);
|
return Boolean.valueOf(getPrimitive(target, code, offset) != 0);
|
||||||
|
|
||||||
case CharField:
|
case CharField:
|
||||||
return Character.valueOf((char) getPrimitive(instance, code, offset));
|
return Character.valueOf((char) getPrimitive(target, code, offset));
|
||||||
|
|
||||||
case ShortField:
|
case ShortField:
|
||||||
return Short.valueOf((short) getPrimitive(instance, code, offset));
|
return Short.valueOf((short) getPrimitive(target, code, offset));
|
||||||
|
|
||||||
case IntField:
|
case IntField:
|
||||||
return Integer.valueOf((int) getPrimitive(instance, code, offset));
|
return Integer.valueOf((int) getPrimitive(target, code, offset));
|
||||||
|
|
||||||
case LongField:
|
case LongField:
|
||||||
return Long.valueOf((int) getPrimitive(instance, code, offset));
|
return Long.valueOf((int) getPrimitive(target, code, offset));
|
||||||
|
|
||||||
case FloatField:
|
case FloatField:
|
||||||
return Float.valueOf
|
return Float.valueOf
|
||||||
(Float.intBitsToFloat((int) getPrimitive(instance, code, offset)));
|
(Float.intBitsToFloat((int) getPrimitive(target, code, offset)));
|
||||||
|
|
||||||
case DoubleField:
|
case DoubleField:
|
||||||
return Double.valueOf
|
return Double.valueOf
|
||||||
(Double.longBitsToDouble(getPrimitive(instance, code, offset)));
|
(Double.longBitsToDouble(getPrimitive(target, code, offset)));
|
||||||
|
|
||||||
case ObjectField:
|
case ObjectField:
|
||||||
return getObject(instance, offset);
|
return getObject(instance, offset);
|
||||||
@ -116,96 +89,58 @@ public class Field<T> extends AccessibleObject {
|
|||||||
default:
|
default:
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(Object instance, Object value)
|
public void set(Object instance, Object value)
|
||||||
throws IllegalAccessException
|
throws IllegalAccessException
|
||||||
{
|
{
|
||||||
|
Object target;
|
||||||
if ((flags & Modifier.STATIC) != 0) {
|
if ((flags & Modifier.STATIC) != 0) {
|
||||||
Object[] a = class_.staticTable();
|
target = class_.staticTable();
|
||||||
switch (code) {
|
} else if (class_.isInstance(instance)) {
|
||||||
case ByteField:
|
target = instance;
|
||||||
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 {
|
} else {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error();
|
|
||||||
}
|
|
||||||
} else if (class_.isInstance(instance)) {
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case ByteField:
|
case ByteField:
|
||||||
setPrimitive(instance, code, offset, (Byte) value);
|
setPrimitive(target, code, offset, (Byte) value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BooleanField:
|
case BooleanField:
|
||||||
setPrimitive(instance, code, offset, ((Boolean) value) ? 1 : 0);
|
setPrimitive(target, code, offset, ((Boolean) value) ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CharField:
|
case CharField:
|
||||||
setPrimitive(instance, code, offset, (Character) value);
|
setPrimitive(target, code, offset, (Character) value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ShortField:
|
case ShortField:
|
||||||
setPrimitive(instance, code, offset, (Short) value);
|
setPrimitive(target, code, offset, (Short) value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IntField:
|
case IntField:
|
||||||
setPrimitive(instance, code, offset, (Integer) value);
|
setPrimitive(target, code, offset, (Integer) value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LongField:
|
case LongField:
|
||||||
setPrimitive(instance, code, offset, (Long) value);
|
setPrimitive(target, code, offset, (Long) value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FloatField:
|
case FloatField:
|
||||||
setPrimitive(instance, code, offset,
|
setPrimitive(target, code, offset,
|
||||||
Float.floatToRawIntBits((Float) value));
|
Float.floatToRawIntBits((Float) value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DoubleField:
|
case DoubleField:
|
||||||
setPrimitive(instance, code, offset,
|
setPrimitive(target, code, offset,
|
||||||
Double.doubleToRawLongBits((Double) value));
|
Double.doubleToRawLongBits((Double) value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjectField:
|
case ObjectField:
|
||||||
if (getType().isInstance(value)) {
|
if (getType().isInstance(value)) {
|
||||||
setObject(instance, offset, value);
|
setObject(target, offset, value);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
@ -214,9 +149,6 @@ public class Field<T> extends AccessibleObject {
|
|||||||
default:
|
default:
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native long getPrimitive
|
private static native long getPrimitive
|
||||||
|
8
makefile
8
makefile
@ -28,7 +28,7 @@ src = src
|
|||||||
classpath = classpath
|
classpath = classpath
|
||||||
test = test
|
test = test
|
||||||
|
|
||||||
input = $(test-build)/GC.class
|
input = $(test-build)/References.class
|
||||||
|
|
||||||
build-cxx = g++
|
build-cxx = g++
|
||||||
build-cc = gcc
|
build-cc = gcc
|
||||||
@ -248,9 +248,6 @@ $(native-build)/type-generator.o: \
|
|||||||
$(classpath-build)/%.class: $(classpath)/%.java
|
$(classpath-build)/%.class: $(classpath)/%.java
|
||||||
@echo $(<)
|
@echo $(<)
|
||||||
|
|
||||||
$(test-build)/%.class: $(test)/%.java
|
|
||||||
@echo $(<)
|
|
||||||
|
|
||||||
$(classpath-dep): $(classpath-sources)
|
$(classpath-dep): $(classpath-sources)
|
||||||
@echo "compiling classpath classes"
|
@echo "compiling classpath classes"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
@ -258,6 +255,9 @@ $(classpath-dep): $(classpath-sources)
|
|||||||
$(shell make -s $(classpath-classes))
|
$(shell make -s $(classpath-classes))
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
|
||||||
|
$(test-build)/%.class: $(test)/%.java
|
||||||
|
@echo $(<)
|
||||||
|
|
||||||
$(test-dep): $(test-sources)
|
$(test-dep): $(test-sources)
|
||||||
@echo "compiling test classes"
|
@echo "compiling test classes"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
|
@ -733,6 +733,39 @@ findExceptionHandler(Thread* t, int frame)
|
|||||||
return 0;
|
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
|
object
|
||||||
interpret(Thread* t)
|
interpret(Thread* t)
|
||||||
{
|
{
|
||||||
@ -1399,36 +1432,7 @@ interpret(Thread* t)
|
|||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
object instance = popObject(t);
|
pushField(t, popObject(t), field);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
exception = makeNullPointerException(t);
|
exception = makeNullPointerException(t);
|
||||||
goto throw_;
|
goto throw_;
|
||||||
@ -1444,30 +1448,7 @@ interpret(Thread* t)
|
|||||||
|
|
||||||
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)),
|
pushField(t, classStaticTable(t, fieldClass(t, field)), 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);
|
|
||||||
}
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case goto_: {
|
case goto_: {
|
||||||
@ -2458,7 +2439,7 @@ interpret(Thread* t)
|
|||||||
|
|
||||||
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
||||||
|
|
||||||
object v;
|
object table = classStaticTable(t, fieldClass(t, field));
|
||||||
|
|
||||||
switch (fieldCode(t, field)) {
|
switch (fieldCode(t, field)) {
|
||||||
case ByteField:
|
case ByteField:
|
||||||
@ -2467,23 +2448,36 @@ interpret(Thread* t)
|
|||||||
case ShortField:
|
case ShortField:
|
||||||
case FloatField:
|
case FloatField:
|
||||||
case IntField: {
|
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;
|
} break;
|
||||||
|
|
||||||
case DoubleField:
|
case DoubleField:
|
||||||
case LongField: {
|
case LongField: {
|
||||||
v = makeLong(t, popLong(t));
|
cast<int64_t>(table, fieldOffset(t, field)) = popLong(t);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ObjectField:
|
case ObjectField: {
|
||||||
v = popObject(t);
|
set(t, table, fieldOffset(t, field), popObject(t));
|
||||||
break;
|
} break;
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(t, classStaticTable(t, fieldClass(t, field)),
|
|
||||||
ArrayBody + (fieldOffset(t, field) * BytesPerWord), v);
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case ret: {
|
case ret: {
|
||||||
@ -2658,35 +2652,10 @@ pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects,
|
|||||||
pushObject(t, this_);
|
pushObject(t, this_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* s = spec;
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
||||||
++ s; // skip '('
|
switch (*it.next()) {
|
||||||
while (*s and *s != ')') {
|
|
||||||
switch (*s) {
|
|
||||||
case 'L':
|
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 '[':
|
case '[':
|
||||||
while (*s == '[') ++ s;
|
|
||||||
switch (*s) {
|
|
||||||
case 'L':
|
|
||||||
while (*s and *s != ';') ++ s;
|
|
||||||
++ s;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
++ s;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indirectObjects) {
|
if (indirectObjects) {
|
||||||
object* v = va_arg(a, object*);
|
object* v = va_arg(a, object*);
|
||||||
pushObject(t, v ? *v : 0);
|
pushObject(t, v ? *v : 0);
|
||||||
@ -2697,17 +2666,14 @@ pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects,
|
|||||||
|
|
||||||
case 'J':
|
case 'J':
|
||||||
case 'D':
|
case 'D':
|
||||||
++ s;
|
|
||||||
pushLong(t, va_arg(a, uint64_t));
|
pushLong(t, va_arg(a, uint64_t));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'F': {
|
case 'F': {
|
||||||
++ s;
|
|
||||||
pushFloat(t, va_arg(a, double));
|
pushFloat(t, va_arg(a, double));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
++ s;
|
|
||||||
pushInt(t, va_arg(a, uint32_t));
|
pushInt(t, va_arg(a, uint32_t));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2722,40 +2688,22 @@ pushArguments(Thread* t, object this_, const char* spec, object a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
const char* s = spec;
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
||||||
++ s; // skip '('
|
switch (*it.next()) {
|
||||||
while (*s and *s != ')') {
|
|
||||||
switch (*s) {
|
|
||||||
case 'L':
|
case 'L':
|
||||||
while (*s and *s != ';') ++ s;
|
|
||||||
++ s;
|
|
||||||
pushObject(t, objectArrayBody(t, a, index++));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
while (*s == '[') ++ s;
|
|
||||||
switch (*s) {
|
|
||||||
case 'L':
|
|
||||||
while (*s and *s != ';') ++ s;
|
|
||||||
++ s;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
++ s;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pushObject(t, objectArrayBody(t, a, index++));
|
pushObject(t, objectArrayBody(t, a, index++));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'J':
|
case 'J':
|
||||||
case 'D':
|
case 'D':
|
||||||
++ s;
|
pushLong(t, cast<int64_t>(objectArrayBody(t, a, index++),
|
||||||
pushLong(t, cast<int64_t>(objectArrayBody(t, a, index++), BytesPerWord));
|
BytesPerWord));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
++ s;
|
pushInt(t, cast<int32_t>(objectArrayBody(t, a, index++),
|
||||||
pushInt(t, cast<int32_t>(objectArrayBody(t, a, index++), BytesPerWord));
|
BytesPerWord));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2899,43 +2847,20 @@ class MyProcessor: public Processor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned
|
virtual unsigned
|
||||||
parameterFootprint(vm::Thread*, const char* s, bool static_)
|
parameterFootprint(vm::Thread* t, const char* s, bool static_)
|
||||||
{
|
{
|
||||||
unsigned footprint = 0;
|
unsigned footprint = 0;
|
||||||
++ s; // skip '('
|
for (MethodSpecIterator it(t, s); it.hasNext();) {
|
||||||
while (*s and *s != ')') {
|
switch (*it.next()) {
|
||||||
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;
|
|
||||||
|
|
||||||
case 'J':
|
case 'J':
|
||||||
case 'D':
|
case 'D':
|
||||||
++ s;
|
footprint += 2;
|
||||||
++ footprint;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
++ s;
|
++ footprint;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
++ footprint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not static_) {
|
if (not static_) {
|
||||||
|
116
src/machine.cpp
116
src/machine.cpp
@ -201,9 +201,19 @@ walk(Thread* t, Heap::Walker* w, object o)
|
|||||||
intArrayLength(t, objectMask) * 4);
|
intArrayLength(t, objectMask) * 4);
|
||||||
|
|
||||||
walk(t, w, mask, fixedSize, arrayElementSize, arrayLength);
|
walk(t, w, mask, fixedSize, arrayElementSize, arrayLength);
|
||||||
// } else if (classVmFlags(t, class_) & SingletonFlag) {
|
} else if (classVmFlags(t, class_) & SingletonFlag) {
|
||||||
// unsigned length = singletonLength(t, o);
|
unsigned length = singletonLength(t, o);
|
||||||
// walk(t, w, mask, fixedSize, 0, 0);
|
if (length) {
|
||||||
|
unsigned maskSize = ceiling(length + 2, BitsPerWord + 1);
|
||||||
|
|
||||||
|
uint32_t mask[maskSize * (BytesPerWord / 4)];
|
||||||
|
memcpy(mask, &singletonBody(t, o, length - maskSize),
|
||||||
|
maskSize * BytesPerWord);
|
||||||
|
|
||||||
|
walk(t, w, mask, length - maskSize, 0, 0);
|
||||||
|
} else {
|
||||||
|
w->visit(0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w->visit(0);
|
w->visit(0);
|
||||||
}
|
}
|
||||||
@ -832,7 +842,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
|
|
||||||
unsigned count = s.read2();
|
unsigned count = s.read2();
|
||||||
if (count) {
|
if (count) {
|
||||||
unsigned staticOffset = 0;
|
unsigned staticOffset = BytesPerWord * 2;
|
||||||
|
unsigned staticCount = 0;
|
||||||
|
|
||||||
object fieldTable = makeArray(t, count, true);
|
object fieldTable = makeArray(t, count, true);
|
||||||
PROTECT(t, fieldTable);
|
PROTECT(t, fieldTable);
|
||||||
@ -840,6 +851,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
object staticValueTable = makeArray(t, count, true);
|
object staticValueTable = makeArray(t, count, true);
|
||||||
PROTECT(t, staticValueTable);
|
PROTECT(t, staticValueTable);
|
||||||
|
|
||||||
|
uint8_t staticTypes[count];
|
||||||
|
|
||||||
for (unsigned i = 0; i < count; ++i) {
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
unsigned flags = s.read2();
|
unsigned flags = s.read2();
|
||||||
unsigned name = s.read2();
|
unsigned name = s.read2();
|
||||||
@ -862,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
|
object field = makeField
|
||||||
(t,
|
(t,
|
||||||
0, // vm flags
|
0, // vm flags
|
||||||
fieldCode(t, byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)),
|
code,
|
||||||
flags,
|
flags,
|
||||||
0, // offset
|
0, // offset
|
||||||
arrayBody(t, pool, name - 1),
|
arrayBody(t, pool, name - 1),
|
||||||
@ -873,21 +889,32 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
class_);
|
class_);
|
||||||
|
|
||||||
if (flags & ACC_STATIC) {
|
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);
|
value);
|
||||||
fieldOffset(t, field) = staticOffset++;
|
|
||||||
|
staticTypes[staticCount++] = code;
|
||||||
} else {
|
} else {
|
||||||
if (value) {
|
if (value) {
|
||||||
abort(t); // todo: handle non-static field initializers
|
abort(t); // todo: handle non-static field initializers
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned excess = memberOffset % fieldSize(t, field);
|
unsigned excess = memberOffset % fieldSize(t, code);
|
||||||
if (excess) {
|
if (excess) {
|
||||||
memberOffset += BytesPerWord - excess;
|
memberOffset += BytesPerWord - excess;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldOffset(t, field) = memberOffset;
|
fieldOffset(t, field) = memberOffset;
|
||||||
memberOffset += fieldSize(t, field);
|
memberOffset += fieldSize(t, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(t, fieldTable, ArrayBody + (i * BytesPerWord), field);
|
set(t, fieldTable, ArrayBody + (i * BytesPerWord), field);
|
||||||
@ -895,11 +922,69 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
|
|
||||||
set(t, class_, ClassFieldTable, fieldTable);
|
set(t, class_, ClassFieldTable, fieldTable);
|
||||||
|
|
||||||
if (staticOffset) {
|
if (staticCount) {
|
||||||
object staticTable = makeArray(t, staticOffset, false);
|
unsigned footprint = ceiling(staticOffset - (BytesPerWord * 2),
|
||||||
memcpy(&arrayBody(t, staticTable, 0),
|
BytesPerWord);
|
||||||
&arrayBody(t, staticValueTable, 0),
|
unsigned maskSize = ceiling(footprint + 2, BitsPerWord);
|
||||||
staticOffset * BytesPerWord);
|
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] |= 1 << (index % 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += size;
|
||||||
|
}
|
||||||
|
|
||||||
set(t, class_, ClassStaticTable, staticTable);
|
set(t, class_, ClassStaticTable, staticTable);
|
||||||
}
|
}
|
||||||
@ -1665,6 +1750,9 @@ Thread::init()
|
|||||||
|
|
||||||
m->unsafe = false;
|
m->unsafe = false;
|
||||||
|
|
||||||
|
classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|
||||||
|
|= SingletonFlag;
|
||||||
|
|
||||||
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|
||||||
|= ReferenceFlag;
|
|= ReferenceFlag;
|
||||||
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|
||||||
|
@ -27,7 +27,7 @@ namespace vm {
|
|||||||
const bool Verbose = false;
|
const bool Verbose = false;
|
||||||
const bool DebugRun = false;
|
const bool DebugRun = false;
|
||||||
const bool DebugStack = false;
|
const bool DebugStack = false;
|
||||||
const bool DebugMonitors = false;
|
const bool DebugMonitors = true;
|
||||||
const bool DebugReferences = false;
|
const bool DebugReferences = false;
|
||||||
|
|
||||||
const uintptr_t HashTakenMark = 1;
|
const uintptr_t HashTakenMark = 1;
|
||||||
@ -62,6 +62,7 @@ const unsigned NeedInitFlag = 1 << 2;
|
|||||||
const unsigned InitFlag = 1 << 3;
|
const unsigned InitFlag = 1 << 3;
|
||||||
const unsigned PrimitiveFlag = 1 << 4;
|
const unsigned PrimitiveFlag = 1 << 4;
|
||||||
const unsigned BootstrapFlag = 1 << 5;
|
const unsigned BootstrapFlag = 1 << 5;
|
||||||
|
const unsigned SingletonFlag = 1 << 6;
|
||||||
|
|
||||||
// method flags:
|
// method flags:
|
||||||
const unsigned ClassInitFlag = 1 << 0;
|
const unsigned ClassInitFlag = 1 << 0;
|
||||||
@ -1963,9 +1964,8 @@ unsigned
|
|||||||
primitiveSize(Thread* t, unsigned code);
|
primitiveSize(Thread* t, unsigned code);
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
fieldSize(Thread* t, object field)
|
fieldSize(Thread* t, unsigned code)
|
||||||
{
|
{
|
||||||
unsigned code = fieldCode(t, field);
|
|
||||||
if (code == ObjectField) {
|
if (code == ObjectField) {
|
||||||
return BytesPerWord;
|
return BytesPerWord;
|
||||||
} else {
|
} else {
|
||||||
@ -1973,6 +1973,12 @@ fieldSize(Thread* t, object field)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
fieldSize(Thread* t, object field)
|
||||||
|
{
|
||||||
|
return fieldSize(t, fieldCode(t, field));
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
findLoadedClass(Thread* t, object spec);
|
findLoadedClass(Thread* t, object spec);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user