X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Forg%2Fibex%2Fjs%2FInterpreter.java;fp=src%2Forg%2Fibex%2Fjs%2FInterpreter.java;h=6f163fabc7fc4831b7fa7d348baaf589e8ed70fa;hb=0e9197be8053d1e3bc8699a8f527d34850024cd7;hp=15d42bef09438020b6da6b243cd8defe181cc333;hpb=b1c3851aa91d7da83b62c267596ecacb6ac73868;p=org.ibex.core.git diff --git a/src/org/ibex/js/Interpreter.java b/src/org/ibex/js/Interpreter.java index 15d42be..6f163fa 100644 --- a/src/org/ibex/js/Interpreter.java +++ b/src/org/ibex/js/Interpreter.java @@ -27,13 +27,22 @@ class Interpreter implements ByteCodes, Tokens { this.pausecount = pauseable ? 0 : -1; this.scope = new JSScope(f.parentScope); try { - stack.push(new CallMarker()); // the "root function returned" marker -- f==null + stack.push(new CallMarker(null)); // the "root function returned" marker -- f==null stack.push(args); } catch(JSExn e) { throw new Error("should never happen"); } } + Interpreter(Trap t, JS val, boolean pauseOnPut) { + this.pausecount = -1; + try { + setupTrap(t,val,new TrapMarker(null,t,val,pauseOnPut)); + } catch(JSExn e) { + throw new Error("should never happen"); + } + } + /** this is the only synchronization point we need in order to be threadsafe */ synchronized JS resume() throws JSExn { if(f == null) throw new RuntimeException("function already finished"); @@ -168,14 +177,14 @@ class Interpreter implements ByteCodes, Tokens { pc = ((TryMarker)o).finallyLoc - 1; continue OUTER; } else if (o instanceof CallMarker) { + boolean didTrapPut = false; if (o instanceof TrapMarker) { // handles return component of a read trap TrapMarker tm = (TrapMarker) o; boolean cascade = tm.t.isWriteTrap() && !tm.cascadeHappened && !JS.toBoolean(retval); if(cascade) { Trap t = tm.t.nextWriteTrap(); - if(t == null && tm.target instanceof JS.Clone) { - tm.target = ((JS.Clone)tm.target).clonee; - t = tm.target.getTrap(tm.key); + if(t == null && tm.t.target instanceof JS.Clone) { + t = ((JS.Clone)tm.t.target).clonee.getTrap(tm.t.key); if(t != null) t = t.writeTrap(); } if(t != null) { @@ -184,7 +193,8 @@ class Interpreter implements ByteCodes, Tokens { pc--; // we increment it on the next iter continue OUTER; } else { - tm.target.put(tm.key,tm.val); + didTrapPut = true; + if(!tm.pauseOnPut) tm.t.target.put(tm.t.key,tm.val); } } } @@ -192,9 +202,13 @@ class Interpreter implements ByteCodes, Tokens { scope = cm.scope; pc = cm.pc - 1; f = cm.f; - stack.push(retval); - if (pausecount > initialPauseCount) { pc++; return null; } // we were paused - if(f == null) return retval; + if (didTrapPut) { + if (((TrapMarker)cm).pauseOnPut) { pc++; return ((TrapMarker)cm).val; } + if (pausecount > initialPauseCount) { pc++; return null; } // we were paused + } else { + stack.push(retval); + } + if (f == null) return retval; continue OUTER; } } @@ -214,8 +228,8 @@ class Interpreter implements ByteCodes, Tokens { CallMarker o = stack.findCall(); if(o instanceof TrapMarker) { tm = (TrapMarker) o; - target = tm.target; - key = tm.key; + target = tm.t.target; + key = tm.t.key; tm.cascadeHappened = true; t = tm.t; if(t.isReadTrap()) throw new JSExn("can't do a write cascade in a read trap"); @@ -235,10 +249,11 @@ class Interpreter implements ByteCodes, Tokens { stack.push(val); if(t != null) { - setupTrap(t,val,new TrapMarker(this,t,target,key,val)); + setupTrap(t,val,new TrapMarker(this,t,val, tm != null && tm.pauseOnPut)); pc--; // we increment later break; } else { + if (tm != null && tm.pauseOnPut) { pc++; return val; } target.put(key,val); if (pausecount > initialPauseCount) { pc++; return null; } // we were paused break; @@ -266,8 +281,8 @@ class Interpreter implements ByteCodes, Tokens { CallMarker o = stack.findCall(); if(o instanceof TrapMarker) { tm = (TrapMarker) o; - target = tm.target; - key = tm.key; + target = tm.t.target; + key = tm.t.key; t = tm.t; if(t.isWriteTrap()) throw new JSExn("can't do a read cascade in a write trap"); t = t.nextReadTrap(); @@ -284,7 +299,7 @@ class Interpreter implements ByteCodes, Tokens { } if(t != null) { - setupTrap(t,null,new TrapMarker(this,t,target,key,null)); + setupTrap(t,null,new TrapMarker(this,t,null)); pc--; // we increment later break; } else { @@ -520,7 +535,7 @@ class Interpreter implements ByteCodes, Tokens { stack.push(cm); stack.push(t.isWriteTrap() ? new JSArgs(val,t.f) : new JSArgs(t.f)); f = t.f; - scope = new TrapScope(t.f.parentScope,t.target,t.f,t.key); + scope = new TrapScope(t.f.parentScope,t); pc = 0; } @@ -538,22 +553,24 @@ class Interpreter implements ByteCodes, Tokens { final int pc; final JSScope scope; final JSFunction f; - public CallMarker(Interpreter cx) { pc = cx.pc + 1; scope = cx.scope; f = cx.f; } - public CallMarker() { pc = -1; scope = null; f = null; } + public CallMarker(Interpreter cx) { + pc = cx == null ? -1 : cx.pc + 1; + scope = cx == null ? null : cx.scope; + f = cx == null ? null : cx.f; + } } static class TrapMarker extends CallMarker { Trap t; - JS target; - final JS key; - final JS val; + JS val; boolean cascadeHappened; - public TrapMarker(Interpreter cx, Trap t, JS target, JS key, JS val) { + final boolean pauseOnPut; + public TrapMarker(Interpreter cx, Trap t, JS val) { this(cx,t,val,false); } + public TrapMarker(Interpreter cx, Trap t, JS val, boolean pauseOnPut) { super(cx); this.t = t; - this.target = target; - this.key = key; this.val = val; + this.pauseOnPut = pauseOnPut; } } @@ -592,18 +609,16 @@ class Interpreter implements ByteCodes, Tokens { } static class TrapScope extends JSScope { - JS trapee; - JS callee; - JS trapname; - public TrapScope(JSScope parent, JS trapee, JS callee, JS trapname) { - super(parent); this.trapee = trapee; this.callee = callee; this.trapname = trapname; + private Trap t; + public TrapScope(JSScope parent, Trap t) { + super(parent); this.t = t; } public JS get(JS key) throws JSExn { if(JS.isString(key)) { //#switch(JS.toString(key)) - case "trapee": return trapee; - case "callee": return callee; - case "trapname": return trapname; + case "trapee": return t.target; + case "callee": return t.f; + case "trapname": return t.key; //#end } return super.get(key); @@ -685,7 +700,7 @@ class Interpreter implements ByteCodes, Tokens { if(cm.f == null) break; String s = cm.f.sourceName + ":" + cm.f.line[cm.pc-1]; if(cm instanceof Interpreter.TrapMarker) - s += " (trap on " + JS.debugToString(((Interpreter.TrapMarker)cm).key) + ")"; + s += " (trap on " + JS.debugToString(((Interpreter.TrapMarker)cm).t.key) + ")"; e.addBacktrace(s); } }