001/* 002 * Copyright (c) 2012, 2015, 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.replacements; 024 025import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; 026import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; 027import static com.oracle.graal.nodes.PiNode.*; 028import static com.oracle.graal.replacements.SnippetTemplate.*; 029import jdk.internal.jvmci.code.*; 030 031import com.oracle.graal.compiler.common.type.*; 032import com.oracle.graal.hotspot.meta.*; 033import com.oracle.graal.nodes.*; 034import com.oracle.graal.nodes.extended.*; 035import com.oracle.graal.nodes.java.*; 036import com.oracle.graal.nodes.spi.*; 037import com.oracle.graal.replacements.*; 038import com.oracle.graal.replacements.Snippet.ConstantParameter; 039import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; 040import com.oracle.graal.replacements.SnippetTemplate.Arguments; 041import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; 042import com.oracle.graal.replacements.nodes.*; 043import com.oracle.graal.word.*; 044 045/** 046 * Snippet for loading the exception object at the start of an exception dispatcher. 047 * <p> 048 * The frame state upon entry to an exception handler is such that it is a 049 * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly the 050 * exception object (per the JVM spec) to rethrow. This means that the code generated for this node 051 * must not cause a deoptimization as the runtime/interpreter would not have a valid location to 052 * find the exception object to be rethrown. 053 */ 054public class LoadExceptionObjectSnippets implements Snippets { 055 056 /** 057 * Alternative way to implement exception object loading. 058 */ 059 private static final boolean USE_C_RUNTIME = Boolean.getBoolean("graal.loadExceptionObject.useCRuntime"); 060 061 @Snippet 062 public static Object loadException(@ConstantParameter Register threadRegister) { 063 Word thread = registerAsWord(threadRegister); 064 Object exception = readExceptionOop(thread); 065 writeExceptionOop(thread, null); 066 writeExceptionPc(thread, Word.zero()); 067 return piCast(exception, StampFactory.forNodeIntrinsic()); 068 } 069 070 public static class Templates extends AbstractTemplates { 071 072 private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException", EXCEPTION_OOP_LOCATION, EXCEPTION_PC_LOCATION); 073 074 public Templates(HotSpotProviders providers, TargetDescription target) { 075 super(providers, providers.getSnippetReflection(), target); 076 } 077 078 public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) { 079 if (USE_C_RUNTIME) { 080 StructuredGraph graph = loadExceptionObject.graph(); 081 ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false)); 082 graph.addBeforeFixed(loadExceptionObject, thread); 083 ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread)); 084 loadExceptionC.setStateAfter(loadExceptionObject.stateAfter()); 085 graph.replaceFixedWithFixed(loadExceptionObject, loadExceptionC); 086 } else { 087 Arguments args = new Arguments(loadException, loadExceptionObject.graph().getGuardsStage(), tool.getLoweringStage()); 088 args.addConst("threadRegister", registers.getThreadRegister()); 089 template(args).instantiate(providers.getMetaAccess(), loadExceptionObject, DEFAULT_REPLACER, args); 090 } 091 } 092 } 093}