Search in sources :

Example 1 with VirtualFrame

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();
}
Also used : VirtualFrame(com.oracle.svm.core.deopt.DeoptimizedFrame.VirtualFrame) SharedMethod(com.oracle.svm.core.meta.SharedMethod) FrameInfoQueryResult(com.oracle.svm.core.code.FrameInfoQueryResult)

Example 2 with VirtualFrame

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;
}
Also used : VirtualFrame(com.oracle.svm.core.deopt.DeoptimizedFrame.VirtualFrame) ValueInfo(com.oracle.svm.core.code.FrameInfoQueryResult.ValueInfo) JavaConstant(jdk.vm.ci.meta.JavaConstant) FrameInfoQueryResult(com.oracle.svm.core.code.FrameInfoQueryResult)

Example 3 with VirtualFrame

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;
}
Also used : VirtualFrame(com.oracle.svm.core.deopt.DeoptimizedFrame.VirtualFrame) MonitorSupport(com.oracle.svm.core.MonitorSupport) CodeInfoQueryResult(com.oracle.svm.core.code.CodeInfoQueryResult) FrameInfoQueryResult(com.oracle.svm.core.code.FrameInfoQueryResult)

Example 4 with VirtualFrame

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;
}
Also used : VirtualFrame(com.oracle.svm.core.deopt.DeoptimizedFrame.VirtualFrame) CodeInfoQueryResult(com.oracle.svm.core.code.CodeInfoQueryResult) FrameInfoQueryResult(com.oracle.svm.core.code.FrameInfoQueryResult)

Aggregations

FrameInfoQueryResult (com.oracle.svm.core.code.FrameInfoQueryResult)4 VirtualFrame (com.oracle.svm.core.deopt.DeoptimizedFrame.VirtualFrame)4 CodeInfoQueryResult (com.oracle.svm.core.code.CodeInfoQueryResult)2 MonitorSupport (com.oracle.svm.core.MonitorSupport)1 ValueInfo (com.oracle.svm.core.code.FrameInfoQueryResult.ValueInfo)1 SharedMethod (com.oracle.svm.core.meta.SharedMethod)1 JavaConstant (jdk.vm.ci.meta.JavaConstant)1