use of org.vmmagic.pragma.Entrypoint 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.vmmagic.pragma.Entrypoint 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.vmmagic.pragma.Entrypoint in project JikesRVM by JikesRVM.
the class RVMThread method yieldpointFromBackedge.
/**
* Yieldpoint taken on backedge.
*/
@BaselineSaveLSRegisters
// Save all non-volatile registers in prologue
@NoOptCompile
@NoInline
// TODO fix this -- related to SaveVolatile
@Entrypoint
@Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
public static void yieldpointFromBackedge() {
Address fp = Magic.getFramePointer();
yieldpoint(BACKEDGE, fp);
}
use of org.vmmagic.pragma.Entrypoint in project JikesRVM by JikesRVM.
the class ThinLock method inlineLock.
@Inline
@NoNullCheck
@Unpreemptible
@Entrypoint
public static void inlineLock(Object o, Offset lockOffset) {
// FIXME: bad for PPC?
Word old = Magic.prepareWord(o, lockOffset);
Word id = old.and(TL_THREAD_ID_MASK.or(TL_STAT_MASK));
Word tid = Word.fromIntSignExtend(RVMThread.getCurrentThread().getLockingId());
if (id.EQ(tid)) {
Word changed = old.plus(TL_LOCK_COUNT_UNIT);
if (!changed.and(TL_LOCK_COUNT_MASK).isZero()) {
setDedicatedU16(o, lockOffset, changed);
Magic.combinedLoadBarrier();
return;
}
} else if (id.EQ(TL_STAT_THIN)) {
// lock is thin and not held by anyone
if (Magic.attemptWord(o, lockOffset, old, old.or(tid))) {
if (!VM.MagicAttemptImpliesStoreLoadBarrier)
Magic.fence();
return;
}
}
lock(o, lockOffset);
}
use of org.vmmagic.pragma.Entrypoint in project JikesRVM by JikesRVM.
the class MultianewarrayHelper method newArrayArray.
/**
* Allocate something like {@code new Foo[cnt0][cnt1]...[cntN-1]},
* or {@code new int[cnt0][cnt1]...[cntN-1]}.
* @param methodId id of caller
* @param numDimensions number of array dimensions
* @param typeId {@link TypeReference} id of type of array
* @param argOffset position of word *above* `cnt0' argument within caller's frame
* This is used to access the number of elements to
* be allocated for each dimension.
* See also: bytecode 0xc5 ("multianewarray") in Compiler
* @return the new array
*/
@Entrypoint
static Object newArrayArray(int methodId, int numDimensions, int typeId, int argOffset) throws NoClassDefFoundError, NegativeArraySizeException, OutOfMemoryError {
if (numDimensions == 2) {
int dim0, dim1;
// fetch number of elements to be allocated for each array dimension
VM.disableGC();
Address argp = Magic.getFramePointer().loadAddress().plus(argOffset);
int offset = (BYTES_IN_STACKSLOT * 0) + BYTES_IN_INT;
dim0 = argp.minus(offset).loadInt();
offset = (BYTES_IN_STACKSLOT * 1) + BYTES_IN_INT;
dim1 = argp.minus(offset).loadInt();
VM.enableGC();
// validate arguments
if ((dim0 < 0) || (dim1 < 0))
throw new NegativeArraySizeException();
// create array
TypeReference tRef = TypeReference.getTypeRef(typeId);
RVMArray array = tRef.resolve().asArray();
return RuntimeEntrypoints.buildTwoDimensionalArray(methodId, dim0, dim1, array);
} else {
// fetch number of elements to be allocated for each array dimension
int[] numElements = new int[numDimensions];
VM.disableGC();
Address argp = Magic.getFramePointer().loadAddress().plus(argOffset);
for (int i = 0; i < numDimensions; ++i) {
int offset = (BYTES_IN_STACKSLOT * i) + BYTES_IN_INT;
numElements[i] = argp.minus(offset).loadInt();
}
VM.enableGC();
// validate arguments
for (int elements : numElements) {
if (elements < 0)
throw new NegativeArraySizeException();
}
// create array
TypeReference tRef = TypeReference.getTypeRef(typeId);
RVMArray array = tRef.resolve().asArray();
return RuntimeEntrypoints.buildMultiDimensionalArray(methodId, numElements, array);
}
}
Aggregations