diff --git a/classpath/java/lang/StackTraceElement.java b/classpath/java/lang/StackTraceElement.java index c26db301f5..f20dc27803 100644 --- a/classpath/java/lang/StackTraceElement.java +++ b/classpath/java/lang/StackTraceElement.java @@ -27,6 +27,34 @@ public class StackTraceElement { this.line = line; } + public int hashCode() { + return class_.hashCode() ^ method.hashCode() ^ line; + } + + public boolean equals(Object o) { + if (o instanceof StackTraceElement) { + StackTraceElement e = (StackTraceElement) o; + return class_.equals(e.class_) + && method.equals(e.method) + && line == e.line; + } else { + return false; + } + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(class_).append(".").append(method); + + if (line == NativeLine) { + sb.append(" (native)"); + } else if (line >= 0) { + sb.append(" (line ").append(line).append(")"); + } + + return sb.toString(); + } + public String getClassName() { return class_; } diff --git a/classpath/java/lang/Throwable.java b/classpath/java/lang/Throwable.java index 5250a380af..333a156166 100644 --- a/classpath/java/lang/Throwable.java +++ b/classpath/java/lang/Throwable.java @@ -101,21 +101,7 @@ public class Throwable { StackTraceElement[] trace = resolveTrace(); for (int i = 0; i < trace.length; ++i) { - sb.append(" at ") - .append(trace[i].getClassName()) - .append(".") - .append(trace[i].getMethodName()); - - if (trace[i].isNativeMethod()) { - sb.append(" (native)"); - } else { - int line = trace[i].getLineNumber(); - if (line >= 0) { - sb.append(" (line ").append(line).append(")"); - } - } - - sb.append(nl); + sb.append(" at ").append(trace[i].toString()).append(nl); } if (cause != null) { diff --git a/src/builtin.cpp b/src/builtin.cpp index f93e6e07ef..7a880b846c 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -53,6 +53,7 @@ enumerateThreads(Thread* t, Thread* x, object array, unsigned* index, { if (*index < limit) { set(t, array, ArrayBody + (*index * BytesPerWord), x->javaThread); + ++ (*index); if (x->peer) enumerateThreads(t, x->peer, array, index, limit); @@ -711,7 +712,7 @@ Java_java_lang_Thread_interrupt(Thread* t, jclass, jlong peer) } extern "C" JNIEXPORT jobject JNICALL -Java_java_lang_Thread_getTrace(Thread* t, jclass, jlong peer) +Java_java_lang_Thread_getStackTrace(Thread* t, jclass, jlong peer) { ENTER(t, Thread::ActiveState); diff --git a/src/common.h b/src/common.h index 0e4383fab6..a02627b5d8 100644 --- a/src/common.h +++ b/src/common.h @@ -29,11 +29,12 @@ #ifdef __i386__ # define LD "d" -# define LX "x" # define LLD "lld" #ifdef __APPLE__ # define ULD "lu" +# define LX "lx" #else +# define LX "x" # define ULD "u" #endif #elif defined __x86_64__ diff --git a/src/compile.cpp b/src/compile.cpp index 0712548195..cebeb4f00f 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -41,14 +41,12 @@ class MyThread: public Thread { public: CallTrace(MyThread* t): t(t), - ip(t->ip), base(t->base), stack(t->stack), nativeMethod(0), next(t->trace) { t->trace = this; - t->ip = 0; t->base = 0; t->stack = 0; } @@ -56,7 +54,6 @@ class MyThread: public Thread { ~CallTrace() { t->stack = stack; t->base = base; - t->ip = ip; t->trace = next; } @@ -153,6 +150,14 @@ methodForIp(MyThread* t, void* ip) class MyStackWalker: public Processor::StackWalker { public: + enum State { + Start, + Next, + Method, + NativeMethod, + Finish + }; + class MyProtector: public Thread::Protector { public: MyProtector(MyStackWalker* walker): @@ -161,7 +166,6 @@ class MyStackWalker: public Processor::StackWalker { virtual void visit(Heap::Visitor* v) { v->visit(&(walker->method_)); - v->visit(&(walker->nativeMethod)); } MyStackWalker* walker; @@ -169,109 +173,156 @@ class MyStackWalker: public Processor::StackWalker { MyStackWalker(MyThread* t): t(t), - ip_(t->ip ? t->ip : (t->stack ? *static_cast(t->stack) : 0)), + state(Start), + ip_(t->ip), base(t->base), stack(t->stack), trace(t->trace), - nativeMethod(trace->nativeMethod), - method_(ip_ ? methodForIp(t, ip_) : 0), + method_(0), protector(this) { } MyStackWalker(MyStackWalker* w): t(w->t), + state(w->state), ip_(w->ip_), base(w->base), stack(w->stack), trace(w->trace), - nativeMethod(w->nativeMethod), method_(w->method_), protector(this) { } virtual void walk(Processor::StackVisitor* v) { - if (stack == 0) { - return; - } - - if (not v->visit(this)) { - return; - } - - for (MyStackWalker it(this); it.next();) { + for (MyStackWalker it(this); it.valid();) { MyStackWalker walker(it); if (not v->visit(&walker)) { break; } + it.next(); } } - bool next() { - if (nativeMethod) { - nativeMethod = 0; - } else { - stack = static_cast(base) + 1; - base = *static_cast(base); - ip_ = *static_cast(stack); - method_ = methodForIp(t, *static_cast(stack)); - if (method_ == 0) { - if (trace and trace->stack) { - base = trace->base; - stack = static_cast(trace->stack); + bool valid() { + while (true) { +// fprintf(stderr, "state: %d\n", state); + switch (state) { + case Start: + if (ip_ == 0 and stack) { ip_ = *static_cast(stack); - method_ = methodForIp(t, *static_cast(stack)); - nativeMethod = trace->nativeMethod; - trace = trace->next; - } else { - return false; } + + if (trace and trace->nativeMethod) { + method_ = trace->nativeMethod; + state = NativeMethod; + } else if (ip_) { + state = Next; + } else { + state = Finish; + } + break; + + case Next: + if (stack) { + method_ = methodForIp(t, ip_); + if (method_) { + state = Method; + } else if (trace) { + base = trace->base; + stack = static_cast(trace->stack); + ip_ = (stack ? *static_cast(stack) : 0); + + if (trace->nativeMethod) { + method_ = trace->nativeMethod; + state = NativeMethod; + } else { + trace = trace->next; + state = Next; + } + } else { + state = Finish; + } + } else { + state = Finish; + } + break; + + case Method: + case NativeMethod: + return true; + + case Finish: + return false; + + default: + abort(t); } } - return true; + } + + void next() { + switch (state) { + case Method: + stack = static_cast(base) + 1; + ip_ = (stack ? *static_cast(stack) : 0); + base = *static_cast(base); + state = Next; + break; + + case NativeMethod: + trace = trace->next; + state = Next; + break; + + default: + abort(t); + } } virtual object method() { - if (nativeMethod) { - return nativeMethod; - } else { + switch (state) { + case Method: return method_; + + case NativeMethod: + return trace->nativeMethod; + + default: + abort(t); } } virtual int ip() { - if (nativeMethod) { - return 0; - } else { + switch (state) { + case Method: return reinterpret_cast(ip_) - reinterpret_cast (&singletonValue(t, methodCompiled(t, method_), 0)); + + case NativeMethod: + return 0; + + default: + abort(t); } } virtual unsigned count() { - class Visitor: public Processor::StackVisitor { - public: - Visitor(): count(0) { } + unsigned count = 0; - virtual bool visit(Processor::StackWalker*) { - ++ count; - return true; - } - - unsigned count; - } v; - - MyStackWalker walker(this); - walker.walk(&v); + for (MyStackWalker walker(this); walker.valid();) { + walker.next(); + ++ count; + } - return v.count; + return count; } MyThread* t; + State state; void* ip_; void* base; void* stack; MyThread::CallTrace* trace; - object nativeMethod; object method_; MyProtector protector; }; @@ -1012,14 +1063,9 @@ findCallNode(MyThread* t, void* address); void insertCallNode(MyThread* t, object node); -void -removeCallNode(MyThread* t, object node); - void* findExceptionHandler(Thread* t, object method, void* ip) { - PROTECT(t, method); - object table = codeExceptionHandlerTable(t, methodCode(t, method)); if (table) { object index = arrayBody(t, table, 0); @@ -1033,25 +1079,7 @@ findExceptionHandler(Thread* t, object method, void* ip) unsigned key = difference(ip, compiled) - 1; if (key >= start and key < end) { - object catchType = 0; - if (arrayBody(t, table, i + 1)) { - object e = t->exception; - t->exception = 0; - PROTECT(t, e); - - PROTECT(t, table); - PROTECT(t, index); - - catchType = resolveClassInObject - (t, table, ArrayBody + ((i + 1) * BytesPerWord)); - - if (catchType) { - t->exception = e; - } else { - // can't find what we're supposed to catch - move on. - continue; - } - } + object catchType = arrayBody(t, table, i + 1); if (catchType == 0 or instanceOf(t, catchType, t->exception)) { return compiled + intArrayBody(t, index, (i * 3) + 2); @@ -1070,9 +1098,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetBase, void* ip = t->ip; void* base = t->base; void** stack = static_cast(t->stack); - if (ip) { - t->ip = 0; - } else { + if (ip == 0) { ip = *stack; } @@ -2091,21 +2117,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(doubleToFloat)), - 0, 0, 0, 4, 1, frame->popLong())); + context->indirection, 0, 0, 4, 1, frame->popLong())); } break; case d2i: { frame->pushInt (c->call (c->constant(reinterpret_cast(doubleToInt)), - 0, 0, 0, 4, 1, frame->popLong())); + context->indirection, 0, 0, 4, 1, frame->popLong())); } break; case d2l: { frame->pushLong (c->call (c->constant(reinterpret_cast(doubleToLong)), - 0, 0, 0, 8, 1, frame->popLong())); + context->indirection, 0, 0, 8, 1, frame->popLong())); } break; case dadd: { @@ -2115,7 +2141,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(addDouble)), - 0, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 2, a, b)); } break; case dcmpg: { @@ -2125,7 +2151,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareDoublesG)), - 0, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 2, a, b)); } break; case dcmpl: { @@ -2135,7 +2161,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareDoublesL)), - 0, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 2, a, b)); } break; case dconst_0: @@ -2153,7 +2179,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(divideDouble)), - 0, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 2, a, b)); } break; case dmul: { @@ -2163,14 +2189,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(multiplyDouble)), - 0, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 2, a, b)); } break; case dneg: { frame->pushLong (c->call (c->constant(reinterpret_cast(negateDouble)), - 0, 0, 0, 8, 1, frame->popLong())); + context->indirection, 0, 0, 8, 1, frame->popLong())); } break; case vm::drem: { @@ -2180,7 +2206,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(moduloDouble)), - 0, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 2, a, b)); } break; case dsub: { @@ -2190,7 +2216,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(subtractDouble)), - 0, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 2, a, b)); } break; case dup: @@ -2221,21 +2247,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(floatToDouble)), - 0, 0, 0, 8, 1, frame->popInt())); + context->indirection, 0, 0, 8, 1, frame->popInt())); } break; case f2i: { frame->pushInt (c->call (c->constant(reinterpret_cast(floatToInt)), - 0, 0, 0, 4, 1, frame->popInt())); + context->indirection, 0, 0, 4, 1, frame->popInt())); } break; case f2l: { frame->pushLong (c->call (c->constant(reinterpret_cast(floatToLong)), - 0, 0, 0, 8, 1, frame->popInt())); + context->indirection, 0, 0, 8, 1, frame->popInt())); } break; case fadd: { @@ -2245,7 +2271,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(addFloat)), - 0, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 2, a, b)); } break; case fcmpg: { @@ -2255,7 +2281,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareFloatsG)), - 0, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 2, a, b)); } break; case fcmpl: { @@ -2265,7 +2291,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareFloatsL)), - 0, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 2, a, b)); } break; case fconst_0: @@ -2287,7 +2313,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(divideFloat)), - 0, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 2, a, b)); } break; case fmul: { @@ -2297,14 +2323,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(multiplyFloat)), - 0, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 2, a, b)); } break; case fneg: { frame->pushInt (c->call (c->constant(reinterpret_cast(negateFloat)), - 0, 0, 0, 4, 1, frame->popInt())); + context->indirection, 0, 0, 4, 1, frame->popInt())); } break; case vm::frem: { @@ -2314,7 +2340,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(moduloFloat)), - 0, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 2, a, b)); } break; case fsub: { @@ -2324,7 +2350,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(subtractFloat)), - 0, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 2, a, b)); } break; case getfield: @@ -2422,14 +2448,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(intToDouble)), - 0, 0, 0, 8, 1, frame->popInt())); + context->indirection, 0, 0, 8, 1, frame->popInt())); } break; case i2f: { frame->pushInt (c->call (c->constant(reinterpret_cast(intToFloat)), - 0, 0, 0, 4, 1, frame->popInt())); + context->indirection, 0, 0, 4, 1, frame->popInt())); } break; case i2l: @@ -2656,7 +2682,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(instanceOf)), - 0, 0, 0, 4, + context->indirection, 0, 0, 4, 3, c->thread(), frame->append(class_), frame->popObject())); } break; @@ -2852,14 +2878,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(longToDouble)), - 0, 0, 0, 8, 1, frame->popLong())); + context->indirection, 0, 0, 8, 1, frame->popLong())); } break; case l2f: { frame->pushInt (c->call (c->constant(reinterpret_cast(longToFloat)), - 0, 0, 0, 4, 1, frame->popLong())); + context->indirection, 0, 0, 4, 1, frame->popLong())); } break; case l2i: @@ -3029,7 +3055,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->jmp (c->call (c->constant(reinterpret_cast(lookUpAddress)), - 0, 0, 0, BytesPerWord, + context->indirection, 0, 0, BytesPerWord, 4, key, start, c->constant(pairCount), default_)); for (int32_t i = 0; i < pairCount; ++i) { @@ -3327,7 +3353,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } else { c->call (c->constant(reinterpret_cast(set)), - 0, 0, 0, 0, + context->indirection, 0, 0, 0, 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } break; @@ -3484,6 +3510,8 @@ translateExceptionHandlerTable(MyThread* t, Compiler* c, object code, PROTECT(t, newIndex); object newTable = makeArray(t, length + 1, false); + PROTECT(t, newTable); + set(t, newTable, ArrayBody, newIndex); for (unsigned i = 0; i < length; ++i) { @@ -3499,10 +3527,14 @@ translateExceptionHandlerTable(MyThread* t, Compiler* c, object code, intArrayBody(t, newIndex, (i * 3) + 2) = c->machineIp(exceptionHandlerIp(oldHandler))->value() - start; - object type = - (exceptionHandlerCatchType(oldHandler) ? - singletonObject(t, codePool(t, code), - exceptionHandlerCatchType(oldHandler) - 1) : 0); + object type; + if (exceptionHandlerCatchType(oldHandler)) { + type = resolveClassInPool + (t, codePool(t, code), exceptionHandlerCatchType(oldHandler) - 1); + if (UNLIKELY(t->exception)) return; + } else { + type = 0; + } set(t, newTable, ArrayBody + ((i + 1) * BytesPerWord), type); } @@ -3739,6 +3771,7 @@ finish(MyThread* t, Context* context) translateExceptionHandlerTable(t, c, methodCode(t, context->method), reinterpret_cast(start)); + if (UNLIKELY(t->exception)) return 0; translateLineNumberTable(t, c, methodCode(t, context->method), reinterpret_cast(start)); @@ -3980,14 +4013,6 @@ compileMethod2(MyThread* t) (t, resolveThisPointer(t, t->stack, target)), methodOffset(t, target)) = &singletonValue(t, methodCompiled(t, target), 0); } else { -#ifndef VM_STRESS - // valgrind doesn't like this, since the effect of updateCall - // below does not propagate to valgrind's interpreter: - { ACQUIRE(t, t->m->classLock); - removeCallNode(t, node); - } -#endif - Context context(t); context.assembler->updateCall (reinterpret_cast(callNodeAddress(t, node)), @@ -4196,11 +4221,11 @@ invokeNative(MyThread* t) { if (t->trace->nativeMethod == 0) { object node = findCallNode(t, *static_cast(t->stack)); - t->trace->nativeMethod = callNodeTarget(t, node); + object target = callNodeTarget(t, node); if (callNodeVirtualCall(t, node)) { - t->trace->nativeMethod = resolveTarget - (t, t->stack, t->trace->nativeMethod); + target = resolveTarget(t, t->stack, target); } + t->trace->nativeMethod = target; } uint64_t result = 0; @@ -4535,6 +4560,13 @@ invoke(Thread* thread, object method, ArgumentList* arguments) arguments->position, returnType); } + if (t->exception) { + if (t->backupHeap) { + collect(t, Heap::MinorCollection); + } + return 0; + } + object r; switch (returnCode) { case ByteField: @@ -4571,16 +4603,15 @@ traceSize(Thread* t) { class Counter: public Processor::StackVisitor { public: - Counter(Thread* t): t(t), count(0) { } + Counter(): count(0) { } virtual bool visit(Processor::StackWalker*) { ++ count; return true; } - Thread* t; unsigned count; - } counter(t); + } counter; t->m->processor->walkStack(t, &counter); @@ -4599,15 +4630,26 @@ class SegFaultHandler: public System::SignalHandler { if (t->state == Thread::ActiveState) { object node = methodForIp(t, *ip); if (node) { + void* oldIp = t->ip; + void* oldBase = t->base; + void* oldStack = t->stack; + t->ip = *ip; t->base = *base; t->stack = *stack; ensure(t, FixedSizeOfNullPointerException + traceSize(t)); + t->tracing = true; t->exception = makeNullPointerException(t); + t->tracing = false; findUnwindTarget(t, ip, base, stack); + + t->ip = oldIp; + t->base = oldBase; + t->stack = oldStack; + *thread = t; return true; } @@ -4618,6 +4660,11 @@ class SegFaultHandler: public System::SignalHandler { Machine* m; }; +class MyProcessor; + +MyProcessor* +processor(MyThread* t); + class MyProcessor: public Processor { public: class CodeAllocator: public Allocator { @@ -4929,22 +4976,54 @@ class MyProcessor: public Processor { MyThread* t = static_cast(vmt); MyThread* target = static_cast(vmTarget); + processor(t)->getDefaultCompiled(t); + processor(t)->getNativeCompiled(t); + class Visitor: public System::ThreadVisitor { public: Visitor(MyThread* t, MyThread* target): t(t), target(target) { } virtual void visit(void* ip, void* base, void* stack) { - ensure(t, traceSize(t)); - void* oldIp = target->ip; - void* oldBase = target->ip; + void* oldBase = target->base; void* oldStack = target->stack; - target->ip = ip; - target->base = base; - target->stack = stack; + if (methodForIp(t, ip)) { + target->ip = ip; + target->base = base; + target->stack = stack; + } else { + MyProcessor* p = processor(t); + uint8_t* default_ = reinterpret_cast + (&singletonValue(t, p->defaultCompiled, 0)); + unsigned defaultSize = singletonLength(t, p->defaultCompiled); + + uint8_t* native = reinterpret_cast + (&singletonValue(t, p->nativeCompiled, 0)); + unsigned nativeSize = singletonLength(t, p->nativeCompiled); + + if ((static_cast(ip) >= p->indirectCaller + and static_cast(ip) + < p->indirectCaller + p->indirectCallerSize) + + or (static_cast(ip) >= default_ + and static_cast(ip) < default_ + defaultSize) + + or (static_cast(ip) >= native + and static_cast(ip) < native + nativeSize)) + { + target->ip = *static_cast(stack); + target->base = base; + target->stack = stack; + } + } + + ensure(t, traceSize(target)); + + t->tracing = true; trace = makeTrace(t, target); + t->tracing = false; target->ip = oldIp; target->base = oldBase; @@ -4956,6 +5035,8 @@ class MyProcessor: public Processor { object trace; } visitor(t, target); + t->m->system->visit(t->systemThread, target->systemThread, &visitor); + if (t->backupHeap) { PROTECT(t, visitor.trace); @@ -5082,7 +5163,7 @@ object findCallNode(MyThread* t, void* address) { if (DebugCallTable) { - fprintf(stderr, "find trace node %p\n", address); + fprintf(stderr, "find call node %p\n", address); } MyProcessor* p = processor(t); @@ -5142,7 +5223,7 @@ void insertCallNode(MyThread* t, object node) { if (DebugCallTable) { - fprintf(stderr, "insert trace node %p\n", + fprintf(stderr, "insert call node %p\n", reinterpret_cast(callNodeAddress(t, node))); } @@ -5164,50 +5245,6 @@ insertCallNode(MyThread* t, object node) set(t, p->callTable, ArrayBody + (index * BytesPerWord), node); } -void -removeCallNode(MyThread* t, object node) -{ - if (DebugCallTable) { - fprintf(stderr, "remove call node %p\n", - reinterpret_cast(callNodeAddress(t, node))); - } - - MyProcessor* p = processor(t); - PROTECT(t, node); - - object oldNode = 0; - PROTECT(t, oldNode); - - object newNode = 0; - PROTECT(t, newNode); - - intptr_t key = callNodeAddress(t, node); - unsigned index = static_cast(key) - & (arrayLength(t, p->callTable) - 1); - - for (oldNode = arrayBody(t, p->callTable, index); - oldNode; - oldNode = callNodeNext(t, oldNode)) - { - if (oldNode != node) { - newNode = makeCallNode - (t, callNodeAddress(t, oldNode), - callNodeTarget(t, oldNode), - callNodeVirtualCall(t, oldNode), - newNode); - } - } - - set(t, p->callTable, ArrayBody + (index * BytesPerWord), newNode); - - -- p->callTableSize; - - if (p->callTableSize <= arrayLength(t, p->callTable) / 3) { - p->callTable = resizeTable - (t, p->callTable, arrayLength(t, p->callTable) / 2); - } -} - object& methodTree(MyThread* t) { diff --git a/src/heap.cpp b/src/heap.cpp index 596b9e0a9a..d4942e6f0e 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -1709,6 +1709,11 @@ class MyHeap: public Heap { } } + virtual bool needsMark(void* p, unsigned offset) { + return needsMark(p) and targetNeedsMark + (mask(*(static_cast(p) + offset))); + } + bool targetNeedsMark(void* target) { return target and not c.gen2.contains(target) diff --git a/src/heap.h b/src/heap.h index 8b4331ca1e..bf4dc5a360 100644 --- a/src/heap.h +++ b/src/heap.h @@ -62,6 +62,7 @@ class Heap: public Allocator { virtual void* allocateImmortal(Allocator* allocator, unsigned sizeInWords, bool objectMask, unsigned* totalInBytes) = 0; virtual bool needsMark(void* p) = 0; + virtual bool needsMark(void* p, unsigned offset) = 0; virtual void mark(void* p, unsigned offset, unsigned count) = 0; virtual void pad(void* p) = 0; virtual void* follow(void* p) = 0; diff --git a/src/machine.cpp b/src/machine.cpp index bea74e231d..7c596c9bf9 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -490,6 +490,7 @@ postCollect(Thread* t) if (t->backupHeap) { t->m->heap->free (t->backupHeap, t->backupHeapSizeInWords * BytesPerWord); + t->backupHeap = 0; t->backupHeapIndex = 0; t->backupHeapSizeInWords = 0; } @@ -1735,7 +1736,8 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): heap(defaultHeap), backupHeap(0), backupHeapIndex(0), - backupHeapSizeInWords(0) + backupHeapSizeInWords(0), + tracing(false) #ifdef VM_STRESS , stress(false) #endif // VM_STRESS @@ -2046,6 +2048,10 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, t->backupHeapIndex += ceiling(sizeInBytes, BytesPerWord); cast(o, 0) = 0; return o; + } else if (t->tracing) { + expect(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + <= Thread::HeapSizeInWords); + return allocateSmall(t, sizeInBytes); } ACQUIRE_RAW(t, t->m->stateLock); @@ -2826,6 +2832,7 @@ makeTrace(Thread* t, Processor::StackWalker* walker) } object e = makeTraceElement(t, walker->method(), walker->ip()); + assert(t, index < arrayLength(t, trace)); set(t, trace, ArrayBody + (index * BytesPerWord), e); ++ index; return true; diff --git a/src/machine.h b/src/machine.h index c722155646..cca8a3b564 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1291,6 +1291,7 @@ class Thread { uintptr_t* backupHeap; unsigned backupHeapIndex; unsigned backupHeapSizeInWords; + bool tracing; #ifdef VM_STRESS bool stress; #endif // VM_STRESS @@ -1486,7 +1487,10 @@ mark(Thread* t, object o, unsigned offset, unsigned count) inline void mark(Thread* t, object o, unsigned offset) { - mark(t, o, offset, 1); + if (t->m->heap->needsMark(o, offset / BytesPerWord)) { + ACQUIRE_RAW(t, t->m->heapLock); + t->m->heap->mark(o, offset / BytesPerWord, 1); + } } inline void diff --git a/src/posix.cpp b/src/posix.cpp index 15d195e4b6..6b0c63739f 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -793,6 +793,8 @@ handleSignal(int signal, siginfo_t* info, void* context) System::Thread* t = system->visitTarget; system->visitTarget = 0; + + ACQUIRE_MONITOR(t, system->visitLock); system->visitLock->notifyAll(t); } break; @@ -830,7 +832,13 @@ handleSignal(int signal, siginfo_t* info, void* context) } else if (system->oldHandlers[index].sa_handler) { system->oldHandlers[index].sa_handler(signal); } else { - abort(); + switch (signal) { + case VisitSignal: + break; + + default: + abort(); + } } } diff --git a/src/process.cpp b/src/process.cpp index 570d832570..ecfac1f2d8 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -223,7 +223,11 @@ findLineNumber(Thread* t, object method, unsigned ip) } } - abort(t); + if (top < lineNumberTableLength(t, lnt)) { + return lineNumberLine(lineNumberTableBody(t, lnt, top)); + } else { + return UnknownLine; + } } else { return UnknownLine; } diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 616d3458e2..231e31fb56 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1793,11 +1793,14 @@ writeSizes(Output* out, Object* declarations) out->write(typeFixedSize(o)); out->write(";\n\n"); - out->write("const unsigned ArrayElementSizeOf"); - out->write(capitalize(typeName(o))); - out->write(" = "); - out->write(typeArrayElementSize(o)); - out->write(";\n\n"); + int aes = typeArrayElementSize(o); + if (aes) { + out->write("const unsigned ArrayElementSizeOf"); + out->write(capitalize(typeName(o))); + out->write(" = "); + out->write(aes); + out->write(";\n\n"); + } } break; default: break; diff --git a/src/x86.S b/src/x86.S index 4515fb5efc..830b9f08e5 100644 --- a/src/x86.S +++ b/src/x86.S @@ -17,13 +17,14 @@ .globl vmNativeCall vmNativeCall: pushq %rbp + movq %rsp,%rbp - // %rdi aka 0(%rbp): function - // %rsi aka 8(%rbp): stack - // %rdx aka 16(%rbp): stackSize - // %rcx aka 24(%rbp): gprTable - // %r8 aka 32(%rbp): sseTable - // %r9 aka 40(%rbp): returnType + // %rdi aka -48(%rbp): function + // %rsi aka -40(%rbp): stack + // %rdx aka -32(%rbp): stackSize + // %rcx aka -24(%rbp): gprTable + // %r8 aka -16(%rbp): sseTable + // %r9 aka -8(%rbp): returnType // save our argument registers so we can clobber them pushq %r9 @@ -32,8 +33,6 @@ vmNativeCall: pushq %rdx pushq %rsi pushq %rdi - - movq %rsp,%rbp // reserve space for arguments passed via memory subq %rdx,%rsp @@ -49,21 +48,21 @@ loop: movq %rcx,%rax movq %rcx,%rdx addq %rsp,%rdx - addq 8(%rbp),%rax - movq (%rax),%rax + addq -40(%rbp),%rax + movq (%rax),%rax movq %rax,(%rdx) addq $8,%rcx test: - cmpq 16(%rbp),%rcx + cmpq -32(%rbp),%rcx jb loop // do we need to load the general-purpose registers? - cmpq $0,24(%rbp) + cmpq $0,-24(%rbp) je sse // yes, we do - movq 24(%rbp),%rax + movq -24(%rbp),%rax movq 0(%rax),%rdi movq 8(%rax),%rsi movq 16(%rax),%rdx @@ -73,11 +72,11 @@ test: sse: // do we need to load the SSE registers? - cmpq $0,32(%rbp) + cmpq $0,-16(%rbp) je call // yes, we do - movq 32(%rbp),%rax + movq -16(%rbp),%rax movq 0(%rax),%xmm0 movq 8(%rax),%xmm1 movq 16(%rax),%xmm2 @@ -88,10 +87,10 @@ sse: movq 64(%rax),%xmm7 call: - call *0(%rbp) + call *-48(%rbp) // handle return value based on expected type - movq 40(%rbp),%rcx + movq -8(%rbp),%rcx void: cmpq $VOID_TYPE,%rcx @@ -109,10 +108,6 @@ copy: exit: movq %rbp,%rsp - - // pop our argument registers - addq $48,%rsp - popq %rbp ret