diff --git a/src/builtin.cpp b/src/builtin.cpp index 68327980a3..ffef0725dd 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -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(toString) }, + { "Java_java_lang_System_arraycopy", + reinterpret_cast(arraycopy) }, + { "Java_java_lang_System_loadLibrary", + reinterpret_cast(loadLibrary) }, + + { "Java_java_lang_Thread_start", + reinterpret_cast(start) }, + { "Java_java_lang_Thread_sleep", + reinterpret_cast(sleep) }, + + { "Java_java_lang_Throwable_resolveTrace", + reinterpret_cast(resolveTrace) }, + { "Java_java_lang_Throwable_trace", + reinterpret_cast(trace) }, + { "Java_java_lang_Object_getClass", reinterpret_cast(getClass) }, - { "Java_java_lang_Object_wait", - reinterpret_cast(wait) }, { "Java_java_lang_Object_notify", reinterpret_cast(notify) }, { "Java_java_lang_Object_notifyAll", reinterpret_cast(notifyAll) }, - { "Java_java_lang_Thread_sleep", - reinterpret_cast(sleep) }, - { "Java_java_lang_System_loadLibrary", - reinterpret_cast(loadLibrary) }, - { "Java_java_lang_System_arraycopy", - reinterpret_cast(arraycopy) }, - { "Java_java_lang_Throwable_trace", - reinterpret_cast(trace) }, - { "Java_java_lang_Throwable_resolveTrace", - reinterpret_cast(resolveTrace) }, - { "Java_java_lang_Thread_start", - reinterpret_cast(start) }, + { "Java_java_lang_Object_toString", + reinterpret_cast(toString) }, + { "Java_java_lang_Object_wait", + reinterpret_cast(wait) }, + { 0, 0 } }; diff --git a/src/machine.cpp b/src/machine.cpp index 2e5bde5466..f1281b4984 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -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 + (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(&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(&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(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)); diff --git a/src/machine.h b/src/machine.h index dee4bc0938..3a708c1825 100644 --- a/src/machine.h +++ b/src/machine.h @@ -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(array, (2 + index) * BytesPerWord); } +unsigned +parameterFootprint(const char* s); + +inline unsigned +parameterFootprint(Thread* t, object spec) +{ + return parameterFootprint + (reinterpret_cast(&byteArrayBody(t, spec, 0))); +} + +unsigned +parameterCount(const char* s); + +inline unsigned +parameterCount(Thread* t, object spec) +{ + return parameterCount + (reinterpret_cast(&byteArrayBody(t, spec, 0))); +} + int lineNumber(Thread* t, object method, unsigned ip); diff --git a/src/run.cpp b/src/run.cpp index 679e598b47..d313449913 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -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); diff --git a/src/run.h b/src/run.h index 929320f597..1e721dbfc6 100644 --- a/src/run.h +++ b/src/run.h @@ -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,