avoid inifinite recursion if java.lang.Object is missing; refactoring

When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc..  This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.

While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.

Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
This commit is contained in:
Joel Dice 2010-12-09 19:38:12 -07:00
parent cda1ae81c8
commit 3d49173b0b
11 changed files with 219 additions and 332 deletions

View File

@ -239,12 +239,12 @@ public class Thread implements Runnable {
}
public synchronized void setDaemon(boolean v) {
if (v != daemon) {
setDaemon(this, v);
if (getState() != State.NEW) {
throw new IllegalStateException();
}
}
private static native void setDaemon(Thread t, boolean increment);
daemon = v;
}
public static native void yield();

View File

@ -40,8 +40,7 @@ search(Thread* t, object loader, object name,
return reinterpret_cast<int64_t>(r);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
return 0;
}
}
@ -93,8 +92,7 @@ Avian_avian_SystemClassLoader_resourceExists
return r;
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
return 0;
}
}
@ -126,8 +124,7 @@ Avian_avian_Machine_dumpHeap
fclose(out);
} else {
object message = makeString(t, "file not found: %s", n);
t->exception = t->m->classpath->makeThrowable
(t, Machine::RuntimeExceptionType, message);
t->exception = makeThrowable(t, Machine::RuntimeExceptionType, message);
}
}
@ -183,8 +180,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open
return reinterpret_cast<int64_t>(r);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
return 0;
}
}

View File

@ -65,27 +65,6 @@ class MyClasspath : public Classpath {
}
}
virtual object
makeThrowable
(Thread* t, Machine::Type type, object message, object trace, object cause)
{
PROTECT(t, message);
PROTECT(t, trace);
PROTECT(t, cause);
if (trace == 0) {
trace = makeTrace(t);
}
object result = make(t, vm::type(t, type));
set(t, result, ThrowableMessage, message);
set(t, result, ThrowableTrace, trace);
set(t, result, ThrowableCause, cause);
return result;
}
virtual void
boot(Thread*)
{
@ -330,7 +309,7 @@ Avian_java_lang_reflect_Method_invoke
object v = t->m->processor->invokeArray(t, method, instance, args);
if (t->exception) {
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::InvocationTargetExceptionType, 0, 0, t->exception);
}
return reinterpret_cast<int64_t>(v);
@ -348,12 +327,10 @@ Avian_java_lang_reflect_Array_getLength
if (LIKELY(elementSize)) {
return cast<uintptr_t>(array, BytesPerWord);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalArgumentExceptionType);
t->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType);
}
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
}
return 0;
}
@ -462,8 +439,7 @@ Avian_java_lang_System_identityHashCode
if (LIKELY(o)) {
return objectHash(t, o);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
return 0;
}
}
@ -604,16 +580,6 @@ Avian_java_lang_Thread_enumerate
return count;
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Thread_setDaemon
(Thread* t, object, uintptr_t* arguments)
{
object thread = reinterpret_cast<object>(arguments[0]);
bool daemon = arguments[1] != 0;
setDaemon(t, thread, daemon);
}
extern "C" JNIEXPORT void JNICALL
Avian_avian_Classes_acquireClassLock
(Thread* t, object, uintptr_t*)
@ -682,8 +648,7 @@ Avian_avian_Classes_isAssignableFrom
if (LIKELY(that)) {
return vm::isAssignableFrom(t, this_, that);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
return 0;
}
}

View File

@ -101,7 +101,7 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
return;
} else {
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::IndexOutOfBoundsExceptionType);
return;
}
@ -111,13 +111,11 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
}
}
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
return;
}
t->exception = t->m->classpath->makeThrowable
(t, Machine::ArrayStoreExceptionType);
t->exception = makeThrowable(t, Machine::ArrayStoreExceptionType);
}
void
@ -223,7 +221,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
}
} else {
object message = makeString(t, "library not found: %s", name);
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::UnsatisfiedLinkErrorType, message);
}

View File

@ -330,27 +330,6 @@ class MyClasspath : public Classpath {
release(t, t->javaThread);
}
virtual object
makeThrowable
(Thread* t, Machine::Type type, object message, object trace, object cause)
{
PROTECT(t, message);
PROTECT(t, trace);
PROTECT(t, cause);
if (trace == 0) {
trace = makeTrace(t);
}
object result = make(t, vm::type(t, type));
set(t, result, ThrowableMessage, message);
set(t, result, ThrowableTrace, trace);
set(t, result, ThrowableCause, cause);
return result;
}
virtual void
boot(Thread* t)
{
@ -709,22 +688,19 @@ openFile(Thread* t, object method, uintptr_t* arguments)
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
if (ef.jar) {
if (ef.jarLength == 0 or ef.pathLength == 0) {
t->exception = t->m->classpath->makeThrowable
(t, Machine::FileNotFoundExceptionType);
t->exception = makeThrowable(t, Machine::FileNotFoundExceptionType);
return;
}
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
if (finder == 0) {
t->exception = t->m->classpath->makeThrowable
(t, Machine::FileNotFoundExceptionType);
t->exception = makeThrowable(t, Machine::FileNotFoundExceptionType);
return;
}
System::Region* r = finder->find(ef.path);
if (r == 0) {
t->exception = t->m->classpath->makeThrowable
(t, Machine::FileNotFoundExceptionType);
t->exception = makeThrowable(t, Machine::FileNotFoundExceptionType);
return;
}
@ -792,8 +768,7 @@ readByteFromFile(Thread* t, object method, uintptr_t* arguments)
return -1;
}
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IoExceptionType);
t->exception = makeThrowable(t, Machine::IoExceptionType);
return 0;
}
} else {
@ -847,8 +822,7 @@ readBytesFromFile(Thread* t, object method, uintptr_t* arguments)
return length;
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IoExceptionType);
t->exception = makeThrowable(t, Machine::IoExceptionType);
return 0;
}
} else {
@ -892,8 +866,7 @@ skipBytesInFile(Thread* t, object method, uintptr_t* arguments)
return count;
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IoExceptionType);
t->exception = makeThrowable(t, Machine::IoExceptionType);
return 0;
}
} else {
@ -927,8 +900,7 @@ availableBytesInFile(Thread* t, object method, uintptr_t* arguments)
return static_cast<System::Region*>(regionRegion(t, region))->length()
- regionPosition(t, region);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IoExceptionType);
t->exception = makeThrowable(t, Machine::IoExceptionType);
return 0;
}
} else {
@ -1735,8 +1707,7 @@ Avian_sun_misc_Unsafe_allocateMemory
if (p) {
return reinterpret_cast<int64_t>(p);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::OutOfMemoryErrorType);
t->exception = makeThrowable(t, Machine::OutOfMemoryErrorType);
return 0;
}
}
@ -2474,8 +2445,7 @@ EXPORT(JVM_FindPrimitiveClass)(Thread* t, const char* name)
return makeLocalReference
(t, getJClass(t, type(t, Machine::JvoidType)));
default:
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalArgumentExceptionType);
t->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType);
return 0;
}
}
@ -2494,7 +2464,7 @@ EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name,
(t, loader ? *loader : root(t, Machine::BootLoader), name);
if (t->exception) {
if (throwError) {
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::NoClassDefFoundErrorType,
throwableMessage(t, t->exception),
throwableTrace(t, t->exception),

View File

@ -2150,8 +2150,7 @@ findInterfaceMethodFromInstance(MyThread* t, object method, object instance)
return methodAddress(t, target);
}
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
unwind(t);
}
}
@ -2422,7 +2421,7 @@ makeBlankObjectArray(MyThread* t, object class_, int32_t length)
return reinterpret_cast<uint64_t>(makeObjectArray(t, class_, length));
} else {
object message = makeString(t, "%d", length);
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
unwind(t);
}
@ -2472,7 +2471,7 @@ makeBlankArray(MyThread* t, unsigned type, int32_t length)
return reinterpret_cast<uintptr_t>(constructor(t, length));
} else {
object message = makeString(t, "%d", length);
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
unwind(t);
}
@ -2507,8 +2506,7 @@ setMaybeNull(MyThread* t, object o, unsigned offset, object value)
if (LIKELY(o)) {
set(t, o, offset, value);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
unwind(t);
}
}
@ -2519,8 +2517,7 @@ acquireMonitorForObject(MyThread* t, object o)
if (LIKELY(o)) {
acquire(t, o);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
unwind(t);
}
}
@ -2531,8 +2528,7 @@ releaseMonitorForObject(MyThread* t, object o)
if (LIKELY(o)) {
release(t, o);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
unwind(t);
}
}
@ -2548,7 +2544,7 @@ makeMultidimensionalArray2(MyThread* t, object class_, uintptr_t* countStack,
RUNTIME_ARRAY_BODY(counts)[i] = countStack[dimensions - i - 1];
if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) {
object message = makeString(t, "%d", RUNTIME_ARRAY_BODY(counts)[i]);
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
return 0;
}
@ -2603,7 +2599,7 @@ throwArrayIndexOutOfBounds(MyThread* t)
{
if (ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t))) {
atomicOr(&(t->flags), Thread::TracingFlag);
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType);
atomicAnd(&(t->flags), ~Thread::TracingFlag);
} else {
@ -2621,8 +2617,7 @@ throw_(MyThread* t, object o)
if (LIKELY(o)) {
t->exception = o;
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
}
// printTrace(t, t->exception);
@ -2638,8 +2633,7 @@ checkCast(MyThread* t, object class_, object o)
(t, "%s as %s",
&byteArrayBody(t, className(t, objectClass(t, o)), 0),
&byteArrayBody(t, className(t, class_), 0));
t->exception = t->m->classpath->makeThrowable
(t, Machine::ClassCastExceptionType, message);
t->exception = makeThrowable(t, Machine::ClassCastExceptionType, message);
unwind(t);
}
}
@ -6837,7 +6831,7 @@ callContinuation(MyThread* t, object continuation, object result,
action = Call;
}
} else {
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::IncompatibleContinuationExceptionType);
action = Throw;
}
@ -7175,8 +7169,7 @@ class SegFaultHandler: public System::SignalHandler {
if (ensure(t, FixedSizeOfNullPointerException + traceSize(t))) {
atomicOr(&(t->flags), Thread::TracingFlag);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
atomicAnd(&(t->flags), ~Thread::TracingFlag);
} else {
// not enough memory available for a new NPE and stack trace

View File

@ -438,8 +438,7 @@ checkStack(Thread* t, object method)
+ codeMaxStack(t, methodCode(t, method))
> Thread::StackSizeInWords / 2))
{
t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
t->exception = makeThrowable(t, Machine::StackOverflowErrorType);
}
}
@ -864,13 +863,12 @@ interpret(Thread* t)
} else {
object message = makeString
(t, "%d not in [0,%d)", index, objectArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -888,13 +886,12 @@ interpret(Thread* t)
} else {
object message = makeString
(t, "%d not in [0,%d)", index, objectArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -935,7 +932,7 @@ interpret(Thread* t)
pushObject(t, makeObjectArray(t, class_, count));
} else {
object message = makeString(t, "%d", count);
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
goto throw_;
}
@ -957,8 +954,7 @@ interpret(Thread* t)
if (LIKELY(array)) {
pushInt(t, cast<uintptr_t>(array, BytesPerWord));
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -986,8 +982,7 @@ interpret(Thread* t)
case athrow: {
exception = popObject(t);
if (UNLIKELY(exception == 0)) {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
}
} goto throw_;
@ -1005,7 +1000,7 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
booleanArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
@ -1019,14 +1014,13 @@ interpret(Thread* t)
object message = makeString(t, "%d not in [0,%d)", index,
byteArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1046,7 +1040,7 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
booleanArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
@ -1058,14 +1052,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
byteArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1086,13 +1079,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
charArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1110,13 +1102,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
charArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1134,7 +1125,7 @@ interpret(Thread* t)
&byteArrayBody
(t, className(t, objectClass(t, peekObject(t, sp - 1))), 0),
&byteArrayBody(t, className(t, class_), 0));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ClassCastExceptionType, message);
goto throw_;
}
@ -1172,13 +1163,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
doubleArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1196,13 +1186,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
doubleArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1376,13 +1365,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
floatArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1400,13 +1388,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
floatArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1518,8 +1505,7 @@ interpret(Thread* t)
}
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1611,13 +1597,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
intArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1642,13 +1627,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
intArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1915,8 +1899,7 @@ interpret(Thread* t)
(t, method, objectClass(t, peekObject(t, sp - parameterFootprint)));
goto invoke;
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1941,8 +1924,7 @@ interpret(Thread* t)
goto invoke;
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1973,8 +1955,7 @@ interpret(Thread* t)
code = findVirtualMethod(t, method, class_);
goto invoke;
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2110,13 +2091,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
longArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2141,13 +2121,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
longArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2373,8 +2352,7 @@ interpret(Thread* t)
if (LIKELY(o)) {
acquire(t, o);
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2384,8 +2362,7 @@ interpret(Thread* t)
if (LIKELY(o)) {
release(t, o);
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2403,7 +2380,7 @@ interpret(Thread* t)
counts[i] = popInt(t);
if (UNLIKELY(counts[i] < 0)) {
object message = makeString(t, "%d", counts[i]);
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
goto throw_;
}
@ -2477,7 +2454,7 @@ interpret(Thread* t)
pushObject(t, array);
} else {
object message = makeString(t, "%d", count);
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
goto throw_;
}
@ -2540,8 +2517,7 @@ interpret(Thread* t)
break;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
}
} break;
@ -2552,8 +2528,7 @@ interpret(Thread* t)
if (LIKELY(o)) {
cast<int64_t>(o, fieldOffset(t, field)) = value;
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
}
} break;
@ -2563,8 +2538,7 @@ interpret(Thread* t)
if (LIKELY(o)) {
set(t, o, fieldOffset(t, field), value);
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
}
} break;
@ -2694,13 +2668,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
shortArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2718,13 +2691,12 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
shortArrayLength(t, array));
exception = t->m->classpath->makeThrowable
exception = makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -3166,8 +3138,7 @@ class MyProcessor: public Processor {
if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1
> Thread::StackSizeInWords / 2))
{
t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
t->exception = makeThrowable(t, Machine::StackOverflowErrorType);
return 0;
}
@ -3192,8 +3163,7 @@ class MyProcessor: public Processor {
if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1
> Thread::StackSizeInWords / 2))
{
t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
t->exception = makeThrowable(t, Machine::StackOverflowErrorType);
return 0;
}
@ -3217,8 +3187,7 @@ class MyProcessor: public Processor {
if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false)
> Thread::StackSizeInWords / 2))
{
t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
t->exception = makeThrowable(t, Machine::StackOverflowErrorType);
return 0;
}

View File

@ -31,26 +31,17 @@ AttachCurrentThread(Machine* m, Thread** t, void*)
{
*t = static_cast<Thread*>(m->localThread->get());
if (*t == 0) {
*t = m->processor->makeThread(m, 0, m->rootThread);
m->system->attach(&((*t)->runnable));
enter(*t, Thread::ActiveState);
enter(*t, Thread::IdleState);
m->localThread->set(*t);
*t = attachThread(m, false);
}
return 0;
}
jint JNICALL
AttachCurrentThreadAsDaemon(Machine* m, Thread** t, void* parameters)
AttachCurrentThreadAsDaemon(Machine* m, Thread** t, void*)
{
*t = static_cast<Thread*>(m->localThread->get());
if (*t == 0) {
AttachCurrentThread(m, t, parameters);
ENTER(*t, Thread::ActiveState);
setDaemon(*t, (*t)->javaThread, true);
*t = attachThread(m, true);
}
return 0;
}
@ -2040,13 +2031,12 @@ boot(Thread* t)
enter(t, Thread::ActiveState);
if (t->exception == 0) {
setRoot(t, Machine::NullPointerException, t->m->classpath->makeThrowable
setRoot(t, Machine::NullPointerException, makeThrowable
(t, Machine::NullPointerExceptionType));
if (t->exception == 0) {
setRoot(t, Machine::ArrayIndexOutOfBoundsException,
t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType));
makeThrowable(t, Machine::ArrayIndexOutOfBoundsExceptionType));
}
}

View File

@ -1731,11 +1731,13 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
PROTECT(t, spec);
PROTECT(t, elementClass);
// Load java.lang.Object if present so we can use its vtable, but
// don't throw an exception if we can't find it. This way, we
// avoid infinite recursion due to trying to create an array to
// make a stack trace for a ClassNotFoundException.
resolveSystemClass
(t, root(t, Machine::BootLoader),
className(t, type(t, Machine::JobjectType)));
if (UNLIKELY(t->exception)) return 0;
className(t, type(t, Machine::JobjectType)), false);
}
object vtable = classVirtualTable(t, type(t, Machine::JobjectType));
@ -2324,18 +2326,16 @@ Thread::init()
setRoot(this, Machine::JNIMethodTable, makeVector(this, 0, 0));
m->localThread->set(this);
javaThread = m->classpath->makeThread(this, 0);
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
} else {
peer = parent->child;
parent->child = this;
}
expect(this, m->system->success(m->system->make(&lock)));
if (javaThread == 0) {
this->javaThread = m->classpath->makeThread(this, parent);
}
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
}
void
@ -2494,36 +2494,6 @@ enter(Thread* t, Thread::State s)
} break;
case Thread::IdleState:
// The java.lang.Thread implementation may or may not notify the
// VM when the daemon field in the Java object changes, so we sync
// up the native field whenever the thread transitions to idle:
// todo: this won't always help if some other thread sets the
// daemon field. The thread trying to shut down the VM really
// just needs to count from scratch every time any thread makes a
// transition (i.e. eliminate Machine::daemonCount).
if (UNLIKELY(((t->flags & Thread::DaemonFlag) != 0)
!= threadDaemon(t, t->javaThread)))
{
ACQUIRE_LOCK;
if (threadDaemon(t, t->javaThread)) {
atomicOr(&(t->flags), Thread::DaemonFlag);
} else {
atomicAnd(&(t->flags), ~Thread::DaemonFlag);
}
if (t->flags & Thread::DaemonFlag) {
++ t->m->daemonCount;
} else {
expect(t, t->m->daemonCount);
-- t->m->daemonCount;
}
t->m->stateLock->notifyAll(t->systemThread);
}
if (LIKELY(t->state == Thread::ActiveState)) {
// fast path
assert(t, t->m->activeCount > 0);
@ -2563,7 +2533,7 @@ enter(Thread* t, Thread::State s)
assert(t, t->m->liveCount > 0);
-- t->m->liveCount;
if (threadDaemon(t, t->javaThread)) {
if (t->flags & Thread::DaemonFlag) {
-- t->m->daemonCount;
}
}
@ -3239,7 +3209,7 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
hashMapInsert(t, classLoaderMap(t, loader), spec, class_, byteArrayHash);
} else if (throw_ and t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::ClassNotFoundExceptionType, message);
}
}
@ -3334,7 +3304,7 @@ resolveClass(Thread* t, object loader, object spec, bool throw_)
} else {
if (t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::ClassNotFoundExceptionType, message);
}
@ -3361,8 +3331,7 @@ resolveMethod(Thread* t, object class_, const char* methodName,
(t, "%s %s not found in %s", methodName, methodSpec,
&byteArrayBody(t, className(t, class_), 0));
t->exception = t->m->classpath->makeThrowable
(t, Machine::NoSuchMethodErrorType, message);
t->exception = makeThrowable(t, Machine::NoSuchMethodErrorType, message);
return 0;
} else {
return method;
@ -3395,8 +3364,7 @@ resolveField(Thread* t, object class_, const char* fieldName,
(t, "%s %s not found in %s", fieldName, fieldSpec,
&byteArrayBody(t, className(t, class_), 0));
t->exception = t->m->classpath->makeThrowable
(t, Machine::NoSuchFieldErrorType, message);
t->exception = makeThrowable(t, Machine::NoSuchFieldErrorType, message);
return 0;
} else {
return field;
@ -3449,7 +3417,7 @@ preInitClass(Thread* t, object c)
object message = makeString
(t, "%s", &byteArrayBody(t, className(t, c), 0));
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::NoClassDefFoundErrorType, message);
} else {
classVmFlags(t, c) |= InitFlag;
@ -3467,7 +3435,7 @@ postInitClass(Thread* t, object c)
ACQUIRE(t, t->m->classLock);
if (t->exception) {
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::ExceptionInInitializerErrorType, 0, 0, t->exception);
classVmFlags(t, c) |= NeedInitFlag | InitErrorFlag;
@ -3527,6 +3495,7 @@ resolveObjectArrayClass(Thread* t, object loader, object elementClass)
}
object arrayClass = resolveClass(t, loader, spec);
if (UNLIKELY(t->exception)) return 0;
set(t, getClassRuntimeData(t, elementClass), ClassRuntimeDataArrayClass,
arrayClass);
@ -3539,6 +3508,8 @@ makeObjectArray(Thread* t, object elementClass, unsigned count)
{
object arrayClass = resolveObjectArrayClass
(t, classLoader(t, elementClass), elementClass);
if (UNLIKELY(t->exception)) return 0;
PROTECT(t, arrayClass);
object array = makeArray(t, count);
@ -3760,13 +3731,12 @@ collect(Thread* t, Heap::CollectionType type)
}
if (root(t, Machine::ObjectsToFinalize) and m->finalizeThread == 0) {
m->finalizeThread = m->processor->makeThread
(m, t->m->classpath->makeThread(t, m->rootThread), m->rootThread);
object javaThread = t->m->classpath->makeThread(t, m->rootThread);
threadDaemon(t, javaThread) = true;
if (not t->m->system->success
(m->system->start(&(m->finalizeThread->runnable))))
{
m->finalizeThread->exit();
m->finalizeThread = m->processor->makeThread(m, javaThread, m->rootThread);
if (not startThread(t, m->finalizeThread)) {
m->finalizeThread = 0;
}
}
@ -3849,8 +3819,7 @@ void
printTrace(Thread* t, object exception)
{
if (exception == 0) {
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
exception = makeThrowable(t, Machine::NullPointerExceptionType);
}
for (object e = exception; e; e = throwableCause(t, e)) {
@ -3956,8 +3925,6 @@ makeTrace(Thread* t, Thread* target)
void
runFinalizeThread(Thread* t)
{
setDaemon(t, t->javaThread, true);
object list = 0;
PROTECT(t, list);

View File

@ -1282,6 +1282,9 @@ runJavaThread(Thread* t);
void
runFinalizeThread(Thread* t);
void
checkDaemon(Thread* t);
class Thread {
public:
enum State {
@ -1361,6 +1364,8 @@ class Thread {
t->m->localThread->set(t);
checkDaemon(t);
if (t == t->m->finalizeThread) {
runFinalizeThread(t);
} else if (t->javaThread) {
@ -1429,11 +1434,6 @@ class Classpath {
virtual void
runThread(Thread* t) = 0;
virtual object
makeThrowable
(Thread* t, Machine::Type type, object message = 0, object trace = 0,
object cause = 0) = 0;
virtual void
boot(Thread* t) = 0;
@ -1709,19 +1709,6 @@ setObjectClass(Thread*, object o, object value)
| (reinterpret_cast<uintptr_t>(cast<object>(o, 0)) & (~PointerMask)));
}
inline Thread*
startThread(Thread* t, object javaThread)
{
Thread* p = t->m->processor->makeThread(t->m, javaThread, t);
if (t->m->system->success(t->m->system->start(&(p->runnable)))) {
return p;
} else {
p->exit();
return 0;
}
}
inline const char*
findProperty(Machine* m, const char* name)
{
@ -1759,6 +1746,69 @@ runJavaThread(Thread* t)
t->m->classpath->runThread(t);
}
inline bool
startThread(Thread* t, Thread* p)
{
return t->m->system->success(t->m->system->start(&(p->runnable)));
}
inline Thread*
startThread(Thread* t, object javaThread)
{
Thread* p = t->m->processor->makeThread(t->m, javaThread, t);
if (startThread(t, p)) {
return p;
} else {
return 0;
}
}
inline void
registerDaemon(Thread* t)
{
ACQUIRE_RAW(t, t->m->stateLock);
atomicOr(&(t->flags), Thread::DaemonFlag);
++ t->m->daemonCount;
t->m->stateLock->notifyAll(t->systemThread);
}
inline void
checkDaemon(Thread* t)
{
if (threadDaemon(t, t->javaThread)) {
registerDaemon(t);
}
}
inline Thread*
attachThread(Machine* m, bool daemon)
{
Thread* t = m->processor->makeThread(m, 0, m->rootThread);
m->system->attach(&(t->runnable));
enter(t, Thread::ActiveState);
t->javaThread = m->classpath->makeThread(t, m->rootThread);
threadPeer(t, t->javaThread) = reinterpret_cast<jlong>(t);
if (daemon) {
threadDaemon(t, t->javaThread) = true;
registerDaemon(t);
}
enter(t, Thread::IdleState);
m->localThread->set(t);
return t;
}
inline object&
root(Thread* t, Machine::Root root)
{
@ -2237,6 +2287,28 @@ findMethodInClass(Thread* t, object class_, object name, object spec)
(t, classMethodTable(t, class_), name, spec, methodName, methodSpec);
}
inline object
makeThrowable
(Thread* t, Machine::Type type, object message = 0, object trace = 0,
object cause = 0)
{
PROTECT(t, message);
PROTECT(t, trace);
PROTECT(t, cause);
if (trace == 0) {
trace = makeTrace(t);
}
object result = make(t, vm::type(t, type));
set(t, result, ThrowableMessage, message);
set(t, result, ThrowableTrace, trace);
set(t, result, ThrowableCause, cause);
return result;
}
object
findInHierarchyOrNull(Thread* t, object class_, object name, object spec,
object (*find)(Thread*, object, object, object));
@ -2254,7 +2326,7 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
&byteArrayBody(t, name, 0),
&byteArrayBody(t, spec, 0),
&byteArrayBody(t, className(t, class_), 0));
t->exception = t->m->classpath->makeThrowable(t, errorType, message);
t->exception = makeThrowable(t, errorType, message);
}
return o;
@ -2707,12 +2779,10 @@ wait(Thread* t, object o, int64_t milliseconds)
bool interrupted = monitorWait(t, m, milliseconds);
if (interrupted) {
t->exception = t->m->classpath->makeThrowable
(t, Machine::InterruptedExceptionType);
t->exception = makeThrowable(t, Machine::InterruptedExceptionType);
}
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalMonitorStateExceptionType);
t->exception = makeThrowable(t, Machine::IllegalMonitorStateExceptionType);
}
if (DebugMonitors) {
@ -2741,8 +2811,7 @@ notify(Thread* t, object o)
if (m and monitorOwner(t, m) == t) {
monitorNotify(t, m);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalMonitorStateExceptionType);
t->exception = makeThrowable(t, Machine::IllegalMonitorStateExceptionType);
}
}
@ -2759,8 +2828,7 @@ notifyAll(Thread* t, object o)
if (m and monitorOwner(t, m) == t) {
monitorNotifyAll(t, m);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalMonitorStateExceptionType);
t->exception = makeThrowable(t, Machine::IllegalMonitorStateExceptionType);
}
}
@ -2803,34 +2871,6 @@ interrupt(Thread* t, Thread* target)
}
}
inline void
setDaemon(Thread* t, object thread, bool daemon)
{
ACQUIRE_RAW(t, t->m->stateLock);
if ((threadDaemon(t, thread) != 0) != daemon) {
threadDaemon(t, thread) = daemon;
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, thread));
if (p) {
if (daemon) {
atomicOr(&(p->flags), Thread::DaemonFlag);
} else {
atomicAnd(&(p->flags), ~Thread::DaemonFlag);
}
}
if (daemon) {
++ t->m->daemonCount;
} else {
expect(t, t->m->daemonCount);
-- t->m->daemonCount;
}
t->m->stateLock->notifyAll(t->systemThread);
}
}
object
intern(Thread* t, object s);
@ -3157,8 +3197,7 @@ primitiveClass(Thread* t, char name)
case 'V': return type(t, Machine::JvoidType);
case 'Z': return type(t, Machine::JbooleanType);
default:
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalArgumentExceptionType);
t->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType);
return 0;
}
}

View File

@ -243,7 +243,7 @@ resolveNative(Thread* t, object method)
&byteArrayBody(t, methodName(t, method), 0),
&byteArrayBody(t, methodSpec(t, method), 0));
t->exception = t->m->classpath->makeThrowable
t->exception = makeThrowable
(t, Machine::UnsatisfiedLinkErrorType, message);
return;
}