diff --git a/makefile b/makefile index 21d1eb6c97..c000eddd8c 100644 --- a/makefile +++ b/makefile @@ -28,7 +28,7 @@ src = src classpath = classpath test = test -input = $(test-build)/References.class +input = $(test-build)/List.class build-cxx = g++ build-cc = gcc diff --git a/src/interpret.cpp b/src/interpret.cpp index 7ac781103f..9ac471f900 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -2051,36 +2051,33 @@ interpret(Thread* t) index = codeReadInt16(t, code, ip); } - object v = arrayBody(t, codePool(t, code), index - 1); + object pool = codePool(t, code); - if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::IntType) - or objectClass(t, v) == arrayBody(t, t->m->types, Machine::FloatType)) - { - pushInt(t, intValue(t, v)); - } else if (objectClass(t, v) - == arrayBody(t, t->m->types, Machine::StringType)) - { - pushObject(t, v); + if (singletonIsObject(t, pool, index - 1)) { + object v = singletonObject(t, pool, index - 1); + if (objectClass(t, v) + == arrayBody(t, t->m->types, Machine::ByteArrayType)) + { + object class_ = resolveClassInPool(t, pool, index - 1); + if (UNLIKELY(exception)) goto throw_; + + pushObject(t, class_); + } else { + pushObject(t, v); + } } else { - object class_ = resolveClassInPool(t, codePool(t, code), index - 1); - if (UNLIKELY(exception)) goto throw_; - - pushObject(t, class_); + pushInt(t, singletonValue(t, pool, index - 1)); } } goto loop; case ldc2_w: { uint16_t index = codeReadInt16(t, code, ip); - object v = arrayBody(t, codePool(t, code), index - 1); + object pool = codePool(t, code); - if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::LongType) - or objectClass(t, v) == arrayBody(t, t->m->types, Machine::DoubleType)) - { - pushLong(t, longValue(t, v)); - } else { - abort(t); - } + uint64_t v; + memcpy(&v, &singletonValue(t, pool, index - 1), 8); + pushLong(t, v); } goto loop; case ldiv_: { @@ -2863,15 +2860,45 @@ class MyProcessor: public Processor { } virtual object - methodStub(vm::Thread*) + makeMethod(vm::Thread* t, + uint8_t vmFlags, + uint8_t returnCode, + uint8_t parameterCount, + uint8_t parameterFootprint, + uint16_t flags, + uint16_t offset, + object name, + object spec, + object class_, + object code) { - return 0; + return vm::makeMethod + (t, vmFlags, returnCode, parameterCount, parameterFootprint, flags, + offset, name, spec, class_, code, 0); } virtual object - nativeInvoker(vm::Thread*) + makeClass(vm::Thread* t, + uint16_t flags, + uint8_t vmFlags, + uint8_t arrayDimensions, + uint16_t fixedSize, + uint16_t arrayElementSize, + object objectMask, + object name, + object super, + object interfaceTable, + object virtualTable, + object fieldTable, + object methodTable, + object staticTable, + object loader, + unsigned vtableLength UNUSED) { - return 0; + return vm::makeClass + (t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize, + objectMask, name, super, interfaceTable, virtualTable, fieldTable, + methodTable, staticTable, loader, 0, false); } virtual unsigned diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 5f5b72accc..19b86025dc 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -197,15 +197,15 @@ IsInstanceOf(Thread* t, jobject o, jclass c) } object -findMethod(Thread* t, object class_, const char* name, const char* spec) +findMethod(Thread* t, object c, const char* name, const char* spec) { - ENTER(t, Thread::ActiveState); + PROTECT(t, c); object n = makeByteArray(t, "%s", name); PROTECT(t, n); object s = makeByteArray(t, "%s", spec); - return vm::findMethod(t, class_, n, s); + return vm::findMethod(t, c, n, s); } jmethodID JNICALL diff --git a/src/machine.cpp b/src/machine.cpp index 1714ef7cee..7ae3c6a9f2 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -204,13 +204,8 @@ walk(Thread* t, Heap::Walker* w, object o) } else if (classVmFlags(t, class_) & SingletonFlag) { unsigned length = singletonLength(t, o); 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 + 2) * BytesPerWord, 0, 0); + walk(t, w, singletonMask(t, o), + (singletonCount(t, o) + 2) * BytesPerWord, 0, 0); } else { w->visit(0); } @@ -617,127 +612,151 @@ parseUtf8(Thread* t, Stream& s, unsigned length) return value; } +unsigned +parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) +{ + PROTECT(t, pool); + + s.setPosition(index[i]); + + switch (s.read1()) { + case CONSTANT_Integer: + case CONSTANT_Float: { + singletonValue(t, pool, i) = s.read4(); + } return 1; + + case CONSTANT_Long: + case CONSTANT_Double: { + uint64_t v = s.read8(); + memcpy(&singletonValue(t, pool, i), &v, 8); + } return 2; + + case CONSTANT_Utf8: { + if (singletonObject(t, pool, i) == 0) { + object value = parseUtf8(t, s, s.read2()); + set(t, pool, SingletonBody + (i * BytesPerWord), value); + } + } return 1; + + case CONSTANT_Class: { + if (singletonObject(t, pool, i) == 0) { + unsigned si = s.read2() - 1; + parsePoolEntry(t, s, index, pool, si); + + object value = singletonObject(t, pool, si); + set(t, pool, SingletonBody + (i * BytesPerWord), value); + } + } return 1; + + case CONSTANT_String: { + if (singletonObject(t, pool, i) == 0) { + unsigned si = s.read2() - 1; + parsePoolEntry(t, s, index, pool, si); + + object value = singletonObject(t, pool, si); + value = makeString(t, value, 0, byteArrayLength(t, value) - 1, 0); + value = intern(t, value); + set(t, pool, SingletonBody + (i * BytesPerWord), value); + } + } return 1; + + case CONSTANT_NameAndType: { + if (singletonObject(t, pool, i) == 0) { + unsigned ni = s.read2() - 1; + unsigned ti = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, ni); + parsePoolEntry(t, s, index, pool, ti); + + object name = singletonObject(t, pool, ni); + object type = singletonObject(t, pool, ti); + object value = makePair(t, name, type); + set(t, pool, SingletonBody + (i * BytesPerWord), value); + } + } return 1; + + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: { + if (singletonObject(t, pool, i) == 0) { + unsigned ci = s.read2() - 1; + unsigned nti = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, ci); + parsePoolEntry(t, s, index, pool, nti); + + object class_ = singletonObject(t, pool, ci); + object nameAndType = singletonObject(t, pool, nti); + object value = makeReference + (t, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType)); + set(t, pool, SingletonBody + (i * BytesPerWord), value); + } + } return 1; + + default: abort(t); + } +} + object parsePool(Thread* t, Stream& s) { - unsigned poolCount = s.read2() - 1; - object pool = makeArray(t, poolCount, true); + unsigned count = s.read2() - 1; - PROTECT(t, pool); + object pool = makeSingleton(t, count); - for (unsigned i = 0; i < poolCount; ++i) { - unsigned c = s.read1(); + if (count) { + uint32_t* index = static_cast + (t->m->system->allocate(count * 4)); - switch (c) { - case CONSTANT_Integer: { - object value = makeInt(t, s.read4()); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; + for (unsigned i = 0; i < count; ++i) { + index[i] = s.position(); - case CONSTANT_Float: { - object value = makeInt(t, s.readFloat()); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; + switch (s.read1()) { + case CONSTANT_Class: + case CONSTANT_String: + singletonMarkObject(t, pool, i); + s.skip(2); + break; - case CONSTANT_Long: { - object value = makeLong(t, s.read8()); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - ++i; - } break; + case CONSTANT_Integer: + case CONSTANT_Float: + s.skip(4); + break; - case CONSTANT_Double: { - object value = makeLong(t, s.readDouble()); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - ++i; - } break; - - case CONSTANT_Utf8: { - object value = parseUtf8(t, s, s.read2()); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; - - case CONSTANT_Class: { - object value = makeIntArray(t, 2, false); - intArrayBody(t, value, 0) = c; - intArrayBody(t, value, 1) = s.read2(); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; - - case CONSTANT_String: { - object value = makeIntArray(t, 2, false); - intArrayBody(t, value, 0) = c; - intArrayBody(t, value, 1) = s.read2(); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; - - case CONSTANT_NameAndType: { - object value = makeIntArray(t, 3, false); - intArrayBody(t, value, 0) = c; - intArrayBody(t, value, 1) = s.read2(); - intArrayBody(t, value, 2) = s.read2(); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; - - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: { - object value = makeIntArray(t, 3, false); - intArrayBody(t, value, 0) = c; - intArrayBody(t, value, 1) = s.read2(); - intArrayBody(t, value, 2) = s.read2(); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; - - default: abort(t); - } - } - - for (unsigned i = 0; i < poolCount; ++i) { - object o = arrayBody(t, pool, i); - if (o and objectClass(t, o) - == arrayBody(t, t->m->types, Machine::IntArrayType)) - { - switch (intArrayBody(t, o, 0)) { - case CONSTANT_Class: { - set(t, pool, ArrayBody + (i * BytesPerWord), - arrayBody(t, pool, intArrayBody(t, o, 1) - 1)); - } break; - - case CONSTANT_String: { - object bytes = arrayBody(t, pool, intArrayBody(t, o, 1) - 1); - object value = makeString - (t, bytes, 0, byteArrayLength(t, bytes) - 1, 0); - value = intern(t, value); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; - - case CONSTANT_NameAndType: { - object name = arrayBody(t, pool, intArrayBody(t, o, 1) - 1); - object type = arrayBody(t, pool, intArrayBody(t, o, 2) - 1); - object value = makePair(t, name, type); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; - } - } - } - - for (unsigned i = 0; i < poolCount; ++i) { - object o = arrayBody(t, pool, i); - if (o and objectClass(t, o) - == arrayBody(t, t->m->types, Machine::IntArrayType)) - { - switch (intArrayBody(t, o, 0)) { + case CONSTANT_NameAndType: case CONSTANT_Fieldref: case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: { - object c = arrayBody(t, pool, intArrayBody(t, o, 1) - 1); - object nameAndType = arrayBody(t, pool, intArrayBody(t, o, 2) - 1); - object value = makeReference - (t, c, pairFirst(t, nameAndType), pairSecond(t, nameAndType)); - set(t, pool, ArrayBody + (i * BytesPerWord), value); - } break; + case CONSTANT_InterfaceMethodref: + singletonMarkObject(t, pool, i); + s.skip(4); + break; + + case CONSTANT_Long: + case CONSTANT_Double: + s.skip(8); + ++ i; + break; + + case CONSTANT_Utf8: + singletonMarkObject(t, pool, i); + s.skip(s.read2()); + break; + + default: abort(t); } } + + unsigned end = s.position(); + + PROTECT(t, pool); + + for (unsigned i = 0; i < count;) { + i += parsePoolEntry(t, s, index, pool, i); + } + + t->m->system->free(index); + + s.setPosition(end); } return pool; @@ -780,7 +799,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool) unsigned count = s.read2(); for (unsigned i = 0; i < count; ++i) { - object name = arrayBody(t, pool, s.read2() - 1); + object name = singletonObject(t, pool, s.read2() - 1); PROTECT(t, name); object interface = resolveClass(t, name); @@ -861,31 +880,53 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) object value = 0; PROTECT(t, value); + unsigned code = fieldCode + (t, byteArrayBody(t, singletonObject(t, pool, spec - 1), 0)); + unsigned attributeCount = s.read2(); for (unsigned j = 0; j < attributeCount; ++j) { - object name = arrayBody(t, pool, s.read2() - 1); + object name = singletonObject(t, pool, s.read2() - 1); unsigned length = s.read4(); if (strcmp(reinterpret_cast("ConstantValue"), &byteArrayBody(t, name, 0)) == 0) { - value = arrayBody(t, pool, s.read2() - 1); + switch (code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case IntField: + case FloatField: + value = makeInt(t, singletonValue(t, pool, s.read2() - 1)); + break; + + case LongField: + case DoubleField: { + uint64_t v; + memcpy(&v, &singletonValue(t, pool, s.read2() - 1), 8); + value = makeLong(t, v); + } break; + + case ObjectField: + value = singletonObject(t, pool, s.read2() - 1); + break; + + default: abort(t); + } } else { s.skip(length); } } - unsigned code = fieldCode - (t, byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)); - object field = makeField (t, 0, // vm flags code, flags, 0, // offset - arrayBody(t, pool, name - 1), - arrayBody(t, pool, spec - 1), + singletonObject(t, pool, name - 1), + singletonObject(t, pool, spec - 1), class_); if (flags & ACC_STATIC) { @@ -925,19 +966,11 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) if (staticCount) { unsigned footprint = ceiling(staticOffset - (BytesPerWord * 2), BytesPerWord); - unsigned maskSize = ceiling(footprint + 2, BitsPerWord); - object staticTable = makeSingleton(t, footprint + maskSize, false); + object staticTable = makeSingleton(t, footprint); uint8_t* body = reinterpret_cast (&singletonBody(t, staticTable, 0)); - uint32_t* mask = reinterpret_cast - (&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; @@ -979,8 +1012,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) } if (staticTypes[i] == ObjectField) { - unsigned index = (offset / BytesPerWord) + 2; - mask[index / 32] |= static_cast(1) << (index % 32); + singletonMarkObject(t, staticTable, offset / BytesPerWord); } offset += size; @@ -1064,7 +1096,7 @@ parseCode(Thread* t, Stream& s, object pool) unsigned attributeCount = s.read2(); for (unsigned j = 0; j < attributeCount; ++j) { - object name = arrayBody(t, pool, s.read2() - 1); + object name = singletonObject(t, pool, s.read2() - 1); unsigned length = s.read4(); if (strcmp(reinterpret_cast("LineNumberTable"), @@ -1181,7 +1213,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) object code = 0; unsigned attributeCount = s.read2(); for (unsigned j = 0; j < attributeCount; ++j) { - object name = arrayBody(t, pool, s.read2() - 1); + object name = singletonObject(t, pool, s.read2() - 1); unsigned length = s.read4(); if (strcmp(reinterpret_cast("Code"), @@ -1194,7 +1226,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) } const char* specString = reinterpret_cast - (&byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)); + (&byteArrayBody(t, singletonObject(t, pool, spec - 1), 0)); unsigned parameterCount; unsigned returnCode; @@ -1203,25 +1235,19 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) unsigned parameterFootprint = t->m->processor->parameterFootprint (t, specString, flags & ACC_STATIC); - object compiled; - if (flags & ACC_NATIVE) { - compiled = t->m->processor->nativeInvoker(t); - } else { - compiled = t->m->processor->methodStub(t); - } + object method = t->m->processor->makeMethod + (t, + 0, // vm flags + returnCode, + parameterCount, + parameterFootprint, + flags, + 0, // offset + singletonObject(t, pool, name - 1), + singletonObject(t, pool, spec - 1), + class_, + code); - object method = makeMethod(t, - 0, // vm flags - returnCode, - parameterCount, - parameterFootprint, - flags, - 0, // offset - arrayBody(t, pool, name - 1), - arrayBody(t, pool, spec - 1), - class_, - code, - compiled); PROTECT(t, method); if (methodVirtual(t, method)) { @@ -1357,6 +1383,35 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) } } +void +updateClassTables(Thread* t, object newClass, object oldClass) +{ + object fieldTable = classFieldTable(t, newClass); + if (fieldTable) { + for (unsigned i = 0; i < arrayLength(t, fieldTable); ++i) { + set(t, arrayBody(t, fieldTable, i), FieldClass, newClass); + } + } + + if (classFlags(t, newClass) & ACC_INTERFACE) { + object virtualTable = classVirtualTable(t, newClass); + if (virtualTable) { + for (unsigned i = 0; i < arrayLength(t, virtualTable); ++i) { + if (methodClass(t, arrayBody(t, virtualTable, i)) == oldClass) { + set(t, arrayBody(t, virtualTable, i), MethodClass, newClass); + } + } + } + } else { + object methodTable = classMethodTable(t, newClass); + if (methodTable) { + for (unsigned i = 0; i < arrayLength(t, methodTable); ++i) { + set(t, arrayBody(t, methodTable, i), MethodClass, newClass); + } + } + } +} + void updateBootstrapClass(Thread* t, object bootstrapClass, object class_) { @@ -1364,7 +1419,10 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_) // verify that the classes have the same layout expect(t, classSuper(t, bootstrapClass) == classSuper(t, class_)); - expect(t, classFixedSize(t, bootstrapClass) == classFixedSize(t, class_)); + + expect(t, bootstrapClass == arrayBody(t, t->m->types, Machine::ClassType) + or classFixedSize(t, bootstrapClass) == classFixedSize(t, class_)); + expect(t, (classVmFlags(t, bootstrapClass) & ReferenceFlag) or (classObjectMask(t, bootstrapClass) == 0 @@ -1388,19 +1446,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_) set(t, bootstrapClass, ClassMethodTable, classMethodTable(t, class_)); set(t, bootstrapClass, ClassStaticTable, classStaticTable(t, class_)); - object fieldTable = classFieldTable(t, class_); - if (fieldTable) { - for (unsigned i = 0; i < arrayLength(t, fieldTable); ++i) { - set(t, arrayBody(t, fieldTable, i), FieldClass, bootstrapClass); - } - } - - object methodTable = classMethodTable(t, class_); - if (methodTable) { - for (unsigned i = 0; i < arrayLength(t, methodTable); ++i) { - set(t, arrayBody(t, methodTable, i), MethodClass, bootstrapClass); - } - } + updateClassTables(t, bootstrapClass, class_); } object @@ -1408,7 +1454,10 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec, object elementClass) { // todo: arrays should implement Cloneable and Serializable - return makeClass + object vtable = classVirtualTable + (t, arrayBody(t, t->m->types, Machine::JobjectType)); + + return t->m->processor->makeClass (t, 0, 0, @@ -1419,11 +1468,12 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec, spec, arrayBody(t, t->m->types, Machine::JobjectType), 0, - classVirtualTable(t, arrayBody(t, t->m->types, Machine::JobjectType)), + vtable, 0, 0, elementClass, - t->m->loader); + t->m->loader, + arrayLength(t, vtable)); } object @@ -1517,7 +1567,7 @@ invoke(Thread* t, const char* className, int argc, const char** argv) void bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask, - unsigned fixedSize, unsigned arrayElementSize) + unsigned fixedSize, unsigned arrayElementSize, unsigned vtableLength) { object mask; if (objectMask) { @@ -1529,9 +1579,9 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask, object super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0); - object class_ = makeClass + object class_ = t->m->processor->makeClass (t, 0, BootstrapFlag, 0, fixedSize, arrayElementSize, mask, 0, super, 0, 0, - 0, 0, 0, t->m->loader); + 0, 0, 0, t->m->loader, vtableLength); set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_); } @@ -2517,7 +2567,7 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) public: Client(Thread* t): t(t) { } - virtual void NO_RETURN handleEOS() { + virtual void NO_RETURN handleError() { abort(t); } @@ -2545,19 +2595,21 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) 0, // fixed size 0, // array size 0, // object mask - arrayBody(t, pool, name - 1), + singletonObject(t, pool, name - 1), 0, // super 0, // interfaces 0, // vtable 0, // fields 0, // methods 0, // static table - t->m->loader); + t->m->loader, + 0, // vtable length + false); PROTECT(t, class_); unsigned super = s.read2(); if (super) { - object sc = resolveClass(t, arrayBody(t, pool, super - 1)); + object sc = resolveClass(t, singletonObject(t, pool, super - 1)); if (UNLIKELY(t->exception)) return 0; set(t, class_, ClassSuper, sc); @@ -2575,7 +2627,30 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) parseMethodTable(t, s, class_, pool); if (UNLIKELY(t->exception)) return 0; - return class_; + object vtable = classVirtualTable(t, class_); + unsigned vtableLength = (vtable ? arrayLength(t, vtable) : 0); + + object real = t->m->processor->makeClass + (t, + classFlags(t, class_), + classVmFlags(t, class_), + classArrayDimensions(t, class_), + classFixedSize(t, class_), + classArrayElementSize(t, class_), + classObjectMask(t, class_), + className(t, class_), + classSuper(t, class_), + classInterfaceTable(t, class_), + classVirtualTable(t, class_), + classFieldTable(t, class_), + classMethodTable(t, class_), + classStaticTable(t, class_), + classLoader(t, class_), + vtableLength); + + updateClassTables(t, real, class_); + + return real; } object @@ -2616,7 +2691,9 @@ resolveClass(Thread* t, object spec) if (LIKELY(t->exception == 0)) { if (Verbose) { - fprintf(stderr, "done parsing %s\n", &byteArrayBody(t, spec, 0)); + fprintf(stderr, "done parsing %s: %p\n", + &byteArrayBody(t, spec, 0), + class_); } object bootstrapClass = hashMapFind diff --git a/src/machine.h b/src/machine.h index f6bbb6181a..0e16fa85f3 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2188,6 +2188,79 @@ methodVirtual(Thread* t, object method) and byteArrayBody(t, methodName(t, method), 0) != '<'; } +inline unsigned +singletonMaskSize(unsigned count) +{ + if (count) { + return ceiling(count + 2, BitsPerWord); + } + return 0; +} + +inline unsigned +singletonMaskSize(Thread* t, object singleton) +{ + unsigned length = singletonLength(t, singleton); + if (length) { + return ceiling(length + 2, BitsPerWord + 1); + } + return 0; +} + +inline unsigned +singletonCount(Thread* t, object singleton) +{ + return singletonLength(t, singleton) - singletonMaskSize(t, singleton); +} + +inline uint32_t* +singletonMask(Thread* t, object singleton) +{ + assert(t, singletonLength(t, singleton)); + return reinterpret_cast + (&singletonBody(t, singleton, singletonCount(t, singleton))); +} + +inline void +singletonMarkObject(Thread* t, object singleton, unsigned index) +{ + singletonMask(t, singleton)[(index + 2) / 32] + |= (static_cast(1) << ((index + 2) % 32)); +} + +inline bool +singletonIsObject(Thread* t, object singleton, unsigned index) +{ + assert(t, index < singletonCount(t, singleton)); + + return (singletonMask(t, singleton)[(index + 2) / 32] + & (static_cast(1) << ((index + 2) % 32))) != 0; +} + +inline object +singletonObject(Thread* t, object singleton, unsigned index) +{ + assert(t, singletonIsObject(t, singleton, index)); + return reinterpret_cast(singletonBody(t, singleton, index)); +} + +inline uintptr_t& +singletonValue(Thread* t, object singleton, unsigned index) +{ + assert(t, not singletonIsObject(t, singleton, index)); + return singletonBody(t, singleton, index); +} + +inline object +makeSingleton(Thread* t, unsigned count) +{ + object o = makeSingleton(t, count + singletonMaskSize(count), true); + if (count) { + singletonMask(t, o)[0] = 1; + } + return o; +} + } // namespace vm #endif//MACHINE_H diff --git a/src/process.h b/src/process.h index 3f0c96355a..c43445dff6 100644 --- a/src/process.h +++ b/src/process.h @@ -45,7 +45,7 @@ resolveClassInObject(Thread* t, object container, unsigned classOffset) inline object resolveClassInPool(Thread* t, object pool, unsigned index) { - object o = arrayBody(t, pool, index); + object o = singletonObject(t, pool, index); if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) { PROTECT(t, pool); @@ -53,7 +53,7 @@ resolveClassInPool(Thread* t, object pool, unsigned index) o = resolveClass(t, o); if (UNLIKELY(t->exception)) return 0; - set(t, pool, ArrayBody + (index * BytesPerWord), o); + set(t, pool, SingletonBody + (index * BytesPerWord), o); } return o; } @@ -63,7 +63,7 @@ resolve(Thread* t, object pool, unsigned index, object (*find)(vm::Thread*, object, object, object), object (*makeError)(vm::Thread*, object)) { - object o = arrayBody(t, pool, index); + object o = singletonObject(t, pool, index); if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) { PROTECT(t, pool); @@ -79,7 +79,7 @@ resolve(Thread* t, object pool, unsigned index, find, makeError); if (UNLIKELY(t->exception)) return 0; - set(t, pool, ArrayBody + (index * BytesPerWord), o); + set(t, pool, SingletonBody + (index * BytesPerWord), o); } return o; diff --git a/src/processor.h b/src/processor.h index 82db1b9e04..1274a00a93 100644 --- a/src/processor.h +++ b/src/processor.h @@ -15,10 +15,35 @@ class Processor { makeThread(Machine* m, object javaThread, Thread* parent) = 0; virtual object - methodStub(Thread* t) = 0; + makeMethod(Thread* t, + uint8_t vmFlags, + uint8_t returnCode, + uint8_t parameterCount, + uint8_t parameterFootprint, + uint16_t flags, + uint16_t offset, + object name, + object spec, + object class_, + object code) = 0; virtual object - nativeInvoker(Thread* t) = 0; + makeClass(Thread* t, + uint16_t flags, + uint8_t vmFlags, + uint8_t arrayDimensions, + uint16_t fixedSize, + uint16_t arrayElementSize, + object objectMask, + object name, + object super, + object interfaceTable, + object virtualTable, + object fieldTable, + object methodTable, + object staticTable, + object loader, + unsigned vtableLength) = 0; virtual unsigned parameterFootprint(Thread* t, const char* spec, bool static_) = 0; diff --git a/src/stream.h b/src/stream.h index 29e1beedb7..96c23fb594 100644 --- a/src/stream.h +++ b/src/stream.h @@ -10,27 +10,35 @@ class Stream { class Client { public: virtual ~Client() { } - virtual void NO_RETURN handleEOS() = 0; + virtual void NO_RETURN handleError() = 0; }; Stream(Client* client, const uint8_t* data, unsigned size): - client(client), data(data), size(size), position(0) + client(client), data(data), size(size), position_(0) { } + unsigned position() { + return position_; + } + + void setPosition(unsigned p) { + position_ = p; + } + void skip(unsigned size) { - if (size > this->size - position) { - client->handleEOS(); + if (size > this->size - position_) { + client->handleError(); } else { - position += size; + position_ += size; } } void read(uint8_t* data, unsigned size) { - if (size > this->size - position) { - client->handleEOS(); + if (size > this->size - position_) { + client->handleError(); } else { - memcpy(data, this->data + position, size); - position += size; + memcpy(data, this->data + position_, size); + position_ += size; } } @@ -70,7 +78,7 @@ class Stream { Client* client; const uint8_t* data; unsigned size; - unsigned position; + unsigned position_; }; } // namespace vm diff --git a/src/type-generator.cpp b/src/type-generator.cpp index bae321a994..949af6678b 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1351,6 +1351,12 @@ parseJavaClass(Object* type, Stream* s, Object* declarations) } } + if (equal(typeJavaName(type), "java/lang/Class")) { + // add inline vtable + addMember(type, Array::make + (type, 0, "void*", "vtable", sizeOf("void*", 0))); + } + if (typeSuper(type)) { for (Object* p = typeMethods(typeSuper(type)); p; p = cdr(p)) { addMethod(type, car(p)); @@ -2114,6 +2120,9 @@ writeInitialization(Output* out, Object* type) out->write(", "); out->write(typeArrayElementSize(type)); + out->write(", "); + + out->write(methodCount(type)); out->write(");\n"); }