2003/08/14 07:01:48
authorbrian <brian@xwt.org>
Fri, 30 Jan 2004 07:04:27 +0000 (07:04 +0000)
committerbrian <brian@xwt.org>
Fri, 30 Jan 2004 07:04:27 +0000 (07:04 +0000)
darcs-hash:20040130070427-aa32f-6882599699fa6a65c8b04bff9eee2c7d587e685b.gz

src/org/xwt/js/CompiledFunctionImpl.java

index 721b0a4..5771060 100644 (file)
@@ -72,11 +72,14 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
             cx.stack.push(args);
             eval(scope);
             Object ret = cx.stack.pop();
-            // FIXME: if we catch an exception in Java, JS won't notice and the stack will be messed up
             if (cx.stack.size() > size)
                 // this should never happen
-                throw new Error("ERROR: stack grew by " + (cx.stack.size() - size) + " elements during call");
+                throw new Error("ERROR: stack grew by " + (cx.stack.size() - size) + " elements during call at " + sourceName + ":" + firstLine);
             return ret;
+        } catch(Error e) {
+            // Unwind the stack
+            while(cx.stack.size() > 0) if(cx.stack.pop() instanceof CallMarker) throw e;
+            throw new Error("CallMarker not found on the stack"); // should never happen
         } finally {
             cx.currentCompiledFunction = saved;
         }
@@ -119,6 +122,7 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
         int pc;
         int lastPC = -1;
         OUTER: for(pc=0; pc<size; pc++) {
+        try {
             String label = null;
             cx.pc = lastPC = pc;
             int curOP = op[pc];
@@ -285,62 +289,27 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
                 for(int j=numArgs - 1; j >= 0; j--) arguments.setElementAt(t.pop(), j);
                 Object o = t.pop();
                 if(o == null) throw je("attempted to call null");
-                try {
-                    Object ret;
-                    if(op[pc] == CALLMETHOD) {
-                        Object method = o;
-                        o = t.pop();
-                        if(o instanceof String || o instanceof Number || o instanceof Boolean)
-                            ret = Internal.callMethodOnPrimitive(o,method,arguments);
-                        else if(o instanceof JS)
-                            ret = ((JS)o).callMethod(method,arguments,false);
-                        else
-                            throw new JS.Exn("Tried to call a method on an object that isn't a JS object");
-                    } else {                   
-                        ret = ((JS.Callable)o).call(arguments);
-                    }
-                    t.push(ret);
-                    break;
-                } catch (JS.Exn e) {
-                    t.push(e);
+                Object ret;
+                if(op[pc] == CALLMETHOD) {
+                    Object method = o;
+                    o = t.pop();
+                    if(o instanceof String || o instanceof Number || o instanceof Boolean)
+                        ret = Internal.callMethodOnPrimitive(o,method,arguments);
+                    else if(o instanceof JS)
+                        ret = ((JS)o).callMethod(method,arguments,false);
+                    else
+                        throw new JS.Exn("Tried to call a method on an object that isn't a JS object");
+                } else {                   
+                    ret = ((JS.Callable)o).call(arguments);
                 }
+                t.push(ret);
+                break;
             }
             // fall through if exception was thrown
             case THROW: {
-                Object exn = t.pop();
-                while(t.size() > 0) {
-                    Object o = t.pop();
-                    if (o instanceof CatchMarker || o instanceof TryMarker) {
-                        boolean inCatch = o instanceof CatchMarker;
-                        if(inCatch) {
-                            o = t.pop();
-                            if(((TryMarker)o).finallyLoc < 0) continue; // no finally block, keep going
-                        }
-                        if(!inCatch && ((TryMarker)o).catchLoc >= 0) {
-                            // run the catch block, this will implicitly run the finally block, if it exists
-                            t.push(o);
-                            t.push(catchMarker);
-                            t.push((exn instanceof JS.Exn) ? ((JS.Exn)exn).getObject() : exn);
-                            s = ((TryMarker)o).scope;
-                            pc = ((TryMarker)o).catchLoc - 1;
-                            continue OUTER;
-                        } else {
-                            t.push(exn);
-                            t.push(new FinallyData(THROW));
-                            s = ((TryMarker)o).scope;
-                            pc = ((TryMarker)o).finallyLoc - 1;
-                            continue OUTER;
-                        }
-                    }
-                    // no handler found within this func
-                    if(o instanceof CallMarker) {
-                        if(exn instanceof JS.Exn)
-                            throw (JS.Exn)exn;
-                        else
-                            throw new JS.Exn(exn);
-                    }
-                }
-                throw new Error("error: THROW invoked but couldn't find a Try or Call Marker!");
+                Object o = t.pop();
+                if(o instanceof JS.Exn) throw (JS.Exn)o;
+                throw new JS.Exn(o);
             }
 
             case INC: case DEC: {
@@ -444,7 +413,37 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
                 default: throw new Error("unknown opcode " + op[pc]);
                 } }
             }
-        }
+        } catch(JS.Exn e) {
+            while(t.size() > 0) {
+                Object o = t.pop();
+                if (o instanceof CatchMarker || o instanceof TryMarker) {
+                    boolean inCatch = o instanceof CatchMarker;
+                    if(inCatch) {
+                        o = t.pop();
+                        if(((TryMarker)o).finallyLoc < 0) continue; // no finally block, keep going
+                    }
+                    if(!inCatch && ((TryMarker)o).catchLoc >= 0) {
+                        // run the catch block, this will implicitly run the finally block, if it exists
+                        t.push(o);
+                        t.push(catchMarker);
+                        t.push(e.getObject());
+                        s = ((TryMarker)o).scope;
+                        pc = ((TryMarker)o).catchLoc - 1;
+                        continue OUTER;
+                    } else {
+                        t.push(e);
+                        t.push(new FinallyData(THROW));
+                        s = ((TryMarker)o).scope;
+                        pc = ((TryMarker)o).finallyLoc - 1;
+                        continue OUTER;
+                    }
+                }
+                // no handler found within this func
+                if(o instanceof CallMarker) throw e;
+            }
+            throw new Error("couldn't find a Try or Call Marker!");
+        } // end try/catch
+        } // end for
         // this should never happen, we will ALWAYS have a RETURN at the end of the func
         throw new Error("Just fell out of CompiledFunction::eval() loop. Last PC was " + lastPC);
     }