Original version of exception handling. exceptions
authortzezula
Sat, 08 Dec 2012 08:19:46 +0100
branchexceptions
changeset 285c8be2d837788
parent 114 a0505844750a
child 286 15053b74bdd9
Original version of exception handling.
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
vm/src/test/java/org/apidesign/vm4brwsr/Exceptions.java
vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java
     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 +}