use of com.oracle.svm.core.deopt.DeoptimizedFrame.VirtualFrame in project graal by oracle.
the class Deoptimizer method printDeoptimizedFrame.
private static void printDeoptimizedFrame(Log log, Pointer sp, DeoptimizedFrame deoptimizedFrame, FrameInfoQueryResult sourceFrameInfo) {
log.string("[Deoptimization of frame").newline();
SubstrateInstalledCode installedCode = deoptimizedFrame.getSourceInstalledCode();
if (installedCode != null) {
log.string(" name: ").string(installedCode.getName()).newline();
}
log.string(" sp: ").hex(sp).string(" ip: ").hex(deoptimizedFrame.getSourcePC()).newline();
if (sourceFrameInfo != null) {
log.string(" stack trace where execution continues:").newline();
FrameInfoQueryResult sourceFrame = sourceFrameInfo;
VirtualFrame targetFrame = deoptimizedFrame.getTopFrame();
while (sourceFrame != null) {
SharedMethod deoptMethod = sourceFrame.getDeoptMethod();
int bci = sourceFrame.getBci();
log.string(" at ");
if (deoptMethod != null) {
StackTraceElement element = deoptMethod.asStackTraceElement(bci);
if (element.getFileName() != null && element.getLineNumber() >= 0) {
log.string(element.toString());
} else {
log.string(deoptMethod.format("%H.%n(%p)")).string(" bci ").signed(bci);
}
} else {
log.string("method at ").hex(sourceFrame.getDeoptMethodAddress()).string(" bci ").signed(bci);
}
log.newline();
if (Options.TraceDeoptimizationDetails.getValue()) {
printVirtualFrame(log, targetFrame);
}
sourceFrame = sourceFrame.getCaller();
targetFrame = targetFrame.getCaller();
}
}
log.string("]").newline();
}
use of com.oracle.svm.core.deopt.DeoptimizedFrame.VirtualFrame in project graal by oracle.
the class Deoptimizer method constructTargetFrame.
/**
* Constructs the frame entries for the deopimization target method.
*
* @param targetInfo The bytecode frame (+ some other info) of the target.
* @param sourceFrame The bytecode frame of the source.
*/
private VirtualFrame constructTargetFrame(CodeInfoQueryResult targetInfo, FrameInfoQueryResult sourceFrame) {
FrameInfoQueryResult targetFrame = targetInfo.getFrameInfo();
long targetFrameSize = targetInfo.getTotalFrameSize() - FrameAccess.returnAddressSize();
VirtualFrame result = new VirtualFrame(targetFrame);
/* The first word of the new content is the return address into the target method. */
result.returnAddress = new DeoptimizedFrame.ReturnAddress(targetContentSize, targetInfo.getIP().rawValue());
targetContentSize += FrameAccess.returnAddressSize();
/* The source and target bytecode frame must match (as they stem from the same BCI). */
assert sourceFrame.getNumLocals() == targetFrame.getNumLocals();
assert sourceFrame.getNumStack() == targetFrame.getNumStack();
assert sourceFrame.getNumLocks() == targetFrame.getNumLocks();
assert targetFrame.getVirtualObjects().length == 0;
assert sourceFrame.getValueInfos().length >= targetFrame.getValueInfos().length;
int numValues = targetFrame.getValueInfos().length;
/*
* Create stack entries for all values of the source frame.
*/
int newEndOfParams = endOfParams;
for (int idx = 0; idx < numValues; idx++) {
ValueInfo targetValue = targetFrame.getValueInfos()[idx];
if (targetValue.getKind() == JavaKind.Illegal) {
/*
* The target value is optimized out, e.g. at a position after the lifetime of a
* local variable. Actually we don't care what's the source value in this case, but
* most likely it's also "illegal".
*/
} else {
JavaConstant con = readValue(sourceFrame.getValueInfos()[idx], sourceFrame);
assert con.getJavaKind() != JavaKind.Illegal;
if (con.getJavaKind().isObject() && SubstrateObjectConstant.isCompressed(con) != targetValue.isCompressedReference()) {
// rewrap in constant with the appropriate compression for the target value
Object obj = SubstrateObjectConstant.asObject(con);
con = SubstrateObjectConstant.forObject(obj, targetValue.isCompressedReference());
}
relockVirtualObject(sourceFrame, idx, con);
switch(targetValue.getType()) {
case StackSlot:
/*
* The target value is on the stack
*/
DeoptimizationCounters.counters().stackValueCount.inc();
int targetOffset = TypeConversion.asS4(targetValue.getData());
assert targetOffset != targetFrameSize : "stack slot would overwrite return address";
int totalOffset = targetContentSize + targetOffset;
assert totalOffset >= endOfParams : "stack location overwrites param area";
if (targetOffset < targetFrameSize) {
/*
* This is the most common case: a regular slot in the stack frame,
* which e.g. holds a variable.
*/
assert totalOffset >= targetContentSize;
result.values[idx] = DeoptimizedFrame.ConstantEntry.factory(totalOffset, con);
} else if (sourceFrame.getCaller() != null) {
/*
* Handle stack parameters for inlined calls: write the value to the
* outgoing parameter area of the caller frame.
*/
assert totalOffset >= targetContentSize;
result.values[idx] = DeoptimizedFrame.ConstantEntry.factory(totalOffset, con);
int endOffset = totalOffset + ConfigurationValues.getObjectLayout().sizeInBytes(con.getJavaKind(), targetValue.isCompressedReference());
if (endOffset > newEndOfParams) {
newEndOfParams = endOffset;
}
}
break;
case DefaultConstant:
case Constant:
/*
* The target value was constant propagated. Check that source and target
* performed the same constant propagation
*/
assert verifyConstant(targetFrame, targetValue, con);
DeoptimizationCounters.counters().constantValueCount.inc();
break;
default:
/*
* There must not be any other target value types because deoptimization
* target methods are only optimized in a limited way. Especially there must
* not be Register values because registers cannot be alive across method
* calls; and there must not be virtual objects because no escape analysis
* is performed.
*/
throw VMError.shouldNotReachHere("unknown deopt target value " + targetValue);
}
}
}
targetContentSize += targetFrameSize;
endOfParams = newEndOfParams;
return result;
}
use of com.oracle.svm.core.deopt.DeoptimizedFrame.VirtualFrame in project graal by oracle.
the class Deoptimizer method deoptSourceFrameOperation.
private DeoptimizedFrame deoptSourceFrameOperation(CodePointer pc, boolean ignoreNonDeoptimizable, IsolateThread currentThread) {
VMOperation.guaranteeInProgress("deoptSourceFrame");
assert DeoptimizationSupport.getDeoptStubPointer().rawValue() != 0;
DeoptimizedFrame existing = checkDeoptimized(sourceSp);
if (existing != null) {
/* Already deoptimized, so nothing to do. */
return existing;
}
FrameInfoQueryResult frameInfo = sourceChunk.getFrameInfo();
if (frameInfo == null) {
if (ignoreNonDeoptimizable) {
return null;
} else {
throw VMError.shouldNotReachHere("Deoptimization: cannot deoptimize a method that was not marked as deoptimizable from address " + Long.toHexString(pc.rawValue()));
}
}
assert sourceChunk.getTotalFrameSize() >= FrameAccess.wordSize() : "no place in frame to put pointer to DeoptimizedFrame";
assert endOfParams == 0;
/*
* In case deoptimization is called from an inlined method, we have to construct multiple
* target frames (one for each inline level) for this source frame. Note that target methods
* are never inlined.
*/
FrameInfoQueryResult deoptInfo = frameInfo;
VirtualFrame previousVirtualFrame = null;
VirtualFrame topFrame = null;
while (deoptInfo != null) {
DeoptimizationCounters.counters().virtualFrameCount.inc();
if (deoptInfo.getDeoptMethodOffset() == 0) {
if (ignoreNonDeoptimizable) {
return null;
} else {
throw VMError.shouldNotReachHere("Deoptimization: cannot deoptimize a method that has no deoptimization entry point: " + deoptInfo.getSourceReference());
}
}
CodeInfoQueryResult targetInfo = CodeInfoTable.lookupDeoptimizationEntrypoint(deoptInfo.getDeoptMethodOffset(), deoptInfo.getEncodedBci());
if (targetInfo == null || targetInfo.getFrameInfo() == null) {
throw VMError.shouldNotReachHere("Deoptimization: no matching target bytecode frame found for bci " + deoptInfo.getBci() + " (encodedBci " + deoptInfo.getEncodedBci() + ") in method at address " + Long.toHexString(deoptInfo.getDeoptMethodAddress().rawValue()));
} else if (!targetInfo.getFrameInfo().isDeoptEntry()) {
throw VMError.shouldNotReachHere("Deoptimization: target frame information not marked as deoptimization entry point for bci " + deoptInfo.getBci() + " (encodedBci " + deoptInfo.getEncodedBci() + ") in method at address" + Long.toHexString(deoptInfo.getDeoptMethodAddress().rawValue()));
}
VirtualFrame virtualFrame = constructTargetFrame(targetInfo, deoptInfo);
if (previousVirtualFrame != null) {
previousVirtualFrame.caller = virtualFrame;
} else {
topFrame = virtualFrame;
}
previousVirtualFrame = virtualFrame;
// Go up one inline level
deoptInfo = deoptInfo.getCaller();
}
if (relockedObjects != null) {
for (Object lockee : relockedObjects) {
if (lockee != null) {
/*
* The re-locked objects must appear as if they had been locked from the thread
* that contains the frame, not the thread that performed deoptimization. Since
* the same object can be re-locked multiple times, we change the thread after
* all virtual frames have been reconstructed.
*/
ImageSingletons.lookup(MonitorSupport.class).setExclusiveOwnerThread(lockee, JavaThreads.singleton().createIfNotExisting(currentThread));
}
}
}
/* Allocate a buffer to hold the contents of the new target frame. */
DeoptimizedFrame deoptimizedFrame = DeoptimizedFrame.factory(targetContentSize, sourceChunk.getTotalFrameSize(), CodeInfoTable.lookupInstalledCode(pc), topFrame, pc);
installDeoptimizedFrame(sourceSp, deoptimizedFrame);
if (Options.TraceDeoptimization.getValue()) {
printDeoptimizedFrame(Log.log(), sourceSp, deoptimizedFrame, frameInfo);
}
logDeoptSourceFrameOperation(sourceSp, deoptimizedFrame);
return deoptimizedFrame;
}
use of com.oracle.svm.core.deopt.DeoptimizedFrame.VirtualFrame in project graal by oracle.
the class SubstrateInspectedFrame method visitFrame.
@Override
public boolean visitFrame(Pointer sp, CodePointer ip, DeoptimizedFrame deoptimizedFrame) {
VirtualFrame virtualFrame = null;
CodeInfoQueryResult info = null;
FrameInfoQueryResult deoptInfo = null;
if (deoptimizedFrame != null) {
virtualFrame = deoptimizedFrame.getTopFrame();
} else {
info = CodeInfoTable.lookupCodeInfoQueryResult(ip);
if (info == null || info.getFrameInfo() == null) {
/*
* We do not have detailed information about this physical frame. It does not
* contain Java frames that we care about, so we can go to the caller.
*/
return true;
}
deoptInfo = info.getFrameInfo();
}
int virtualFrameIndex = 0;
do {
int method;
if (virtualFrame != null) {
assert deoptInfo == null : "must have either deoptimized or non-deoptimized frame information, but not both";
method = virtualFrame.getFrameInfo().getDeoptMethodOffset();
} else {
method = deoptInfo.getDeoptMethodOffset();
}
if (matches(method, curMatchingMethods)) {
if (skip > 0) {
skip--;
} else {
SubstrateInspectedFrame inspectedFrame = new SubstrateInspectedFrame(sp, ip, virtualFrame, info, deoptInfo, virtualFrameIndex);
result = visitor.visitFrame(inspectedFrame);
if (result != null) {
/* The user told us to stop the stackwalk. */
return false;
}
if (virtualFrame == null && inspectedFrame.virtualFrame != null) {
/*
* We deoptimized while visiting the InspectedFrame. Continue walking the
* deoptimized frame.
*/
virtualFrame = inspectedFrame.virtualFrame;
deoptInfo = null;
}
curMatchingMethods = laterMatchingMethods;
}
}
if (virtualFrame != null) {
virtualFrame = virtualFrame.getCaller();
} else {
deoptInfo = deoptInfo.getCaller();
}
virtualFrameIndex++;
} while (virtualFrame != null || deoptInfo != null);
return true;
}
Aggregations