001/* 002 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot.stubs; 024 025import jdk.internal.jvmci.code.*; 026import static com.oracle.graal.hotspot.nodes.JumpToExceptionHandlerInCallerNode.*; 027import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; 028import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*; 029import static com.oracle.graal.hotspot.stubs.StubUtil.*; 030 031import com.oracle.graal.api.replacements.*; 032import com.oracle.graal.compiler.common.spi.*; 033import com.oracle.graal.graph.Node.ConstantNodeParameter; 034import com.oracle.graal.graph.Node.NodeIntrinsic; 035import com.oracle.graal.hotspot.*; 036import com.oracle.graal.hotspot.meta.*; 037import com.oracle.graal.hotspot.nodes.*; 038import com.oracle.graal.nodes.*; 039import com.oracle.graal.replacements.*; 040import com.oracle.graal.replacements.Snippet.ConstantParameter; 041import com.oracle.graal.word.*; 042 043/** 044 * Stub called by an {@link UnwindNode}. This stub executes in the frame of the method throwing an 045 * exception and completes by jumping to the exception handler in the calling frame. 046 */ 047public class UnwindExceptionToCallerStub extends SnippetStub { 048 049 public UnwindExceptionToCallerStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { 050 super("unwindExceptionToCaller", providers, linkage); 051 } 052 053 /** 054 * The current frame is unwound by this stub. Therefore, it does not need to save any registers 055 * as HotSpot uses a caller save convention. 056 */ 057 @Override 058 public boolean preservesRegisters() { 059 return false; 060 } 061 062 @Override 063 protected Object getConstantParameterValue(int index, String name) { 064 assert index == 2; 065 return providers.getRegisters().getThreadRegister(); 066 } 067 068 @Snippet 069 private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister) { 070 Pointer exceptionOop = Word.fromObject(exception); 071 if (logging()) { 072 printf("unwinding exception %p (", exceptionOop.rawValue()); 073 decipher(exceptionOop.rawValue()); 074 printf(") at %p (", returnAddress.rawValue()); 075 decipher(returnAddress.rawValue()); 076 printf(")\n"); 077 } 078 Word thread = registerAsWord(threadRegister); 079 checkNoExceptionInThread(thread, assertionsEnabled()); 080 checkExceptionNotNull(assertionsEnabled(), exception); 081 082 Word handlerInCallerPc = exceptionHandlerForReturnAddress(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, thread, returnAddress); 083 084 if (logging()) { 085 printf("handler for exception %p at return address %p is at %p (", exceptionOop.rawValue(), returnAddress.rawValue(), handlerInCallerPc.rawValue()); 086 decipher(handlerInCallerPc.rawValue()); 087 printf(")\n"); 088 } 089 090 jumpToExceptionHandlerInCaller(handlerInCallerPc, exception, returnAddress); 091 } 092 093 @Fold 094 private static boolean logging() { 095 return Boolean.getBoolean("graal.logUnwindExceptionToCallerStub"); 096 } 097 098 /** 099 * Determines if either Java assertions are enabled for {@link UnwindExceptionToCallerStub} or 100 * if this is a HotSpot build where the ASSERT mechanism is enabled. 101 * <p> 102 * This first check relies on the per-class assertion status which is why this method must be in 103 * this class. 104 */ 105 @Fold 106 @SuppressWarnings("all") 107 private static boolean assertionsEnabled() { 108 boolean enabled = false; 109 assert enabled = true; 110 return enabled || cAssertionsEnabled(); 111 } 112 113 public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = newDescriptor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", Word.class, Word.class, 114 Word.class); 115 116 @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) 117 public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress); 118}