Original version of exception handling.
1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Oct 16 18:04:11 2012 +0200
1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sat Dec 08 08:19:46 2012 +0100
1.3 @@ -36,9 +36,13 @@
1.4
1.5 import java.io.IOException;
1.6 import java.io.InputStream;
1.7 +import java.util.ArrayDeque;
1.8 import java.util.ArrayList;
1.9 import java.util.Collection;
1.10 +import java.util.Deque;
1.11 +import java.util.HashMap;
1.12 import java.util.List;
1.13 +import java.util.Map;
1.14 import org.apidesign.bck2brwsr.core.ExtraJavaScript;
1.15 import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.16 import org.netbeans.modules.classfile.Annotation;
1.17 @@ -54,6 +58,7 @@
1.18 import org.netbeans.modules.classfile.ClassName;
1.19 import org.netbeans.modules.classfile.Code;
1.20 import org.netbeans.modules.classfile.ElementValue;
1.21 +import org.netbeans.modules.classfile.ExceptionTableEntry;
1.22 import org.netbeans.modules.classfile.Method;
1.23 import org.netbeans.modules.classfile.Parameter;
1.24 import org.netbeans.modules.classfile.PrimitiveElementValue;
1.25 @@ -198,7 +203,7 @@
1.26 out.append("arg").append(String.valueOf(i)).append(";\n");
1.27 }
1.28 out.append(" var stack = new Array();\n");
1.29 - produceCode(code.getByteCodes());
1.30 + produceCode(code.getByteCodes(), code.getExceptionTable());
1.31 } else {
1.32 out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n");
1.33 }
1.34 @@ -241,18 +246,38 @@
1.35 out.append("arg").append(String.valueOf(i + 1)).append(";\n");
1.36 }
1.37 out.append(";\n var stack = new Array();\n");
1.38 - produceCode(code.getByteCodes());
1.39 + produceCode(code.getByteCodes(), code.getExceptionTable());
1.40 } else {
1.41 out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n");
1.42 }
1.43 out.append("}");
1.44 }
1.45
1.46 - private void produceCode(byte[] byteCodes) throws IOException {
1.47 + private void produceCode(byte[] byteCodes, ExceptionTableEntry[] exceptionTable) throws IOException {
1.48 + final Map<Integer, ExceptionTableEntry> exStart = new HashMap<Integer, ExceptionTableEntry>();
1.49 + final Map<Integer, ExceptionTableEntry> exStop = new HashMap<Integer, ExceptionTableEntry>();
1.50 + for (ExceptionTableEntry e : exceptionTable) {
1.51 + exStart.put(e.getStartPC(), e);
1.52 + exStop.put(e.getEndPC(), e);
1.53 + }
1.54 + final Deque<ExceptionTableEntry> current = new ArrayDeque<ExceptionTableEntry>();
1.55 out.append("\n var gt = 0;\n for(;;) switch(gt) {\n");
1.56 for (int i = 0; i < byteCodes.length; i++) {
1.57 + {
1.58 + ExceptionTableEntry e = exStart.get(i);
1.59 + if (e != null) {
1.60 + current.addFirst(e);
1.61 + }
1.62 + e = exStop.get(i);
1.63 + if (e != null) {
1.64 + current.remove(e);
1.65 + }
1.66 + }
1.67 int prev = i;
1.68 out.append(" case " + i).append(": ");
1.69 + if (!current.isEmpty()) {
1.70 + out.append("try {");
1.71 + }
1.72 final int c = (byteCodes[i] + 256) % 256;
1.73 switch (c) {
1.74 case bc_aload_0:
1.75 @@ -708,13 +733,29 @@
1.76 }
1.77
1.78 }
1.79 + if (!current.isEmpty()) {
1.80 + out.append("} catch (e) {");
1.81 + for (ExceptionTableEntry e : current) {
1.82 + if (e.getCatchType() != null) {
1.83 + final String classInternalName = e.getCatchType().getClassName().getInternalName();
1.84 + addReference(classInternalName);
1.85 + out.append("if (e.$instOf_"+classInternalName.replace('/', '_')+") {");
1.86 + out.append("gt="+e.getHandlerPC()+"; continue;");
1.87 + out.append("} ");
1.88 + } else {
1.89 + //finally - todo
1.90 + }
1.91 + }
1.92 + out.append("throw e;");
1.93 + out.append("}");
1.94 + }
1.95 out.append(" //");
1.96 for (int j = prev; j <= i; j++) {
1.97 out.append(" ");
1.98 final int cc = (byteCodes[j] + 256) % 256;
1.99 out.append(Integer.toString(cc));
1.100 }
1.101 - out.append("\n");
1.102 + out.append("\n");
1.103 }
1.104 out.append(" }\n");
1.105 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Exceptions.java Sat Dec 08 08:19:46 2012 +0100
2.3 @@ -0,0 +1,36 @@
2.4 +/*
2.5 + * To change this template, choose Tools | Templates
2.6 + * and open the template in the editor.
2.7 + */
2.8 +package org.apidesign.vm4brwsr;
2.9 +
2.10 +/**
2.11 + *
2.12 + * @author tom
2.13 + */
2.14 +public class Exceptions {
2.15 +
2.16 + public static int methodWithTryCatchNoThrow() {
2.17 + int res = 0;
2.18 + try {
2.19 + res = 1;
2.20 + } catch (IllegalArgumentException e) {
2.21 + res = 2;
2.22 + }
2.23 + //join point
2.24 + return res;
2.25 + }
2.26 +
2.27 + public static int methodWithTryCatchThrow() {
2.28 + int res = 0;
2.29 + try {
2.30 + res = 1;
2.31 + throw new IllegalArgumentException();
2.32 + } catch (IllegalArgumentException e) {
2.33 + res = 2;
2.34 + }
2.35 + //join point
2.36 + return res;
2.37 + }
2.38 +
2.39 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java Sat Dec 08 08:19:46 2012 +0100
3.3 @@ -0,0 +1,88 @@
3.4 +/**
3.5 + * Back 2 Browser Bytecode Translator
3.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
3.7 + *
3.8 + * This program is free software: you can redistribute it and/or modify
3.9 + * it under the terms of the GNU General Public License as published by
3.10 + * the Free Software Foundation, version 2 of the License.
3.11 + *
3.12 + * This program is distributed in the hope that it will be useful,
3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.15 + * GNU General Public License for more details.
3.16 + *
3.17 + * You should have received a copy of the GNU General Public License
3.18 + * along with this program. Look for COPYING file in the top folder.
3.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
3.20 + */
3.21 +/*
3.22 +Java 4 Browser Bytecode Translator
3.23 +Copyright (C) 2012-2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
3.24 +
3.25 +This program is free software: you can redistribute it and/or modify
3.26 +it under the terms of the GNU General Public License as published by
3.27 +the Free Software Foundation, version 2 of the License.
3.28 +
3.29 +This program is distributed in the hope that it will be useful,
3.30 +but WITHOUT ANY WARRANTY; without even the implied warranty of
3.31 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.32 +GNU General Public License for more details.
3.33 +
3.34 +You should have received a copy of the GNU General Public License
3.35 +along with this program. Look for COPYING file in the top folder.
3.36 +If not, see http://opensource.org/licenses/GPL-2.0.
3.37 +*/
3.38 +package org.apidesign.vm4brwsr;
3.39 +
3.40 +import javax.script.Invocable;
3.41 +import javax.script.ScriptException;
3.42 +import org.testng.annotations.Test;
3.43 +import static org.testng.Assert.*;
3.44 +import org.testng.annotations.BeforeClass;
3.45 +
3.46 +/**
3.47 + *
3.48 + * @author Tomas Zezula <tzezula@netbeans.org>
3.49 + */
3.50 +public class ExceptionsTest {
3.51 + @Test
3.52 + public void verifyMethodWithTryCatchNoThrow() throws Exception {
3.53 + assertExec("MethodWithTryCatch", "org_apidesign_vm4brwsr_Exceptions_methodWithTryCatchNoThrowI",
3.54 + new Double(1.0));
3.55 + }
3.56 +
3.57 + @Test
3.58 + public void verifyMethodWithTryCatchThrow() throws Exception {
3.59 + assertExec("MethodWithTryCatch", "org_apidesign_vm4brwsr_Exceptions_methodWithTryCatchThrowI",
3.60 + new Double(1.0));
3.61 + }
3.62 +
3.63 + private static CharSequence codeSeq;
3.64 + private static Invocable code;
3.65 +
3.66 + @BeforeClass
3.67 + public void compileTheCode() throws Exception {
3.68 + StringBuilder sb = new StringBuilder();
3.69 + code = StaticMethodTest.compileClass(sb,
3.70 + "org/apidesign/vm4brwsr/Exceptions"
3.71 + );
3.72 + codeSeq = sb;
3.73 + }
3.74 + private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception {
3.75 + Object ret = null;
3.76 + try {
3.77 + ret = code.invokeFunction(methodName, args);
3.78 + } catch (ScriptException ex) {
3.79 + fail("Execution failed in\n" + codeSeq, ex);
3.80 + } catch (NoSuchMethodException ex) {
3.81 + fail("Cannot find method in\n" + codeSeq, ex);
3.82 + }
3.83 + if (ret == null && expRes == null) {
3.84 + return;
3.85 + }
3.86 + if (expRes.equals(ret)) {
3.87 + return;
3.88 + }
3.89 + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + codeSeq);
3.90 + }
3.91 +}