UnwindExceptionToCallerStub.java revision 12968:4d8a004e5c6d
142421Syokota/*
242421Syokota * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
342421Syokota * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
442421Syokota *
542421Syokota * This code is free software; you can redistribute it and/or modify it
642421Syokota * under the terms of the GNU General Public License version 2 only, as
742421Syokota * published by the Free Software Foundation.
842421Syokota *
942421Syokota * This code is distributed in the hope that it will be useful, but WITHOUT
1042421Syokota * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1142421Syokota * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1242421Syokota * version 2 for more details (a copy is included in the LICENSE file that
1342421Syokota * accompanied this code).
1442421Syokota *
1542421Syokota * You should have received a copy of the GNU General Public License version
1642421Syokota * 2 along with this work; if not, write to the Free Software Foundation,
1742421Syokota * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1842421Syokota *
1942421Syokota * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2042421Syokota * or visit www.oracle.com if you need additional information or have any
2142421Syokota * questions.
2242421Syokota */
2342421Syokotapackage org.graalvm.compiler.hotspot.stubs;
2442421Syokota
2542421Syokotaimport static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
2642421Syokotaimport static org.graalvm.compiler.hotspot.nodes.JumpToExceptionHandlerInCallerNode.jumpToExceptionHandlerInCaller;
2742421Syokotaimport static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
2842421Syokotaimport static org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub.checkExceptionNotNull;
2942421Syokotaimport static org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub.checkNoExceptionInThread;
3042421Syokotaimport static org.graalvm.compiler.hotspot.stubs.StubUtil.cAssertionsEnabled;
3142421Syokotaimport static org.graalvm.compiler.hotspot.stubs.StubUtil.decipher;
3242421Syokotaimport static org.graalvm.compiler.hotspot.stubs.StubUtil.newDescriptor;
33119418Sobrienimport static org.graalvm.compiler.hotspot.stubs.StubUtil.printf;
34119418Sobrien
35119418Sobrienimport org.graalvm.compiler.api.replacements.Fold;
3642421Syokotaimport org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
3742421Syokotaimport org.graalvm.compiler.api.replacements.Snippet;
3842421Syokotaimport org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
3942421Syokotaimport org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
4058271Syokotaimport org.graalvm.compiler.debug.Assertions;
4142421Syokotaimport org.graalvm.compiler.graph.Node.ConstantNodeParameter;
4242421Syokotaimport org.graalvm.compiler.graph.Node.NodeIntrinsic;
4358271Syokotaimport org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
4458271Syokotaimport org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
4558271Syokotaimport org.graalvm.compiler.hotspot.meta.HotSpotProviders;
4642421Syokotaimport org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
47207354Ssobomaximport org.graalvm.compiler.nodes.UnwindNode;
48207354Ssobomaximport org.graalvm.compiler.options.OptionValues;
49207354Ssobomaximport org.graalvm.compiler.word.Pointer;
50207354Ssobomaximport org.graalvm.compiler.word.Word;
51147271Smarius
5242421Syokotaimport jdk.vm.ci.code.Register;
53147271Smarius
54147271Smarius/**
55147271Smarius * Stub called by an {@link UnwindNode}. This stub executes in the frame of the method throwing an
56147271Smarius * exception and completes by jumping to the exception handler in the calling frame.
57147271Smarius */
5842421Syokotapublic class UnwindExceptionToCallerStub extends SnippetStub {
59147271Smarius
6042421Syokota    public UnwindExceptionToCallerStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
6142421Syokota        super("unwindExceptionToCaller", options, providers, linkage);
6242421Syokota    }
63102149Speter
6442421Syokota    /**
6542421Syokota     * The current frame is unwound by this stub. Therefore, it does not need to save any registers
6642421Syokota     * as HotSpot uses a caller save convention.
6742421Syokota     */
6842421Syokota    @Override
6942421Syokota    public boolean preservesRegisters() {
7042421Syokota        return false;
7142421Syokota    }
7242421Syokota
7342421Syokota    @Override
7442421Syokota    protected Object getConstantParameterValue(int index, String name) {
7542421Syokota        if (index == 2) {
7642421Syokota            return providers.getRegisters().getThreadRegister();
7742421Syokota        }
7842421Syokota        assert index == 3;
7942421Syokota        return options;
8058271Syokota    }
8158271Syokota
8258271Syokota    @Snippet
8358271Syokota    private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
8458271Syokota        Pointer exceptionOop = Word.objectToTrackedPointer(exception);
8558271Syokota        if (logging(options)) {
8658271Syokota            printf("unwinding exception %p (", exceptionOop.rawValue());
8742421Syokota            decipher(exceptionOop.rawValue());
8842421Syokota            printf(") at %p (", returnAddress.rawValue());
8942421Syokota            decipher(returnAddress.rawValue());
9042421Syokota            printf(")\n");
9142421Syokota        }
9242421Syokota        Word thread = registerAsWord(threadRegister);
9342421Syokota        checkNoExceptionInThread(thread, assertionsEnabled(INJECTED_VMCONFIG));
9442421Syokota        checkExceptionNotNull(assertionsEnabled(INJECTED_VMCONFIG), exception);
9542421Syokota
9642421Syokota        Word handlerInCallerPc = exceptionHandlerForReturnAddress(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, thread, returnAddress);
9742421Syokota
9842421Syokota        if (logging(options)) {
9942421Syokota            printf("handler for exception %p at return address %p is at %p (", exceptionOop.rawValue(), returnAddress.rawValue(), handlerInCallerPc.rawValue());
100147271Smarius            decipher(handlerInCallerPc.rawValue());
101147271Smarius            printf(")\n");
102147271Smarius        }
103147271Smarius
10442421Syokota        jumpToExceptionHandlerInCaller(handlerInCallerPc, exception, returnAddress);
10542421Syokota    }
10658271Syokota
10758271Syokota    @Fold
10842421Syokota    static boolean logging(OptionValues options) {
10942421Syokota        return StubOptions.TraceUnwindStub.getValue(options);
11042421Syokota    }
11142421Syokota
11242421Syokota    /**
11342421Syokota     * Determines if either Java assertions are enabled for Graal or if this is a HotSpot build
11442421Syokota     * where the ASSERT mechanism is enabled.
11542421Syokota     */
11642421Syokota    @Fold
11742421Syokota    @SuppressWarnings("all")
11842421Syokota    static boolean assertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) {
11942421Syokota        return Assertions.ENABLED || cAssertionsEnabled(config);
12042421Syokota    }
12142421Syokota
12242421Syokota    public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = newDescriptor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", Word.class, Word.class,
12342421Syokota                    Word.class);
12442421Syokota
12542421Syokota    @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
12642421Syokota    public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress);
12769781Sdwmalone}
12842421Syokota