mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
fix various bugs uncovered in GC stress test
This commit is contained in:
parent
7dab93de00
commit
6dec1cbd42
@ -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 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
198
src/machine.cpp
198
src/machine.cpp
@ -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));
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
52
src/run.cpp
52
src/run.cpp
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user