# HG changeset patch # User tzezula # Date 1354951186 -3600 # Node ID c8be2d83778839664debfcd713be6f36760950e3 # Parent a0505844750a9b9168f0dec0a48bd5010871be9a Original version of exception handling. diff -r a0505844750a -r c8be2d837788 vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Oct 16 18:04:11 2012 +0200 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sat Dec 08 08:19:46 2012 +0100 @@ -36,9 +36,13 @@ import java.io.IOException; import java.io.InputStream; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; +import java.util.Deque; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apidesign.bck2brwsr.core.ExtraJavaScript; import org.apidesign.bck2brwsr.core.JavaScriptBody; import org.netbeans.modules.classfile.Annotation; @@ -54,6 +58,7 @@ import org.netbeans.modules.classfile.ClassName; import org.netbeans.modules.classfile.Code; import org.netbeans.modules.classfile.ElementValue; +import org.netbeans.modules.classfile.ExceptionTableEntry; import org.netbeans.modules.classfile.Method; import org.netbeans.modules.classfile.Parameter; import org.netbeans.modules.classfile.PrimitiveElementValue; @@ -198,7 +203,7 @@ out.append("arg").append(String.valueOf(i)).append(";\n"); } out.append(" var stack = new Array();\n"); - produceCode(code.getByteCodes()); + produceCode(code.getByteCodes(), code.getExceptionTable()); } else { out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n"); } @@ -241,18 +246,38 @@ out.append("arg").append(String.valueOf(i + 1)).append(";\n"); } out.append(";\n var stack = new Array();\n"); - produceCode(code.getByteCodes()); + produceCode(code.getByteCodes(), code.getExceptionTable()); } else { out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n"); } out.append("}"); } - private void produceCode(byte[] byteCodes) throws IOException { + private void produceCode(byte[] byteCodes, ExceptionTableEntry[] exceptionTable) throws IOException { + final Map exStart = new HashMap(); + final Map exStop = new HashMap(); + for (ExceptionTableEntry e : exceptionTable) { + exStart.put(e.getStartPC(), e); + exStop.put(e.getEndPC(), e); + } + final Deque current = new ArrayDeque(); out.append("\n var gt = 0;\n for(;;) switch(gt) {\n"); for (int i = 0; i < byteCodes.length; i++) { + { + ExceptionTableEntry e = exStart.get(i); + if (e != null) { + current.addFirst(e); + } + e = exStop.get(i); + if (e != null) { + current.remove(e); + } + } int prev = i; out.append(" case " + i).append(": "); + if (!current.isEmpty()) { + out.append("try {"); + } final int c = (byteCodes[i] + 256) % 256; switch (c) { case bc_aload_0: @@ -708,13 +733,29 @@ } } + if (!current.isEmpty()) { + out.append("} catch (e) {"); + for (ExceptionTableEntry e : current) { + if (e.getCatchType() != null) { + final String classInternalName = e.getCatchType().getClassName().getInternalName(); + addReference(classInternalName); + out.append("if (e.$instOf_"+classInternalName.replace('/', '_')+") {"); + out.append("gt="+e.getHandlerPC()+"; continue;"); + out.append("} "); + } else { + //finally - todo + } + } + out.append("throw e;"); + out.append("}"); + } out.append(" //"); for (int j = prev; j <= i; j++) { out.append(" "); final int cc = (byteCodes[j] + 256) % 256; out.append(Integer.toString(cc)); } - out.append("\n"); + out.append("\n"); } out.append(" }\n"); } diff -r a0505844750a -r c8be2d837788 vm/src/test/java/org/apidesign/vm4brwsr/Exceptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Exceptions.java Sat Dec 08 08:19:46 2012 +0100 @@ -0,0 +1,36 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.apidesign.vm4brwsr; + +/** + * + * @author tom + */ +public class Exceptions { + + public static int methodWithTryCatchNoThrow() { + int res = 0; + try { + res = 1; + } catch (IllegalArgumentException e) { + res = 2; + } + //join point + return res; + } + + public static int methodWithTryCatchThrow() { + int res = 0; + try { + res = 1; + throw new IllegalArgumentException(); + } catch (IllegalArgumentException e) { + res = 2; + } + //join point + return res; + } + +} diff -r a0505844750a -r c8be2d837788 vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java Sat Dec 08 08:19:46 2012 +0100 @@ -0,0 +1,88 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +/* +Java 4 Browser Bytecode Translator +Copyright (C) 2012-2012 Jaroslav Tulach + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2 of the License. + +This program 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 for more details. + +You should have received a copy of the GNU General Public License +along with this program. Look for COPYING file in the top folder. +If not, see http://opensource.org/licenses/GPL-2.0. +*/ +package org.apidesign.vm4brwsr; + +import javax.script.Invocable; +import javax.script.ScriptException; +import org.testng.annotations.Test; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; + +/** + * + * @author Tomas Zezula + */ +public class ExceptionsTest { + @Test + public void verifyMethodWithTryCatchNoThrow() throws Exception { + assertExec("MethodWithTryCatch", "org_apidesign_vm4brwsr_Exceptions_methodWithTryCatchNoThrowI", + new Double(1.0)); + } + + @Test + public void verifyMethodWithTryCatchThrow() throws Exception { + assertExec("MethodWithTryCatch", "org_apidesign_vm4brwsr_Exceptions_methodWithTryCatchThrowI", + new Double(1.0)); + } + + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { + StringBuilder sb = new StringBuilder(); + code = StaticMethodTest.compileClass(sb, + "org/apidesign/vm4brwsr/Exceptions" + ); + codeSeq = sb; + } + private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception { + Object ret = null; + try { + ret = code.invokeFunction(methodName, args); + } catch (ScriptException ex) { + fail("Execution failed in\n" + codeSeq, ex); + } catch (NoSuchMethodException ex) { + fail("Cannot find method in\n" + codeSeq, ex); + } + if (ret == null && expRes == null) { + return; + } + if (expRes.equals(ret)) { + return; + } + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + codeSeq); + } +}