From 8d7388a14c3041cbf139b5b238ff9f52a5f4a856 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 20 Sep 2012 14:53:00 +0200 Subject: [PATCH] added exception handling, stupid control structures in jimple are stupid --- jack/native/jack.cpp | 7 ++ .../jack/generators/HeaderGenerator.java | 4 +- .../generators/ImplementationGenerator.java | 4 +- .../jack/generators/MethodBodyGenerator.java | 4 +- .../jack/generators/StatementGenerator.java | 72 +++++++++++++++++-- .../jack-tests/src/jack/tests/Exceptions.java | 30 ++++++++ 6 files changed, 113 insertions(+), 8 deletions(-) diff --git a/jack/native/jack.cpp b/jack/native/jack.cpp index 5b4cabf..fd355fd 100644 --- a/jack/native/jack.cpp +++ b/jack/native/jack.cpp @@ -84,6 +84,12 @@ void testInstanceOf() { obj->m_test(); } +void testExceptions() { + jack_tests_Exceptions* obj = new jack_tests_Exceptions(); + obj->m_init(); + obj->m_simpleCatch(); +} + int main() { jack_gc_init(); jack_init(); @@ -92,4 +98,5 @@ int main() { testReflection(); testPrimes(); testInstanceOf(); + testExceptions(); } \ No newline at end of file diff --git a/jack/src/com/badlogic/jack/generators/HeaderGenerator.java b/jack/src/com/badlogic/jack/generators/HeaderGenerator.java index d123089..e66711a 100755 --- a/jack/src/com/badlogic/jack/generators/HeaderGenerator.java +++ b/jack/src/com/badlogic/jack/generators/HeaderGenerator.java @@ -129,7 +129,9 @@ public void generate() { } private boolean needsUpdate(String fileName, String newContent) { - return !new FileDescriptor(fileName).readString().equals(newContent); + FileDescriptor file = new FileDescriptor(fileName); + if(!file.exists()) return true; + return !file.readString().equals(newContent); } private void generateMethod(SootMethod method, MethodInfo info) { diff --git a/jack/src/com/badlogic/jack/generators/ImplementationGenerator.java b/jack/src/com/badlogic/jack/generators/ImplementationGenerator.java index 641d0a3..bdc07ac 100755 --- a/jack/src/com/badlogic/jack/generators/ImplementationGenerator.java +++ b/jack/src/com/badlogic/jack/generators/ImplementationGenerator.java @@ -72,6 +72,8 @@ public void generate() { } private boolean needsUpdate(String fileName, String newContent) { - return !new FileDescriptor(fileName).readString().equals(newContent); + FileDescriptor file = new FileDescriptor(fileName); + if(!file.exists()) return true; + return !file.readString().equals(newContent); } } diff --git a/jack/src/com/badlogic/jack/generators/MethodBodyGenerator.java b/jack/src/com/badlogic/jack/generators/MethodBodyGenerator.java index 8fbf188..50ab972 100755 --- a/jack/src/com/badlogic/jack/generators/MethodBodyGenerator.java +++ b/jack/src/com/badlogic/jack/generators/MethodBodyGenerator.java @@ -38,7 +38,8 @@ public void generate() { } /** - * Declares all local variables. + * Declares all local variables plus a variable called _exception that + * holds a pointer to any exception thrown. */ private void declareLocals() { // declare locals @@ -54,5 +55,6 @@ private void declareLocals() { } writer.wl(cType + " " + local.getName() + " = 0;"); } + writer.wl("java_lang_Object* _exception = 0;"); } } diff --git a/jack/src/com/badlogic/jack/generators/StatementGenerator.java b/jack/src/com/badlogic/jack/generators/StatementGenerator.java index 3ab9142..1b845d0 100644 --- a/jack/src/com/badlogic/jack/generators/StatementGenerator.java +++ b/jack/src/com/badlogic/jack/generators/StatementGenerator.java @@ -15,6 +15,7 @@ import soot.Scene; import soot.SootClass; import soot.SootMethod; +import soot.Trap; import soot.Type; import soot.Unit; import soot.Value; @@ -82,6 +83,7 @@ import soot.jimple.UshrExpr; import soot.jimple.VirtualInvokeExpr; import soot.jimple.XorExpr; +import soot.jimple.internal.JCaughtExceptionRef; import soot.jimple.internal.JInstanceFieldRef; import soot.shimple.toolkits.scalar.SEvaluator.MetaConstant; import soot.tagkit.LineNumberTag; @@ -110,16 +112,19 @@ public class StatementGenerator { private final Map labels = new HashMap(); private int nextLabelId = 0; private int lastEmittedSourceLine = 0; + private Map> tries = new HashMap>(); + private Map> catches = new HashMap>(); public StatementGenerator(SourceWriter writer, JavaSourceProvider sourceProvider, ClassInfo info, SootMethod method) { this.writer = writer; this.sourceProvider = sourceProvider; this.info = info; - this.body = (JimpleBody)method.retrieveActiveBody(); + this.body = (JimpleBody)method.retrieveActiveBody(); } public void generate() { generateLabels(); + generateTryCatches(); generateStatements(); } @@ -148,8 +153,45 @@ private void generateLabels() { newLabel((Stmt)target); } } - // FIXME exceptions labels for handlers - } + } + + // generate label for begin/end statements of try/catch/finally + for(Trap trap: body.getTraps()) { + Stmt begin = (Stmt)trap.getBeginUnit(); + Stmt end = (Stmt)trap.getEndUnit(); + Stmt handler = (Stmt)trap.getHandlerUnit(); + newLabel(begin); + newLabel(end); + newLabel(handler); + } + } + + private void generateTryCatches() { + // generate label for begin/end statements of try/catch/finally + for(Trap trap: body.getTraps()) { + Stmt begin = (Stmt)trap.getBeginUnit(); + Stmt end = (Stmt)trap.getEndUnit(); + newTry(begin, trap); + newCatch(end, trap); + } + } + + private void newTry(Stmt stmt, Trap trap) { + List traps = tries.get(stmt); + if(traps == null) { + traps = new ArrayList(); + tries.put(stmt, traps); + } + traps.add(trap); + } + + private void newCatch(Stmt stmt, Trap trap) { + List traps = catches.get(stmt); + if(traps == null) { + traps = new ArrayList(); + catches.put(stmt, traps); + } + traps.add(trap); } /** @@ -195,6 +237,14 @@ private void generateStatement(Stmt stmt) { writer.push(); } + // emit tries if any + if(tries.containsKey(stmt)) { + List traps = tries.get(stmt); + for(Trap trap: traps) { + writer.wl("try {"); + } + } + // translate statements and emit as C++ if(stmt instanceof BreakpointStmt) { // BreakpointStmt s = (BreakpointStmt)stmt; @@ -248,7 +298,11 @@ else if(rightOp.getType() instanceof NullType) { Value rightOp = s.getRightOp(); String l = translateValue(leftOp); String r = translateValue(rightOp); - writer.wl(l + " = " + r + ";"); + if(rightOp instanceof JCaughtExceptionRef) { + writer.wl(l + " = dynamic_cast<" + CTypes.toCType(leftOp.getType()) + ">(" + r + ");"); + } else { + writer.wl(l + " = " + r + ";"); + } } else if(stmt instanceof GotoStmt) { GotoStmt s = (GotoStmt)stmt; String label = labels.get((Stmt)s.getTarget()); @@ -308,6 +362,14 @@ else if(rightOp.getType() instanceof NullType) { } else { throw new RuntimeException("Unkown statement " + stmt); } + + // emit catches if any + if(catches.containsKey(stmt)) { + List traps = catches.get(stmt); + for(Trap trap: traps) { + writer.wl("} catch(" + Mangling.mangle(trap.getException()) + "* e) { _exception = e; goto " + labels.get(trap.getHandlerUnit()) + "; }"); + } + } } private void generateSourceComment(Stmt stmt) { @@ -411,7 +473,7 @@ private String translateRef(Ref val) { } else if(val instanceof IdentityRef) { IdentityRef v = (IdentityRef)val; if(v instanceof ThisRef) return "this"; - if(v instanceof CaughtExceptionRef) return "(0)"; // FIXME exceptions + if(v instanceof CaughtExceptionRef) return "_exception"; else return "param" + ((ParameterRef)v).getIndex(); } else throw new RuntimeException("Unknown Ref Value " + val); } diff --git a/runtime/jack-tests/src/jack/tests/Exceptions.java b/runtime/jack-tests/src/jack/tests/Exceptions.java index ebaacf7..2d0b7a6 100755 --- a/runtime/jack-tests/src/jack/tests/Exceptions.java +++ b/runtime/jack-tests/src/jack/tests/Exceptions.java @@ -13,6 +13,36 @@ public void simpleCatch() { try { checked(); } catch(Exception e) { + return; + } + } + + public void controlCatch() { + try { + for(int i = 0; i < 10; i++) { + if(i == 3) { + return; + } + } + } catch(Throwable t) { + + } + } + + public void complexCatch() { + try { + try { + try { + checked(); + } catch(ClassNotFoundException e) { + + } catch(Throwable e) { + + } + } catch(NullPointerException e) { + + } + } catch(Exception e) { } }