diff --git a/src/common.h b/src/common.h index 0148902304..ab28f2b7a4 100644 --- a/src/common.h +++ b/src/common.h @@ -7,7 +7,8 @@ #include "stdio.h" #define NO_RETURN __attribute__((noreturn)) -#define UNLIKELY(v) __builtin_expect(v, 0) +#define LIKELY(v) __builtin_expect((v) != 0, true) +#define UNLIKELY(v) __builtin_expect((v) == 0, true) #define MACRO_XY(X, Y) X##Y #define MACRO_MakeNameXY(FX, LINE) MACRO_XY(FX, LINE) diff --git a/src/types.def b/src/types.def index 40cb9bd6ac..8f6f962ff8 100644 --- a/src/types.def +++ b/src/types.def @@ -48,14 +48,50 @@ (object name) (object spec)) +(type trace + (object method) + (uint32_t ip) + (object next)) + (type string - (array char value)) + (object bytes) + (int32_t offset) + (int32_t length) + (int32_t hash)) + +(type throwable + (object message) + (object trace)) + +(type exception + (extends throwable)) + +(type runtimeException + (extends exception)) + +(type nullPointerException + (extends runtimeException)) + +(type arrayIndexOutOfBoundsException + (extends runtimeException)) + +(type negativeArrayStoreException + (extends runtimeException)) + +(type classCastException + (extends runtimeException)) + +(type error + (extends throwable)) + +(type StackOverflowError + (extends error)) (type byte (int8_t value)) (type boolean - (extends byte)) + (int8_t byte)) (type short (int16_t value)) @@ -86,7 +122,7 @@ (array int8_t body)) (type booleanArray - (extends byteArray)) + (array int8_t body)) (type shortArray (array int16_t body)) diff --git a/src/vm.cpp b/src/vm.cpp index 10e4b9550a..bfc8394e30 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -2,9 +2,8 @@ #include "system.h" #include "heap.h" -#define PROTECTED(thread, name, value) \ - Protector MAKE_NAME(protector_) (thread, value); \ - object& name(thread->stack[thread->sp - 1]); +#define PROTECT(thread, name) \ + Thread::Protector MAKE_NAME(protector_) (thread, &name); namespace { @@ -54,6 +53,21 @@ class Thread { ExitState }; + class Protector { + public: + Protector(Thread* t, object* p): t(t), p(p), next(t->protector) { + t->protector = this; + } + + ~Protector() { + t->protector = next; + } + + Thread* t; + object* p; + Protector* next; + }; + static const unsigned HeapSize = 64 * 1024; static const unsigned StackSize = 64 * 1024; @@ -68,6 +82,7 @@ class Thread { unsigned heapIndex; object stack[StackSize]; object heap[HeapSize]; + Protector* protector; }; inline void NO_RETURN @@ -121,6 +136,10 @@ iterate(Thread* t, Heap::Visitor* v) v->visit(t->stack + t->sp); } + for (Thread::Protector* p = t->protector; p; p = p->next) { + v->visit(p->p); + } + for (Thread* t = t->child; t; t = t->next) { iterate(t, v); } @@ -295,20 +314,11 @@ pop(Thread* t) return t->stack[--(t->sp)]; } -class Protector { - public: - Protector(Thread* t, object value): t(t) { - if (t->sp >= Thread::StackSize) abort(t); - push(t, value); - } - - ~Protector() { - pop(t); - } - - private: - Thread* t; -}; +inline object& +top(Thread* t) +{ + return t->stack[t->sp - 1]; +} inline object make(Thread* t, object class_) @@ -328,25 +338,75 @@ cast(object p, unsigned offset) return *reinterpret_cast(static_cast(p) + offset); } +void +my_vsnprintf(char* buffer, unsigned size, const char* format, va_list a) +{ + // todo +} + object -makeJString(Thread* t, const char* format, ...) +makeString(Thread* t, const char* format, ...) { static const unsigned Size = 256; char buffer[Size]; va_list a; va_start(a, format); - vsnprintf(buffer, Size - 1, format, a); + my_vsnprintf(buffer, Size - 1, format, a); va_end(a); - PROTECTED(t, s, makeString(t, strlen(buffer) + 1)); - memcpy(stringValue(t, s), buffer, stringLength(t, s)); + object s = makeByteArray(t, strlen(buffer) + 1); + memcpy(byteArrayBody(t, s), buffer, byteArrayLength(t, s)); - object r = make(t, t->vm->jstringClass); - cast(r, sizeof(void*)) = s; - cast(r, sizeof(void*) * 2) = 0; - cast(r, (sizeof(void*) * 2) + sizeof(int32_t)) = stringLength(t, s); - return r; + return makeString(t, s, 0, byteArrayLength(t, s), 0); +} + +object +makeTrace(Thread* t) +{ + object trace = 0; + PROTECT(t, trace); + for (; t->frame; t->frame = frameNext(t, t->frame)) { + trace = makeTrace + (t, frameMethod(t, t->frame), frameIp(t, t->frame), trace); + } + return trace; +} + +object +makeArrayIndexOutOfBoundsException(Thread* t, object message) +{ + PROTECT(t, message); + object trace = makeTrace(t); + return makeArrayIndexOutOfBoundsException(t, message, trace); +} + +object +makeNegativeArrayStoreException(Thread* t, object message) +{ + PROTECT(t, message); + object trace = makeTrace(t); + return makeNegativeArrayStoreException(t, message, trace); +} + +object +makeClassCastException(Thread* t, object message) +{ + PROTECT(t, message); + object trace = makeTrace(t); + return makeArrayIndexOutOfBoundsException(t, message, trace); +} + +object +makeNullPointerException(Thread* t) +{ + return makeNullPointerException(t, 0, makeTrace(t)); +} + +object +makeStackOverflowError(Thread* t) +{ + return makeStackOverflowError(t, 0, makeTrace(t)); } object @@ -361,18 +421,20 @@ run(Thread* t) object index = pop(t); object array = pop(t); - if (array) { + if (LIKELY(array)) { int32_t i = intValue(t, index); - if (i >= 0 and static_cast(i) < objectArrayLength(t, array)) { + if (LIKELY(i >= 0 and + static_cast(i) < objectArrayLength(t, array))) + { push(t, objectArrayBody(t, array)[i]); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - objectArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + objectArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -383,17 +445,19 @@ run(Thread* t) object array = pop(t); int32_t i = intValue(t, index); - if (array) { - if (i >= 0 and static_cast(i) < objectArrayLength(t, array)) { + if (LIKELY(array)) { + if (LIKELY(i >= 0 and + static_cast(i) < objectArrayLength(t, array))) + { set(t, objectArrayBody(t, array)[i], value); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - objectArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + objectArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -436,20 +500,20 @@ run(Thread* t) object count = pop(t); int32_t c = intValue(t, count); - if (c >= 0) { + if (LIKELY(c >= 0)) { uint8_t index1 = codeBody(t, t->code)[ip++]; uint8_t index2 = codeBody(t, t->code)[ip++]; uint16_t index = (index1 << 8) | index2; object class_ = resolveClass(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; object array = makeObjectArray(t, class_, c); memset(objectArrayBody(t, array), 0, c * 4); push(t, array); } else { - object message = makeJString(t, "%d", c); + object message = makeString(t, "%d", c); t->exception = makeNegativeArrayStoreException(t, message); goto throw_; } @@ -472,7 +536,7 @@ run(Thread* t) case arraylength: { object array = pop(t); - if (array) { + if (LIKELY(array)) { if (typeOf(array) == ObjectArrayType) { push(t, makeInt(t, objectArrayLength(t, array))); } else { @@ -480,7 +544,7 @@ run(Thread* t) push(t, makeInt(t, cast(array, sizeof(void*)))); } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } abort(t); @@ -522,8 +586,8 @@ run(Thread* t) case athrow: { t->exception = pop(t); - if (t->exception == 0) { - t->exception = makeNullPointerException(t, 0); + if (UNLIKELY(t->exception == 0)) { + t->exception = makeNullPointerException(t); } goto throw_; } abort(t); @@ -532,18 +596,20 @@ run(Thread* t) object index = pop(t); object array = pop(t); - if (array) { + if (LIKELY(array)) { int32_t i = intValue(t, index); - if (i >= 0 and static_cast(i) < byteArrayLength(t, array)) { + if (LIKELY(i >= 0 and + static_cast(i) < byteArrayLength(t, array))) + { push(t, makeByte(t, byteArrayBody(t, array)[i])); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - byteArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + byteArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -554,17 +620,19 @@ run(Thread* t) object array = pop(t); int32_t i = intValue(t, index); - if (array) { - if (i >= 0 and static_cast(i) < byteArrayLength(t, array)) { + if (LIKELY(array)) { + if (LIKELY(i >= 0 and + static_cast(i) < byteArrayLength(t, array))) + { byteArrayBody(t, array)[i] = intValue(t, value); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - byteArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + byteArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -577,18 +645,20 @@ run(Thread* t) object index = pop(t); object array = pop(t); - if (array) { + if (LIKELY(array)) { int32_t i = intValue(t, index); - if (i >= 0 and static_cast(i) < charArrayLength(t, array)) { + if (LIKELY(i >= 0 and + static_cast(i) < charArrayLength(t, array))) + { push(t, makeInt(t, charArrayBody(t, array)[i])); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - charArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + charArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -599,17 +669,19 @@ run(Thread* t) object array = pop(t); int32_t i = intValue(t, index); - if (array) { - if (i >= 0 and static_cast(i) < charArrayLength(t, array)) { + if (LIKELY(array)) { + if (LIKELY(i >= 0 and + static_cast(i) < charArrayLength(t, array))) + { charArrayBody(t, array)[i] = intValue(t, value); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - charArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + charArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -622,10 +694,14 @@ run(Thread* t) uint16_t index = (index1 << 8) | index2; object class_ = resolveClass(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; if (not instanceOf(t, class_, t->stack[t->sp - 1])) { - t->exception = makeClassCastException(t, 0); + object message = makeString + (t, "%S as %S", + className(t, objectClass(t->stack[t->sp - 1])), + className(t, class_)); + t->exception = makeClassCastException(t, message); goto throw_; } } @@ -723,17 +799,17 @@ run(Thread* t) case getfield: { object instance = pop(t); - if (instance) { + if (LIKELY(instance)) { uint8_t index1 = codeBody(t, t->code)[ip++]; uint8_t index2 = codeBody(t, t->code)[ip++]; uint16_t index = (index1 << 8) | index2; object field = resolveField(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; push(t, getField(instance, field)); } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -744,7 +820,7 @@ run(Thread* t) uint16_t index = (index1 << 8) | index2; object field = resolveField(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; if (not classInitialized(fieldClass(t, field))) { t->code = classInitializer(fieldClass(t, field)); @@ -808,18 +884,20 @@ run(Thread* t) object index = pop(t); object array = pop(t); - if (array) { + if (LIKELY(array)) { int32_t i = intValue(t, index); - if (i >= 0 and static_cast(i) < intArrayLength(t, array)) { + if (LIKELY(i >= 0 and + static_cast(i) < intArrayLength(t, array))) + { push(t, makeInt(t, intArrayBody(t, array)[i])); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - intArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + intArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -837,17 +915,19 @@ run(Thread* t) object array = pop(t); int32_t i = intValue(t, index); - if (array) { - if (i >= 0 and static_cast(i) < intArrayLength(t, array)) { + if (LIKELY(array)) { + if (LIKELY(i >= 0 and + static_cast(i) < intArrayLength(t, array))) + { intArrayBody(t, array)[i] = intValue(t, value); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - intArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + intArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -1096,7 +1176,7 @@ run(Thread* t) uint16_t index = (index1 << 8) | index2; object class_ = resolveClass(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; if (instanceOf(t, class_, t->stack[t->sp - 1])) { push(t, makeInt(t, 1)); @@ -1116,17 +1196,17 @@ run(Thread* t) ip += 2; object method = resolveMethod(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; parameterCount = methodParameterCount(method); - if (t->stack[t->sp - parameterCount]) { + if (LIKELY(t->stack[t->sp - parameterCount])) { t->code = findInterfaceMethod (t, method, t->stack[t->sp - parameterCount]); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; goto invoke; } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -1137,21 +1217,21 @@ run(Thread* t) uint16_t index = (index1 << 8) | index2; object method = resolveMethod(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; parameterCount = methodParameterCount(method); - if (t->stack[t->sp - parameterCount]) { + if (LIKELY(t->stack[t->sp - parameterCount])) { if (isSpecialMethod(method, t->stack[t->sp - parameterCount])) { t->code = findSpecialMethod (t, method, t->stack[t->sp - parameterCount]); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; } else { t->code = method; } goto invoke; } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -1162,7 +1242,7 @@ run(Thread* t) uint16_t index = (index1 << 8) | index2; object method = resolveMethod(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; if (not classInitialized(methodClass(t, method))) { t->code = classInitializer(methodClass(t, method)); @@ -1181,16 +1261,16 @@ run(Thread* t) uint16_t index = (index1 << 8) | index2; object method = resolveMethod(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; parameterCount = methodParameterCount(method); - if (t->stack[t->sp - parameterCount]) { + if (LIKELY(t->stack[t->sp - parameterCount])) { t->code = findVirtualMethod(t, method, t->stack[t->sp - parameterCount]); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; goto invoke; } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -1280,18 +1360,20 @@ run(Thread* t) object index = pop(t); object array = pop(t); - if (array) { + if (LIKELY(array)) { int32_t i = intValue(t, index); - if (i >= 0 and static_cast(i) < longArrayLength(t, array)) { + if (LIKELY(i >= 0 and + static_cast(i) < longArrayLength(t, array))) + { push(t, makeLong(t, longArrayBody(t, array)[i])); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - longArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + longArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -1309,17 +1391,19 @@ run(Thread* t) object array = pop(t); int32_t i = intValue(t, index); - if (array) { - if (i >= 0 and static_cast(i) < longArrayLength(t, array)) { + if (LIKELY(array)) { + if (LIKELY(i >= 0 and + static_cast(i) < longArrayLength(t, array))) + { longArrayBody(t, array)[i] = longValue(t, value); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - longArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + longArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -1428,7 +1512,7 @@ run(Thread* t) uint16_t index = (index1 << 8) | index2; object class_ = resolveClass(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; if (not classInitialized(class_)) { t->code = classInitializer(class_); @@ -1444,7 +1528,7 @@ run(Thread* t) object count = pop(t); int32_t c = intValue(t, count); - if (c >= 0) { + if (LIKELY(c >= 0)) { uint8_t type = codeBody(t, t->code)[ip++]; object array; @@ -1494,12 +1578,12 @@ run(Thread* t) default: abort(t); } - memset(static_cast(instance) + (sizeof(object) * 2), 0 + memset(static_cast(instance) + (sizeof(object) * 2), 0, c * factor); push(t, array); } else { - object message = makeJString(t, "%d", c); + object message = makeString(t, "%d", c); t->exception = makeNegativeArrayStoreException(t, message); goto throw_; } @@ -1522,18 +1606,18 @@ run(Thread* t) case putfield: { object instance = pop(t); - if (instance) { + if (LIKELY(instance)) { uint8_t index1 = codeBody(t, t->code)[ip++]; uint8_t index2 = codeBody(t, t->code)[ip++]; uint16_t index = (index1 << 8) | index2; object field = resolveField(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; object value = pop(t); setField(t, instance, field, value); } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -1544,7 +1628,7 @@ run(Thread* t) uint16_t index = (index1 << 8) | index2; object field = resolveField(t, codePool(t, t->code), index); - if (t->exception) goto throw_; + if (UNLIKELY(t->exception)) goto throw_; if (not classInitialized(fieldClass(t, field))) { t->code = classInitializer(fieldClass(t, field)); @@ -1577,18 +1661,20 @@ run(Thread* t) object index = pop(t); object array = pop(t); - if (array) { + if (LIKELY(array)) { int32_t i = intValue(t, index); - if (i >= 0 and static_cast(i) < shortArrayLength(t, array)) { + if (LIKELY(i >= 0 and + static_cast(i) < shortArrayLength(t, array))) + { push(t, makeShort(t, shortArrayBody(t, array)[i])); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - shortArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + shortArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -1599,17 +1685,19 @@ run(Thread* t) object array = pop(t); int32_t i = intValue(t, index); - if (array) { - if (i >= 0 and static_cast(i) < shortArrayLength(t, array)) { + if (LIKELY(array)) { + if (LIKELY(i >= 0 and + static_cast(i) < shortArrayLength(t, array))) + { shortArrayBody(t, array)[i] = intValue(t, value); } else { - object message = makeJString(t, "%d not in [0,%d]", i, - shortArrayLength(t, array)); + object message = makeString(t, "%d not in [0,%d]", i, + shortArrayLength(t, array)); t->exception = makeArrayIndexOutOfBoundsException(t, message); goto throw_; } } else { - t->exception = makeNullPointerException(t, 0); + t->exception = makeNullPointerException(t); goto throw_; } } goto loop; @@ -1677,10 +1765,10 @@ run(Thread* t) } invoke: - if (codeMaxStack(t, methodCode(t, t->code)) + t->sp - parameterCount - > Thread::StackSize) + if (UNLIKELY(codeMaxStack(t, methodCode(t, t->code)) + t->sp - parameterCount + > Thread::StackSize)) { - t->exception = makeStackOverflowException(t, 0); + t->exception = makeStackOverflowError(t); goto throw_; }