sketch of singleton support

This commit is contained in:
Joel Dice 2007-11-02 15:08:14 -06:00
parent 80775f6cf8
commit e820b6a8a4
6 changed files with 279 additions and 328 deletions

View File

@ -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;
} }

View File

@ -47,176 +47,108 @@ 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)) {
switch (code) { target = instance;
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();
}
} else { } else {
throw new IllegalArgumentException(); 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(instance, offset);
default:
throw new Error();
}
} }
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) {
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();
}
} else if (class_.isInstance(instance)) { } else if (class_.isInstance(instance)) {
switch (code) { target = instance;
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();
}
} else { } else {
throw new IllegalArgumentException(); 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 private static native long getPrimitive

View File

@ -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 $(@))

View File

@ -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_: {
@ -2389,7 +2370,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_;
switch (fieldCode(t, field)) { switch (fieldCode(t, field)) {
case ByteField: case ByteField:
case BooleanField: case BooleanField:
@ -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,19 +2666,16 @@ 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,41 +2688,23 @@ 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_) {

View File

@ -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))

View File

@ -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);