use of org.jikesrvm.scheduler.RVMThread in project JikesRVM by JikesRVM.
the class VMThreadMXBeanImpl method getThreadInfoForId.
/**
* Returns a {@link java.lang.management.ThreadInfo}
* object for the given thread id with a stack trace to
* the given depth (0 for empty, Integer.MAX_VALUE for
* full).
*
* @param id the id of the thread whose info should be returned.
* @param maxDepth the depth of the stack trace.
* @return a {@link java.lang.management.ThreadInfo} instance.
*/
static ThreadInfo getThreadInfoForId(long id, int maxDepth) {
Thread thread = getThreadForId(id);
Constructor<ThreadInfo> cons = null;
try {
// ensure class is at least resolved
Class.forName("java.lang.management.ThreadInfo");
cons = ThreadInfo.class.getDeclaredConstructor(Long.TYPE, String.class, Thread.State.class, Long.TYPE, Long.TYPE, String.class, Long.TYPE, String.class, Long.TYPE, Long.TYPE, Boolean.TYPE, Boolean.TYPE, StackTraceElement[].class, MonitorInfo[].class, LockInfo[].class);
cons.setAccessible(true);
RVMThread rvmThread = JikesRVMSupport.getThread(thread);
// TODO number of times blocked for Java monitors
long blockedCount = 0;
// TODO total time blocked for Java monitors
long blockedTime = 0;
long waitingCount = JMXSupport.getWaitingCount(rvmThread);
long waitingTime = JMXSupport.getWaitingTime(rvmThread);
boolean inNative = JMXSupport.isInNative(rvmThread);
boolean suspended = JMXSupport.isSuspended(rvmThread);
StackTraceElement[] stackTrace;
if (maxDepth == 0) {
stackTrace = null;
} else {
stackTrace = JMXSupport.getStackTraceForThread(rvmThread);
int newMax = Math.min(stackTrace.length, maxDepth);
StackTraceElement[] reducedStackTrace = new StackTraceElement[newMax];
int srcPos = stackTrace.length - newMax;
System.arraycopy(stackTrace, srcPos, reducedStackTrace, 0, newMax);
stackTrace = reducedStackTrace;
}
MonitorInfo[] emptyMonitorInfo = new MonitorInfo[0];
LockInfo[] emptyLockInfo = new LockInfo[0];
return cons.newInstance(id, thread.getName(), thread.getState(), blockedCount, blockedTime, null, -1, null, waitingCount, waitingTime, inNative, suspended, stackTrace, emptyMonitorInfo, emptyLockInfo);
} catch (NoSuchMethodException e) {
throw (Error) new InternalError("Couldn't get ThreadInfo constructor").initCause(e);
} catch (InstantiationException e) {
throw (Error) new InternalError("Couldn't create ThreadInfo").initCause(e);
} catch (IllegalAccessException e) {
throw (Error) new InternalError("Couldn't access ThreadInfo").initCause(e);
} catch (InvocationTargetException e) {
throw (Error) new InternalError("ThreadInfo's constructor threw an exception").initCause(e);
} catch (ClassNotFoundException e) {
throw (Error) new InternalError("Problem resolving ThreadInfo").initCause(e);
}
}
use of org.jikesrvm.scheduler.RVMThread in project JikesRVM by JikesRVM.
the class RuntimeEntrypoints method athrow.
// ---------------------------------------------------------------//
// Exception Handling. //
// ---------------------------------------------------------------//
/**
* Deliver a software exception to current java thread.
* @param exceptionObject exception object to deliver
* (null --> deliver NullPointerException).
* does not return
* (stack is unwound and execution resumes in a catch block)
*
* This method is public so that it can be invoked by java.lang.VMClass.
*/
@NoInline
@Entrypoint
@Unpreemptible("Deliver exception possibly from unpreemptible code")
public static void athrow(Throwable exceptionObject) {
if (traceAthrow) {
VM.sysWriteln("in athrow.");
RVMThread.dumpStack();
}
RVMThread myThread = RVMThread.getCurrentThread();
AbstractRegisters exceptionRegisters = myThread.getExceptionRegisters();
// VM.enableGC() is called when the exception is delivered.
VM.disableGC();
Magic.saveThreadState(exceptionRegisters);
exceptionRegisters.setInUse(true);
deliverException(exceptionObject, exceptionRegisters);
}
use of org.jikesrvm.scheduler.RVMThread in project JikesRVM by JikesRVM.
the class RuntimeEntrypoints method deliverHardwareException.
/**
* Deliver a hardware exception to current java thread.
* <p>
* Does not return.
* (stack is unwound, starting at trap site, and
* execution resumes in a catch block somewhere up the stack)
* /or/ execution resumes at instruction following trap
* (for TRAP_STACK_OVERFLOW)
*
* <p> Note: Control reaches here by the actions of an
* external "C" signal handler
* which saves the register state of the trap site into the
* "exceptionRegisters" field of the current
* Thread object.
* The signal handler also inserts a <hardware trap> frame
* onto the stack immediately above this frame, for use by
* HardwareTrapGCMapIterator during garbage collection.
*
* @param trapCode code indicating kind of exception that was trapped
* (see TRAP_xxx, above)
* @param trapInfo array subscript (for array bounds trap, only), marker
* (for stack overflow traps on PPC) or
*/
@Entrypoint
@UnpreemptibleNoWarn
static void deliverHardwareException(int trapCode, Word trapInfo) {
if (VM.verboseSignalHandling)
VM.sysWriteln("delivering hardware exception");
RVMThread myThread = RVMThread.getCurrentThread();
if (VM.verboseSignalHandling)
VM.sysWriteln("we have a thread = ", Magic.objectAsAddress(myThread));
if (VM.verboseSignalHandling)
VM.sysWriteln("it's in state = ", myThread.getExecStatus());
AbstractRegisters exceptionRegisters = myThread.getExceptionRegisters();
if (VM.verboseSignalHandling)
VM.sysWriteln("we have exception registers = ", Magic.objectAsAddress(exceptionRegisters));
if ((trapCode == TRAP_STACK_OVERFLOW || trapCode == TRAP_JNI_STACK) && myThread.getStack().length < (StackFrameLayout.getMaxStackSize() >> LOG_BYTES_IN_ADDRESS) && !myThread.hasNativeStackFrame()) {
// (C trap handler has set register.ip to the instruction following the trap).
if (trapCode == TRAP_JNI_STACK) {
RVMThread.resizeCurrentStack(myThread.getStackLength() + StackFrameLayout.getJNIStackGrowthSize(), exceptionRegisters);
} else {
RVMThread.resizeCurrentStack(myThread.getStackLength() + StackFrameLayout.getStackGrowthSize(), exceptionRegisters);
}
if (VM.VerifyAssertions)
VM._assert(exceptionRegisters.getInUse());
exceptionRegisters.setInUse(false);
Magic.restoreHardwareExceptionState(exceptionRegisters);
if (VM.VerifyAssertions)
VM._assert(NOT_REACHED);
}
// GC stress testing
if (canForceGC()) {
// VM.sysWriteln("FORCING GC: in deliverHardwareException");
System.gc();
}
// Hardware traps in uninterruptible code should be considered hard failures.
if (!VM.sysFailInProgress()) {
Address fp = exceptionRegisters.getInnermostFramePointer();
int compiledMethodId = Magic.getCompiledMethodID(fp);
if (compiledMethodId != StackFrameLayout.getInvisibleMethodID()) {
CompiledMethod compiledMethod = CompiledMethods.getCompiledMethod(compiledMethodId);
Address ip = exceptionRegisters.getInnermostInstructionAddress();
Offset instructionOffset = compiledMethod.getInstructionOffset(ip);
if (compiledMethod.isWithinUninterruptibleCode(instructionOffset)) {
VM.sysWriteln();
switch(trapCode) {
case TRAP_NULL_POINTER:
VM.sysWriteln("Fatal error: NullPointerException within uninterruptible region.");
break;
case TRAP_ARRAY_BOUNDS:
VM.sysWriteln("Fatal error: ArrayIndexOutOfBoundsException within uninterruptible region (index was ", trapInfo.toInt(), ").");
break;
case TRAP_DIVIDE_BY_ZERO:
VM.sysWriteln("Fatal error: DivideByZero within uninterruptible region.");
break;
case TRAP_STACK_OVERFLOW:
case TRAP_JNI_STACK:
VM.sysWriteln("Fatal error: StackOverflowError within uninterruptible region.");
break;
case TRAP_CHECKCAST:
VM.sysWriteln("Fatal error: ClassCastException within uninterruptible region.");
break;
case TRAP_MUST_IMPLEMENT:
VM.sysWriteln("Fatal error: IncompatibleClassChangeError within uninterruptible region.");
break;
case TRAP_STORE_CHECK:
VM.sysWriteln("Fatal error: ArrayStoreException within uninterruptible region.");
break;
case TRAP_UNREACHABLE_BYTECODE:
VM.sysWriteln("Fatal error: Reached a bytecode that was determined to be unreachable within uninterruptible region.");
break;
default:
VM.sysWriteln("Fatal error: Unknown hardware trap within uninterruptible region.");
break;
}
VM.sysWriteln("trapCode = ", trapCode);
VM.sysWriteln("trapInfo = ", trapInfo.toAddress());
VM.sysFail("Exiting virtual machine due to uninterruptibility violation.");
}
}
}
Throwable exceptionObject;
switch(trapCode) {
case TRAP_NULL_POINTER:
exceptionObject = new java.lang.NullPointerException();
break;
case TRAP_ARRAY_BOUNDS:
exceptionObject = new java.lang.ArrayIndexOutOfBoundsException(trapInfo.toInt());
break;
case TRAP_DIVIDE_BY_ZERO:
exceptionObject = new java.lang.ArithmeticException();
break;
case TRAP_STACK_OVERFLOW:
case TRAP_JNI_STACK:
exceptionObject = new java.lang.StackOverflowError();
break;
case TRAP_CHECKCAST:
exceptionObject = new java.lang.ClassCastException();
break;
case TRAP_MUST_IMPLEMENT:
exceptionObject = new java.lang.IncompatibleClassChangeError();
break;
case TRAP_STORE_CHECK:
exceptionObject = new java.lang.ArrayStoreException();
break;
case TRAP_UNREACHABLE_BYTECODE:
exceptionObject = new java.lang.InternalError(UNREACHABLE_BC_MESSAGE);
break;
default:
exceptionObject = new java.lang.UnknownError();
RVMThread.traceback("UNKNOWN ERROR");
break;
}
// VM.enableGC() is called when the exception is delivered.
VM.disableGC();
deliverException(exceptionObject, exceptionRegisters);
}
use of org.jikesrvm.scheduler.RVMThread in project JikesRVM by JikesRVM.
the class CodeInstaller method install.
public static boolean install(ExecutionState state, CompiledMethod cm) {
RVMThread thread = state.getThread();
byte[] stack = thread.getStack();
Offset tsfromFPOffset = state.getTSFPOffset();
Offset fooFPOffset = state.getFPOffset();
int foomid = Magic.getIntAtOffset(stack, fooFPOffset.plus(STACKFRAME_METHOD_ID_OFFSET));
CompiledMethod foo = CompiledMethods.getCompiledMethod(foomid);
int cType = foo.getCompilerType();
// this offset is used to adjust SP to FP right after return
// from a call. 1 stack slot for return address and
// 1 stack slot for saved FP of tsfrom.
Offset sp2fpOffset = fooFPOffset.minus(tsfromFPOffset).minus(2 * BYTES_IN_STACKSLOT);
// should given an estimated length, and print the instructions
// for debugging
Assembler asm = new Assembler(50, VM.TraceOnStackReplacement);
// 1. generate bridge instructions to recover saved registers
if (cType == CompiledMethod.BASELINE) {
// unwind stack pointer, SP is FP now
if (VM.BuildFor32Addr) {
asm.emitADD_Reg_Imm(SP, sp2fpOffset.toInt());
} else {
asm.emitADD_Reg_Imm_Quad(SP, sp2fpOffset.toInt());
}
asm.generateJTOCloadWord(S0, cm.getOsrJTOCoffset());
// restore saved EDI
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(EDI, SP, EDI_SAVE_OFFSET);
} else {
asm.emitMOV_Reg_RegDisp_Quad(EDI, SP, EDI_SAVE_OFFSET);
}
// restore saved EBX
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(EBX, SP, EBX_SAVE_OFFSET);
} else {
asm.emitMOV_Reg_RegDisp_Quad(EBX, SP, EBX_SAVE_OFFSET);
}
// restore frame pointer
asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset());
// do not pop return address and parameters,
// we make a faked call to newly compiled method
asm.emitJMP_Reg(S0);
} else if (cType == CompiledMethod.OPT) {
// /////////////////////////////////////////////////
// recover saved registers from foo's stack frame
// /////////////////////////////////////////////////
OptCompiledMethod fooOpt = (OptCompiledMethod) foo;
// foo definitely not save volatile
boolean saveVolatile = fooOpt.isSaveVolatile();
if (VM.VerifyAssertions) {
VM._assert(!saveVolatile);
}
// assume SP is on foo's stack frame,
int firstNonVolatile = fooOpt.getFirstNonVolatileGPR();
int nonVolatiles = fooOpt.getNumberOfNonvolatileGPRs();
int nonVolatileOffset = fooOpt.getUnsignedNonVolatileOffset();
for (int i = firstNonVolatile; i < firstNonVolatile + nonVolatiles; i++) {
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(NONVOLATILE_GPRS[i], SP, sp2fpOffset.minus(nonVolatileOffset));
} else {
asm.emitMOV_Reg_RegDisp_Quad(NONVOLATILE_GPRS[i], SP, sp2fpOffset.minus(nonVolatileOffset));
}
nonVolatileOffset += BYTES_IN_STACKSLOT;
}
// adjust SP to frame pointer
if (VM.BuildFor32Addr) {
asm.emitADD_Reg_Imm(SP, sp2fpOffset.toInt());
} else {
asm.emitADD_Reg_Imm_Quad(SP, sp2fpOffset.toInt());
}
// restore frame pointer
asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset());
// branch to the newly compiled instructions
asm.generateJTOCjmp(cm.getOsrJTOCoffset());
}
if (VM.TraceOnStackReplacement) {
VM.sysWrite("new CM instr addr ");
VM.sysWriteHex(Statics.getSlotContentsAsAddress(cm.getOsrJTOCoffset()));
VM.sysWriteln();
VM.sysWrite("JTOC register ");
VM.sysWriteHex(Magic.getTocPointer());
VM.sysWriteln();
VM.sysWrite("Thread register ");
VM.sysWriteHex(Magic.objectAsAddress(Magic.getThreadRegister()));
VM.sysWriteln();
VM.sysWriteln("tsfromFPOffset ", tsfromFPOffset);
VM.sysWriteln("fooFPOffset ", fooFPOffset);
VM.sysWriteln("SP + ", sp2fpOffset.plus(BYTES_IN_STACKSLOT));
}
// 3. set thread flags
thread.isWaitingForOsr = true;
thread.bridgeInstructions = asm.getMachineCodes();
thread.fooFPOffset = fooFPOffset;
thread.tsFPOffset = tsfromFPOffset;
Address bridgeaddr = Magic.objectAsAddress(thread.bridgeInstructions);
Memory.sync(bridgeaddr, thread.bridgeInstructions.length() << LG_INSTRUCTION_WIDTH);
AOSLogging.logger.logOsrEvent("OSR code installation succeeded");
return true;
}
use of org.jikesrvm.scheduler.RVMThread in project JikesRVM by JikesRVM.
the class DynamicLibrary method load.
/**
* Load a dynamic library
* @param libName the name of the library to load.
* @return 0 on failure, 1 on success
*/
public static synchronized int load(String libName) {
DynamicLibrary dl = dynamicLibraries.get(libName);
if (dl != null) {
// success: already loaded
return 1;
} else {
// Convert file name from unicode to filesystem character set.
// (Assume file name is ASCII, for now).
//
byte[] asciiName = StringUtilities.stringToBytesNullTerminated(libName);
// make sure we have enough stack to load the library.
// This operation has been known to require more than 20K of stack.
RVMThread myThread = RVMThread.getCurrentThread();
Offset remaining = Magic.getFramePointer().diff(myThread.stackLimit);
int stackNeededInBytes = StackFrameLayout.getStackSizeDLOpen() - remaining.toInt();
if (stackNeededInBytes > 0) {
if (myThread.hasNativeStackFrame()) {
throw new java.lang.StackOverflowError("Not enough space to open shared library");
} else {
RVMThread.resizeCurrentStack(myThread.getStackLength() + stackNeededInBytes, null);
}
}
Address libHandler = SysCall.sysCall.sysDlopen(asciiName);
if (!libHandler.isZero()) {
dynamicLibraries.put(libName, new DynamicLibrary(libName, libHandler));
return 1;
} else {
// fail; file does not exist
return 0;
}
}
}
Aggregations