From: brian Date: Wed, 7 Jul 2004 07:36:33 +0000 (+0000) Subject: more trap cleanup, brian back putAndTrigger... X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=commitdiff_plain;h=0e9197be8053d1e3bc8699a8f527d34850024cd7 more trap cleanup, brian back putAndTrigger... darcs-hash:20040707073633-24bed-b0056b5de9e6dbf2fc713ad6869df45d30f1af18.gz --- 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); } } diff --git a/src/org/ibex/js/JS.java b/src/org/ibex/js/JS.java index c13d2a0..ad13a40 100644 --- a/src/org/ibex/js/JS.java +++ b/src/org/ibex/js/JS.java @@ -300,17 +300,21 @@ public abstract class JS { /** performs a put, triggering traps if present; traps are run in an unpauseable interpreter */ public void putAndTriggerTraps(JS key, JS value) throws JSExn { Trap t = getTrap(key); - throw new Error("FIXME"); - /*if (t != null) t.invoke(value); - elese put(key, value);*/ + if(t == null || (t = t.writeTrap()) == null) put(key,value); + else new Interpreter(t,value,false).resume(); } /** performs a get, triggering traps if present; traps are run in an unpauseable interpreter */ public JS getAndTriggerTraps(JS key) throws JSExn { Trap t = getTrap(key); - throw new Error("FIXME"); - /*if (t != null) return t.invoke(); - else return get(key);*/ + if (t == null || (t = t.readTrap()) == null) return get(key); + else return new Interpreter(t,null,false).resume(); + } + + public JS justTriggerTraps(JS key, JS value) throws JSExn { + Trap t = getTrap(key); + if(t == null || (t = t.writeTrap()) == null) return value; + else return new Interpreter(t,value,true).resume(); } /** adds a trap, avoiding duplicates */ diff --git a/src/org/ibex/js/Test.java b/src/org/ibex/js/Test.java index 478ef8e..c432a6a 100644 --- a/src/org/ibex/js/Test.java +++ b/src/org/ibex/js/Test.java @@ -32,6 +32,7 @@ public class Test extends JS { if(!JS.isString(key)) return null; if("print".equals(JS.toString(key))) return METHOD; if("clone".equals(JS.toString(key))) return METHOD; + if("firethis".equals(JS.toString(key))) return METHOD; if("bgget".equals(JS.toString(key))) { action = "bgget"; try { @@ -68,6 +69,15 @@ public class Test extends JS { return null; } if("clone".equals(JS.toString(method))) return a0 == null ? null : a0.jsclone(); + if("firethis".equals(JS.toString(method))) { + String action = JS.toString(a0); + JS target = a1; + JS key = a2; + if(action.equals("get")) return a1.getAndTriggerTraps(key); + else if(action.equals("put")) a1.putAndTriggerTraps(key,JS.S("some value")); + else if(action.equals("trigger")) return target.justTriggerTraps(key,JS.S("some trigger value")); + return null; + } return null; } }