diff graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionHandler.java @ 2509:16b9a8b5ad39

Renamings Runtime=>GraalRuntime and Compiler=>GraalCompiler
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 27 Apr 2011 11:50:44 +0200
parents graal/Compiler/src/com/sun/c1x/ir/ExceptionHandler.java@9ec15d6914ca
children 46586c77b129
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionHandler.java	Wed Apr 27 11:50:44 2011 +0200
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.c1x.ir;
+
+import java.util.*;
+
+import com.sun.c1x.lir.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code ExceptionHandler} class represents an exception handler for a Java bytecode method.
+ * There is exactly one instance of this class for every exception handler without any specific
+ * reference to an exception-throwing instruction covered by the handler. Then there is one
+ * instance per exception-throwing instruction that is used to record the frame state before
+ * execution of the instruction. The latter is used to generate exception adapter blocks
+ * (see section 3.4 of the paper <a href="http://www.usenix.org/events/vee05/full_papers/p132-wimmer.pdf">
+ * Optimized Interval Splitting in a Linear Scan Register Allocator</a>) where necessary.
+ *
+ * @author Ben L. Titzer
+ */
+public final class ExceptionHandler {
+
+    public static final List<ExceptionHandler> ZERO_HANDLERS = Collections.emptyList();
+
+    public final RiExceptionHandler handler;
+    private BlockBegin entryBlock;
+    private LIRList entryCode;
+    private int entryCodeOffset;
+    private int phiOperand;
+    private int scopeCount;
+    private int lirOpId;
+
+    public ExceptionHandler(RiExceptionHandler handler) {
+        this.handler = handler;
+        this.entryCodeOffset = -1;
+        this.phiOperand = -1;
+        this.scopeCount = -1;
+        this.lirOpId = -1;
+    }
+
+    public ExceptionHandler(ExceptionHandler other) {
+        this.handler = other.handler;
+        this.entryBlock = other.entryBlock;
+        this.entryCode = other.entryCode;
+        this.entryCodeOffset = other.entryCodeOffset;
+        this.phiOperand = other.phiOperand;
+        this.scopeCount = other.scopeCount;
+        this.lirOpId = other.lirOpId;
+    }
+
+    @Override
+    public String toString() {
+        return "XHandler(Block=" + entryBlock.blockID + ") " + handler;
+    }
+
+    /**
+     * Gets the compiler interface object that describes this exception handler,
+     * including the bytecode ranges.
+     * @return the compiler interface exception handler
+     */
+    public RiExceptionHandler handler() {
+        return handler;
+    }
+
+    /**
+     * Gets the bytecode index of the handler (catch block).
+     * @return the bytecode index of the handler
+     */
+    public int handlerBCI() {
+        return handler.handlerBCI();
+    }
+
+    /**
+     * Utility method to check if this exception handler covers the specified bytecode index.
+     * @param bci the bytecode index to check
+     * @return {@code true} if this exception handler covers the specified bytecode
+     */
+    public boolean covers(int bci) {
+        return handler.startBCI() <= bci && bci < handler.endBCI();
+    }
+
+    /**
+     * Gets the entry block for this exception handler.
+     * @return the entry block
+     */
+    public BlockBegin entryBlock() {
+        return entryBlock;
+    }
+
+    /**
+     * Gets the PC offset of the handler entrypoint, which is used by
+     * the runtime to forward exception points to their catch sites.
+     * @return the pc offset of the handler entrypoint
+     */
+    public int entryCodeOffset() {
+        return entryCodeOffset;
+    }
+
+    public int phiOperand() {
+        return phiOperand;
+    }
+
+    public int scopeCount() {
+        return scopeCount;
+    }
+
+    public void setEntryBlock(BlockBegin entry) {
+        entryBlock = entry;
+    }
+
+    public void setEntryCodeOffset(int pco) {
+        entryCodeOffset = pco;
+    }
+
+    public void setPhiOperand(int phi) {
+        phiOperand = phi;
+    }
+
+    public void setScopeCount(int count) {
+        scopeCount = count;
+    }
+
+    public boolean isCatchAll() {
+        return handler.catchTypeCPI() == 0;
+    }
+
+    public static boolean couldCatch(List<ExceptionHandler> exceptionHandlers, RiType klass, boolean typeIsExact) {
+        // the type is unknown so be conservative
+        if (!klass.isResolved()) {
+            return true;
+        }
+
+        for (int i = 0; i < exceptionHandlers.size(); i++) {
+            ExceptionHandler handler = exceptionHandlers.get(i);
+            if (handler.isCatchAll()) {
+                // catch of ANY
+                return true;
+            }
+            RiType handlerKlass = handler.handler.catchType();
+            // if it's unknown it might be catchable
+            if (!handlerKlass.isResolved()) {
+                return true;
+            }
+            // if the throw type is definitely a subtype of the catch type
+            // then it can be caught.
+            if (klass.isSubtypeOf(handlerKlass)) {
+                return true;
+            }
+            if (!typeIsExact) {
+                // If the type isn't exactly known then it can also be caught by
+                // catch statements where the inexact type is a subtype of the
+                // catch type.
+                // given: foo extends bar extends Exception
+                // throw bar can be caught by catch foo, catch bar, and catch
+                // Exception, however it can't be caught by any handlers without
+                // bar in its type hierarchy.
+                if (handlerKlass.isSubtypeOf(klass)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public int lirOpId() {
+        return lirOpId;
+    }
+
+    public LIRList entryCode() {
+        return entryCode;
+    }
+
+    public void setLirOpId(int throwingOpId) {
+        lirOpId = throwingOpId;
+    }
+
+    public void setEntryCode(LIRList entryCode) {
+        this.entryCode = entryCode;
+
+    }
+}