changeset 17004:158c9ba66e45

SL: added support for guest language stack traces to SLException; added SLAssertionError.
author Christian Humer <christian.humer@gmail.com>
date Mon, 01 Sep 2014 20:08:18 +0200
parents 8fd42ea95f64
children 112ab4a3de3a
files graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLAssertionError.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertFalseBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertTrueBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java
diffstat 5 files changed, 109 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLAssertionError.java	Mon Sep 01 20:08:18 2014 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 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.oracle.truffle.sl;
+
+/**
+ * An implementation of an {@link AssertionError} also containing the guest language stack trace.
+ */
+public class SLAssertionError extends AssertionError {
+
+    private static final long serialVersionUID = -9138475336963945873L;
+
+    public SLAssertionError(String message) {
+        super(message);
+        initCause(new AssertionError("Java stack trace"));
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return SLException.fillInSLStackTrace(this);
+    }
+
+}
\ No newline at end of file
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java	Mon Sep 01 20:08:18 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java	Mon Sep 01 20:08:18 2014 +0200
@@ -22,15 +22,74 @@
  */
 package com.oracle.truffle.sl;
 
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
 /**
  * SL does not need a sophisticated error checking and reporting mechanism, so all unexpected
  * conditions just abort execution. This exception class is used when we abort from within the SL
  * implementation.
  */
 public class SLException extends RuntimeException {
+
     private static final long serialVersionUID = -6799734410727348507L;
 
     public SLException(String message) {
         super(message);
+        initCause(new Throwable("Java stack trace"));
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return fillInSLStackTrace(this);
+    }
+
+    /**
+     * Uses the Truffle API to iterate the stack frames and to create and set Java
+     * {@link StackTraceElement} elements based on the source sections of the call nodes on the
+     * stack.
+     */
+    static Throwable fillInSLStackTrace(Throwable t) {
+        final List<StackTraceElement> stackTrace = new ArrayList<>();
+        Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Void>() {
+            public Void visitFrame(FrameInstance frame) {
+                Node callNode = frame.getCallNode();
+                if (callNode == null) {
+                    return null;
+                }
+                RootNode root = callNode.getRootNode();
+
+                /*
+                 * There should be no RootNodes other than SLRootNodes on the stack. Just for the
+                 * case if this would change.
+                 */
+                String methodName = "$unknownFunction";
+                if (root instanceof SLRootNode) {
+                    methodName = ((SLRootNode) root).getName();
+                }
+
+                SourceSection sourceSection = callNode.getEncapsulatingSourceSection();
+                Source source = sourceSection != null ? sourceSection.getSource() : null;
+                String sourceName = source != null ? source.getName() : null;
+                int lineNumber;
+                try {
+                    lineNumber = sourceSection != null ? sourceSection.getLineLocation().getLineNumber() : -1;
+                } catch (UnsupportedOperationException e) {
+                    /*
+                     * SourceSection#getLineLocation() may throw an UnsupportedOperationException.
+                     */
+                    lineNumber = -1;
+                }
+                stackTrace.add(new StackTraceElement("SL", methodName, sourceName, lineNumber));
+                return null;
+            }
+        });
+        t.setStackTrace(stackTrace.toArray(new StackTraceElement[stackTrace.size()]));
+        return t;
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertFalseBuiltin.java	Mon Sep 01 20:08:18 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertFalseBuiltin.java	Mon Sep 01 20:08:18 2014 +0200
@@ -26,6 +26,7 @@
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
 import com.oracle.truffle.sl.runtime.*;
 
 /**
@@ -43,11 +44,7 @@
     public boolean doAssert(boolean value, String message) {
         if (value) {
             CompilerDirectives.transferToInterpreter();
-            if (message == null) {
-                throw new AssertionError();
-            } else {
-                throw new AssertionError(message);
-            }
+            throw new SLAssertionError(message == null ? "" : message);
         }
         return value;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertTrueBuiltin.java	Mon Sep 01 20:08:18 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertTrueBuiltin.java	Mon Sep 01 20:08:18 2014 +0200
@@ -26,6 +26,7 @@
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
 import com.oracle.truffle.sl.runtime.*;
 
 /**
@@ -43,11 +44,7 @@
     public boolean doAssert(boolean value, String message) {
         if (!value) {
             CompilerDirectives.transferToInterpreter();
-            if (message == null) {
-                throw new AssertionError();
-            } else {
-                throw new AssertionError(message);
-            }
+            throw new SLAssertionError(message == null ? "" : message);
         }
         return value;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Mon Sep 01 20:08:18 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Mon Sep 01 20:08:18 2014 +0200
@@ -67,6 +67,10 @@
         return bodyNode.executeGeneric(frame);
     }
 
+    public String getName() {
+        return name;
+    }
+
     @Override
     public boolean isSplittable() {
         return true;