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
populate(Thread* t, object map)
{
@ -212,28 +213,32 @@ populate(Thread* t, object map)
const char* key;
void* value;
} builtins[] = {
{ "Java_java_lang_Object_toString",
reinterpret_cast<void*>(toString) },
{ "Java_java_lang_System_arraycopy",
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",
reinterpret_cast<void*>(getClass) },
{ "Java_java_lang_Object_wait",
reinterpret_cast<void*>(wait) },
{ "Java_java_lang_Object_notify",
reinterpret_cast<void*>(notify) },
{ "Java_java_lang_Object_notifyAll",
reinterpret_cast<void*>(notifyAll) },
{ "Java_java_lang_Thread_sleep",
reinterpret_cast<void*>(sleep) },
{ "Java_java_lang_System_loadLibrary",
reinterpret_cast<void*>(loadLibrary) },
{ "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) },
{ "Java_java_lang_Object_toString",
reinterpret_cast<void*>(toString) },
{ "Java_java_lang_Object_wait",
reinterpret_cast<void*>(wait) },
{ 0, 0 }
};

View File

@ -271,6 +271,12 @@ postVisit(Thread* t, Heap::Visitor* v)
void
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) {
t->vm->system->free(t->large);
t->large = 0;
@ -410,88 +416,6 @@ makeJNIName(Thread* t, object method, bool decorate)
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
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);
s.read(&codeBody(t, code, 0), length);
PROTECT(t, code);
unsigned ehtLength = s.read2();
if (ehtLength) {
PROTECT(t, code);
object eht = makeExceptionHandlerTable(t, ehtLength, false);
for (unsigned i = 0; i < ehtLength; ++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);
if (classFlags(t, class_) & ACC_INTERFACE) {
PROTECT(t, vtable);
object it = hashMapIterator(t, virtualMap);
for (; it; it = hashMapIteratorNext(t, it)) {
@ -1144,12 +1069,16 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
ENTER(t, Thread::ExclusiveState);
classVmFlags(t, class_) |= classVmFlags(t, bootstrapClass);
classFlags(t, bootstrapClass) = classFlags(t, class_);
memcpy(bootstrapClass,
class_,
extendedSize(t, class_, baseSize(t, class_, objectClass(t, class_)))
* BytesPerWord);
set(t, classSuper(t, bootstrapClass), classSuper(t, class_));
set(t, classInterfaceTable(t, bootstrapClass),
classInterfaceTable(t, class_));
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_);
if (fieldTable) {
@ -1318,9 +1247,6 @@ Thread::Thread(Machine* m, Allocator* allocator, object javaThread,
peer((parent ? parent->child : 0)),
child(0),
state(NoState),
#ifdef VM_STRESS
stress(false),
#endif // VM_STRESS
systemThread(0),
javaThread(javaThread),
code(0),
@ -1331,6 +1257,10 @@ Thread::Thread(Machine* m, Allocator* allocator, object javaThread,
frame(-1),
heapIndex(0),
protector(0)
#ifdef VM_STRESS
, stress(false),
heap(static_cast<object*>(m->system->allocate(HeapSizeInBytes)))
#endif // VM_STRESS
{
if (parent == 0) {
assert(this, m->rootThread == 0);
@ -1605,6 +1535,86 @@ stringChars(Thread* t, object string, char* chars)
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
hashMapFindNode(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
@ -1919,8 +1929,6 @@ resolveClass(Thread* t, object spec)
(t, className(t, class_), 0));
}
PROTECT(t, class_);
object bootstrapClass = hashMapFind
(t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
@ -1934,6 +1942,8 @@ resolveClass(Thread* t, object spec)
}
if (class_) {
PROTECT(t, class_);
hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash);
} else if (t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));

View File

@ -22,7 +22,7 @@
namespace vm {
const bool Verbose = false;
const bool DebugRun = false;
const bool DebugRun = true;
const bool DebugStack = false;
const bool DebugMonitors = false;
@ -1172,9 +1172,6 @@ class Thread {
Thread* peer;
Thread* child;
State state;
#ifdef VM_STRESS
bool stress;
#endif // VM_STRESS
System::Thread* systemThread;
object javaThread;
object code;
@ -1185,8 +1182,13 @@ class Thread {
int frame;
unsigned heapIndex;
Protector* protector;
uintptr_t stack[StackSizeInWords];
#ifdef VM_STRESS
bool stress;
object* heap;
#else // not VM_STRESS
object heap[HeapSizeInWords];
#endif // not VM_STRESS
uintptr_t stack[StackSizeInWords];
};
inline object
@ -1324,15 +1326,21 @@ allocate(Thread* t, unsigned sizeInBytes)
}
inline void
set(Thread* t, object& target, object value)
mark(Thread* t, object& target)
{
target = value;
if (t->vm->heap->needsMark(&target)) {
ACQUIRE_RAW(t, t->vm->heapLock);
t->vm->heap->mark(&target);
}
}
inline void
set(Thread* t, object& target, object value)
{
target = value;
mark(t, target);
}
inline void
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);
}
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
lineNumber(Thread* t, object method, unsigned ip);

View File

@ -2218,6 +2218,8 @@ run(Thread* t)
void
run(Thread* t, const char* className, int argc, const char** argv)
{
enter(t, Thread::ActiveState);
object args = makeObjectArray
(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);
}
run(t, className, "main", "([Ljava/lang/String;)V", args);
run(t, className, "main", "([Ljava/lang/String;)V", 0, args);
}
} // namespace
@ -2237,9 +2239,64 @@ namespace vm {
object
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);
if (UNLIKELY(t->sp + parameterFootprint(methodSpec) + 1
> Thread::StackSizeInWords / 2))
{
t->exception = makeStackOverflowError(t);
return 0;
}
if (this_) {
pushObject(t, this_);
}
va_list a;
va_start(a, this_);
const char* s = methodSpec;
++ s; // skip '('
while (*s and *s != ')') {
switch (*s) {
case 'L':
while (*s and *s != ';') ++ s;
++ s;
pushObject(t, va_arg(a, object));
break;
case '[':
while (*s == '[') ++ s;
switch (*s) {
case 'L':
while (*s and *s != ';') ++ s;
++ s;
break;
default:
++ s;
break;
}
pushObject(t, va_arg(a, object));
break;
case 'J':
case 'D':
++ s;
pushLong(t, va_arg(a, uint64_t));
break;
default:
++ s;
pushInt(t, va_arg(a, uint32_t));
break;
}
}
va_end(a);
object class_ = resolveClass(t, makeByteArray(t, "%s", className));
if (LIKELY(t->exception == 0)) {
@ -2253,52 +2310,7 @@ run(Thread* t, const char* className, const char* methodName,
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));
}
const char* s = methodSpec;
++ s; // skip '('
while (*s and *s != ')') {
switch (*s) {
case 'L':
while (*s and *s != ';') ++ s;
++ s;
pushObject(t, va_arg(a, object));
break;
case '[':
while (*s == '[') ++ s;
switch (*s) {
case 'L':
while (*s and *s != ';') ++ s;
++ s;
break;
default:
++ s;
break;
}
pushObject(t, va_arg(a, object));
break;
case 'J':
case 'D':
++ s;
pushLong(t, va_arg(a, uint64_t));
break;
default:
++ s;
pushInt(t, va_arg(a, uint32_t));
break;
}
}
va_end(a);
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
if (methodFlags(t, method) & ACC_NATIVE) {
unsigned returnCode = invokeNative(t, method);

View File

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