fix various bugs uncovered in GC stress test

This commit is contained in:
Joel Dice 2007-07-16 17:58:37 -06:00
parent 7dab93de00
commit 6dec1cbd42
5 changed files with 222 additions and 167 deletions

View File

@ -205,6 +205,7 @@ start(Thread* t, jobject this_)
} }
} }
} }
void void
populate(Thread* t, object map) populate(Thread* t, object map)
{ {
@ -212,28 +213,32 @@ populate(Thread* t, object map)
const char* key; const char* key;
void* value; void* value;
} builtins[] = { } builtins[] = {
{ "Java_java_lang_Object_toString", { "Java_java_lang_System_arraycopy",
reinterpret_cast<void*>(toString) }, reinterpret_cast<void*>(arraycopy) },
{ "Java_java_lang_System_loadLibrary",
reinterpret_cast<void*>(loadLibrary) },
{ "Java_java_lang_Thread_start",
reinterpret_cast<void*>(start) },
{ "Java_java_lang_Thread_sleep",
reinterpret_cast<void*>(sleep) },
{ "Java_java_lang_Throwable_resolveTrace",
reinterpret_cast<void*>(resolveTrace) },
{ "Java_java_lang_Throwable_trace",
reinterpret_cast<void*>(trace) },
{ "Java_java_lang_Object_getClass", { "Java_java_lang_Object_getClass",
reinterpret_cast<void*>(getClass) }, reinterpret_cast<void*>(getClass) },
{ "Java_java_lang_Object_wait",
reinterpret_cast<void*>(wait) },
{ "Java_java_lang_Object_notify", { "Java_java_lang_Object_notify",
reinterpret_cast<void*>(notify) }, reinterpret_cast<void*>(notify) },
{ "Java_java_lang_Object_notifyAll", { "Java_java_lang_Object_notifyAll",
reinterpret_cast<void*>(notifyAll) }, reinterpret_cast<void*>(notifyAll) },
{ "Java_java_lang_Thread_sleep", { "Java_java_lang_Object_toString",
reinterpret_cast<void*>(sleep) }, reinterpret_cast<void*>(toString) },
{ "Java_java_lang_System_loadLibrary", { "Java_java_lang_Object_wait",
reinterpret_cast<void*>(loadLibrary) }, reinterpret_cast<void*>(wait) },
{ "Java_java_lang_System_arraycopy",
reinterpret_cast<void*>(arraycopy) },
{ "Java_java_lang_Throwable_trace",
reinterpret_cast<void*>(trace) },
{ "Java_java_lang_Throwable_resolveTrace",
reinterpret_cast<void*>(resolveTrace) },
{ "Java_java_lang_Thread_start",
reinterpret_cast<void*>(start) },
{ 0, 0 } { 0, 0 }
}; };

View File

@ -271,6 +271,12 @@ postVisit(Thread* t, Heap::Visitor* v)
void void
postCollect(Thread* t) postCollect(Thread* t)
{ {
#ifdef VM_STRESS
t->vm->system->free(t->heap);
t->heap = static_cast<object*>
(t->vm->system->allocate(Thread::HeapSizeInBytes));
#endif
if (t->large) { if (t->large) {
t->vm->system->free(t->large); t->vm->system->free(t->large);
t->large = 0; t->large = 0;
@ -410,88 +416,6 @@ makeJNIName(Thread* t, object method, bool decorate)
return name; return name;
} }
unsigned
parameterFootprint(Thread* t, object spec)
{
unsigned footprint = 0;
const char* s = reinterpret_cast<const char*>(&byteArrayBody(t, spec, 0));
++ s; // skip '('
while (*s and *s != ')') {
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 'D':
++ s;
++ footprint;
break;
default:
++ s;
break;
}
++ footprint;
}
return footprint;
}
unsigned
parameterCount(Thread* t, object spec)
{
unsigned count = 0;
const char* s = reinterpret_cast<const char*>(&byteArrayBody(t, spec, 0));
++ s; // skip '('
while (*s and *s != ')') {
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;
default:
++ s;
break;
}
++ count;
}
return count;
}
object object
parsePool(Thread* t, Stream& s) parsePool(Thread* t, Stream& s)
{ {
@ -805,11 +729,10 @@ parseCode(Thread* t, Stream& s, object pool)
object code = makeCode(t, pool, 0, 0, maxStack, maxLocals, length, false); object code = makeCode(t, pool, 0, 0, maxStack, maxLocals, length, false);
s.read(&codeBody(t, code, 0), length); s.read(&codeBody(t, code, 0), length);
PROTECT(t, code);
unsigned ehtLength = s.read2(); unsigned ehtLength = s.read2();
if (ehtLength) { if (ehtLength) {
PROTECT(t, code);
object eht = makeExceptionHandlerTable(t, ehtLength, false); object eht = makeExceptionHandlerTable(t, ehtLength, false);
for (unsigned i = 0; i < ehtLength; ++i) { for (unsigned i = 0; i < ehtLength; ++i) {
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i); ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
@ -1012,6 +935,8 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
object vtable = makeArray(t, virtualCount, false); object vtable = makeArray(t, virtualCount, false);
if (classFlags(t, class_) & ACC_INTERFACE) { if (classFlags(t, class_) & ACC_INTERFACE) {
PROTECT(t, vtable);
object it = hashMapIterator(t, virtualMap); object it = hashMapIterator(t, virtualMap);
for (; it; it = hashMapIteratorNext(t, it)) { for (; it; it = hashMapIteratorNext(t, it)) {
@ -1144,12 +1069,16 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
ENTER(t, Thread::ExclusiveState); ENTER(t, Thread::ExclusiveState);
classVmFlags(t, class_) |= classVmFlags(t, bootstrapClass); classFlags(t, bootstrapClass) = classFlags(t, class_);
memcpy(bootstrapClass, set(t, classSuper(t, bootstrapClass), classSuper(t, class_));
class_, set(t, classInterfaceTable(t, bootstrapClass),
extendedSize(t, class_, baseSize(t, class_, objectClass(t, class_))) classInterfaceTable(t, class_));
* BytesPerWord); set(t, classVirtualTable(t, bootstrapClass), classVirtualTable(t, class_));
set(t, classFieldTable(t, bootstrapClass), classFieldTable(t, class_));
set(t, classMethodTable(t, bootstrapClass), classMethodTable(t, class_));
set(t, classStaticTable(t, bootstrapClass), classStaticTable(t, class_));
set(t, classInitializer(t, bootstrapClass), classInitializer(t, class_));
object fieldTable = classFieldTable(t, class_); object fieldTable = classFieldTable(t, class_);
if (fieldTable) { if (fieldTable) {
@ -1318,9 +1247,6 @@ Thread::Thread(Machine* m, Allocator* allocator, object javaThread,
peer((parent ? parent->child : 0)), peer((parent ? parent->child : 0)),
child(0), child(0),
state(NoState), state(NoState),
#ifdef VM_STRESS
stress(false),
#endif // VM_STRESS
systemThread(0), systemThread(0),
javaThread(javaThread), javaThread(javaThread),
code(0), code(0),
@ -1331,6 +1257,10 @@ Thread::Thread(Machine* m, Allocator* allocator, object javaThread,
frame(-1), frame(-1),
heapIndex(0), heapIndex(0),
protector(0) protector(0)
#ifdef VM_STRESS
, stress(false),
heap(static_cast<object*>(m->system->allocate(HeapSizeInBytes)))
#endif // VM_STRESS
{ {
if (parent == 0) { if (parent == 0) {
assert(this, m->rootThread == 0); assert(this, m->rootThread == 0);
@ -1605,6 +1535,86 @@ stringChars(Thread* t, object string, char* chars)
chars[stringLength(t, string)] = 0; chars[stringLength(t, string)] = 0;
} }
unsigned
parameterFootprint(const char* s)
{
unsigned footprint = 0;
++ s; // skip '('
while (*s and *s != ')') {
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 'D':
++ s;
++ footprint;
break;
default:
++ s;
break;
}
++ footprint;
}
return footprint;
}
unsigned
parameterCount(const char* s)
{
unsigned count = 0;
++ s; // skip '('
while (*s and *s != ')') {
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;
default:
++ s;
break;
}
++ count;
}
return count;
}
object object
hashMapFindNode(Thread* t, object map, object key, hashMapFindNode(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object), uint32_t (*hash)(Thread*, object),
@ -1919,8 +1929,6 @@ resolveClass(Thread* t, object spec)
(t, className(t, class_), 0)); (t, className(t, class_), 0));
} }
PROTECT(t, class_);
object bootstrapClass = hashMapFind object bootstrapClass = hashMapFind
(t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual); (t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
@ -1934,6 +1942,8 @@ resolveClass(Thread* t, object spec)
} }
if (class_) { if (class_) {
PROTECT(t, class_);
hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash); hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash);
} else if (t->exception == 0) { } else if (t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));

View File

@ -22,7 +22,7 @@
namespace vm { namespace vm {
const bool Verbose = false; const bool Verbose = false;
const bool DebugRun = false; const bool DebugRun = true;
const bool DebugStack = false; const bool DebugStack = false;
const bool DebugMonitors = false; const bool DebugMonitors = false;
@ -1172,9 +1172,6 @@ class Thread {
Thread* peer; Thread* peer;
Thread* child; Thread* child;
State state; State state;
#ifdef VM_STRESS
bool stress;
#endif // VM_STRESS
System::Thread* systemThread; System::Thread* systemThread;
object javaThread; object javaThread;
object code; object code;
@ -1185,8 +1182,13 @@ class Thread {
int frame; int frame;
unsigned heapIndex; unsigned heapIndex;
Protector* protector; Protector* protector;
uintptr_t stack[StackSizeInWords]; #ifdef VM_STRESS
bool stress;
object* heap;
#else // not VM_STRESS
object heap[HeapSizeInWords]; object heap[HeapSizeInWords];
#endif // not VM_STRESS
uintptr_t stack[StackSizeInWords];
}; };
inline object inline object
@ -1324,15 +1326,21 @@ allocate(Thread* t, unsigned sizeInBytes)
} }
inline void inline void
set(Thread* t, object& target, object value) mark(Thread* t, object& target)
{ {
target = value;
if (t->vm->heap->needsMark(&target)) { if (t->vm->heap->needsMark(&target)) {
ACQUIRE_RAW(t, t->vm->heapLock); ACQUIRE_RAW(t, t->vm->heapLock);
t->vm->heap->mark(&target); t->vm->heap->mark(&target);
} }
} }
inline void
set(Thread* t, object& target, object value)
{
target = value;
mark(t, target);
}
inline void inline void
setObjectClass(Thread* t, object o, object value) setObjectClass(Thread* t, object o, object value)
{ {
@ -1910,6 +1918,26 @@ objectArrayBody(Thread* t, object array, unsigned index)
return cast<object>(array, (2 + index) * BytesPerWord); return cast<object>(array, (2 + index) * BytesPerWord);
} }
unsigned
parameterFootprint(const char* s);
inline unsigned
parameterFootprint(Thread* t, object spec)
{
return parameterFootprint
(reinterpret_cast<const char*>(&byteArrayBody(t, spec, 0)));
}
unsigned
parameterCount(const char* s);
inline unsigned
parameterCount(Thread* t, object spec)
{
return parameterCount
(reinterpret_cast<const char*>(&byteArrayBody(t, spec, 0)));
}
int int
lineNumber(Thread* t, object method, unsigned ip); lineNumber(Thread* t, object method, unsigned ip);

View File

@ -2218,6 +2218,8 @@ run(Thread* t)
void void
run(Thread* t, const char* className, int argc, const char** argv) run(Thread* t, const char* className, int argc, const char** argv)
{ {
enter(t, Thread::ActiveState);
object args = makeObjectArray object args = makeObjectArray
(t, arrayBody(t, t->vm->types, Machine::StringType), argc, true); (t, arrayBody(t, t->vm->types, Machine::StringType), argc, true);
@ -2228,7 +2230,7 @@ run(Thread* t, const char* className, int argc, const char** argv)
set(t, objectArrayBody(t, args, i), arg); set(t, objectArrayBody(t, args, i), arg);
} }
run(t, className, "main", "([Ljava/lang/String;)V", args); run(t, className, "main", "([Ljava/lang/String;)V", 0, args);
} }
} // namespace } // namespace
@ -2237,29 +2239,25 @@ namespace vm {
object object
run(Thread* t, const char* className, const char* methodName, run(Thread* t, const char* className, const char* methodName,
const char* methodSpec, ...) const char* methodSpec, object this_, ...)
{ {
enter(t, Thread::ActiveState); assert(t, t->state == Thread::ActiveState
or t->state == Thread::ExclusiveState);
object class_ = resolveClass(t, makeByteArray(t, "%s", className)); if (UNLIKELY(t->sp + parameterFootprint(methodSpec) + 1
if (LIKELY(t->exception == 0)) { > Thread::StackSizeInWords / 2))
PROTECT(t, class_); {
t->exception = makeStackOverflowError(t);
object name = makeByteArray(t, methodName); return 0;
PROTECT(t, name);
object spec = makeByteArray(t, methodSpec);
object reference = makeReference(t, class_, name, spec);
object method = findMethodInClass(t, class_, reference);
if (LIKELY(t->exception == 0)) {
va_list a;
va_start(a, methodSpec);
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
pushObject(t, va_arg(a, object));
} }
if (this_) {
pushObject(t, this_);
}
va_list a;
va_start(a, this_);
const char* s = methodSpec; const char* s = methodSpec;
++ s; // skip '(' ++ s; // skip '('
while (*s and *s != ')') { while (*s and *s != ')') {
@ -2300,6 +2298,20 @@ run(Thread* t, const char* className, const char* methodName,
va_end(a); va_end(a);
object class_ = resolveClass(t, makeByteArray(t, "%s", className));
if (LIKELY(t->exception == 0)) {
PROTECT(t, class_);
object name = makeByteArray(t, methodName);
PROTECT(t, name);
object spec = makeByteArray(t, methodSpec);
object reference = makeReference(t, class_, name, spec);
object method = findMethodInClass(t, class_, reference);
if (LIKELY(t->exception == 0)) {
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
if (methodFlags(t, method) & ACC_NATIVE) { if (methodFlags(t, method) & ACC_NATIVE) {
unsigned returnCode = invokeNative(t, method); unsigned returnCode = invokeNative(t, method);

View File

@ -10,7 +10,7 @@ namespace vm {
object object
run(Thread* t, const char* className, const char* methodName, run(Thread* t, const char* className, const char* methodName,
const char* methodSpec, ...); const char* methodSpec, object this_, ...);
int int
run(System* sys, Heap* heap, ClassFinder* classFinder, run(System* sys, Heap* heap, ClassFinder* classFinder,