Revision: 4695 http://sourceforge.net/p/vexi/code/4695 Author: mkpg2 Date: 2014-05-10 14:21:51 +0000 (Sat, 10 May 2014) Log Message: ----------- Devl Memory Mode. - show trapholders as well as objects (potential alternative source of leak) - improve leak path formatting significantly -- removed majority of unnecessary java noise in leak path trace -- show variable names in leak path trace
Modified Paths: -------------- branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/JSUX.java branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/RTScopeInfo.java branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/ScopeInfoManager.java branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memory/GCUtil.java branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memory/Memory.java branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memoryhist/MemoryHist.java branches/vexi3/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/Instr.java branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/JSU.java branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/parse/Parser.java branches/vexi3/org.vexi-library.js/src/main/jpp/org/ibex/js/JS.jpp Modified: branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/JSUX.java =================================================================== --- branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/JSUX.java 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/JSUX.java 2014-05-10 14:21:51 UTC (rev 4695) @@ -10,4 +10,18 @@ } return i; } + + + static public Integer scopeLookup(Scope scope, Object var){ + try{ + for(int i=scope.base+scope.vars.length-1; i>=0; i--){ + if(var==scope.get(i)){ + return i; + } + } + }catch(JSExn e){ + throw new Error(e); + } + return null; + } } Modified: branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/RTScopeInfo.java =================================================================== --- branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/RTScopeInfo.java 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/RTScopeInfo.java 2014-05-10 14:21:51 UTC (rev 4695) @@ -12,9 +12,9 @@ static public class Map{ /** Scope to RuntimeScopeInfo*/ - static private HashMap scopeToRTSI = new HashMap(10); + static private java.util.Map scopeToRTSI = new HashMap(10); /*<String,ScopeInfo>*/ - static private HashMap scopeInfos = new HashMap(); + static private java.util.Map<String,ScopeInfo> scopeInfos = new HashMap(); @@ -44,7 +44,9 @@ return (ScopeInfo) scopeInfos.get(sikey); } - + static public ScopeInfo getScopeInfo(JSFunction func) { + return scopeInfos.get(sikey(func.f, 0)); + } } RTScopeInfo(Function f, int pc){ Modified: branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/ScopeInfoManager.java =================================================================== --- branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/ScopeInfoManager.java 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-core.devtools/src/main/java/org/ibex/js/ScopeInfoManager.java 2014-05-10 14:21:51 UTC (rev 4695) @@ -1,6 +1,7 @@ package org.ibex.js; import java.util.Hashtable; +import java.util.Iterator; import java.util.Vector; import org.ibex.js.parse.ByteCodes; @@ -276,21 +277,21 @@ }*/ - - // Returns key (name) from value (scopeslot) - static String reverseLookupScopeInfo(ScopeInfo si, int slot){ -// Iterator I = si.mapping.keySet().iterator(); -// while(I.hasNext()){ -// -// String vn = (String) I.next(); -// ScopeEntry entry = (ScopeEntry) si.mapping.get(vn); -// if(entry.slot.i == slot){ -// return vn ; -// } -// } -// return "? (" + slot + ")"; - return "? (Lookip not currently supported)"; + static public String reverseLookupScopeInfo(ScopeInfo si, int slot){ + while(si!=null){ + Iterator I = si.mapping.keySet().iterator(); + while(I.hasNext()){ + + String vn = (String) I.next(); + ScopeEntry entry = (ScopeEntry) si.mapping.get(vn); + if(((JSNumber)entry.slot).toInt32() == slot){ + return vn ; + } + } + si = si.parent; + } + return "? (" + slot + ")"; } // Get previous NEWSCOPE (scope corresponding to pc) Modified: branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memory/GCUtil.java =================================================================== --- branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memory/GCUtil.java 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memory/GCUtil.java 2014-05-10 14:21:51 UTC (rev 4695) @@ -20,26 +20,23 @@ import java.util.*; import org.ibex.js.*; +import org.ibex.js.JS.TrapHolder; +import org.ibex.js.parse.Parser.ScopeInfo; +import org.vexi.core.Box; +import org.vexi.util.BasicTree; import org.vexi.util.Log; import org.netbeans.insane.scanner.*; /** * */ public abstract class GCUtil { - - - /** Assert GC. Tries to GC ref's referent. - * @param text the text to show when test fails. - * @param ref the referent to object that - * should be GCed - */ - public static void assertGC(String text, java.lang.ref.Reference ref) { - Log.warn("GCUtil", "Making sure of GC, this may take a while ..."); + static public boolean ensurecGC(java.lang.ref.Reference ref){ + Log.warn("GCUtil", "Making sure of GC, this may take a while ..."); ArrayList alloc = new ArrayList (); int size = 100000; for (int i = 0; i < 50; i++) { - if (ref.get() == null) { - return; + if (ref!=null && ref.get() == null) { + return true; } System.gc(); System.runFinalization(); @@ -56,9 +53,20 @@ } } alloc = null; - Log.warn("GCUtil", "Reference not GC'd. Processing heap now, this may also take a while ..."); - throw new AssertionError(text + ":\n" + findRefsFromRoot(ref.get())); + return false; } + + /** Assert GC. Tries to GC ref's referent. + * @param text the text to show when test fails. + * @param ref the referent to object that + * should be GCed + */ + public static void assertGC(String text, java.lang.ref.Reference ref) { + if(!ensurecGC(ref)){ + Log.warn("GCUtil", "Reference not GC'd. Processing heap now, this may also take a while ..."); + throw new AssertionError(text + ":\n" + findRefsFromRoot(ref.get())); + } + } private static String findRefsFromRoot(final Object target) { final Map objects = new IdentityHashMap(); @@ -105,28 +113,110 @@ return "Not found!!!"; } } - /** BFS scan of incomming refs*/ - private static String findRoots(Map objects, Object obj) { - class PathElement { - private Entry item; - private PathElement next; - public PathElement(Entry item, PathElement next) { - this.item = item; - this.next = next; - } - - public Entry getItem() { - return item; - } - public String toString() { - if (next == null) { - return item.toString(); - } else { - return item.toString() + "->\n" + next.toString(); - } - } + + + + static class PathElement { + Entry entry; + PathElement next; + public PathElement(Entry entry, PathElement next) { + this.entry = entry; + this.next = next; } + public Object getObject() { + return entry.get(); + } + public Entry getItem() { + return entry; + } + public String toString() { + return format(this); + } + } + + static private String objectClass(Object obj){ + if(obj instanceof JS.TrapHolder){ + return "(TrapHolder)"; + }else if(obj instanceof JS){ + return "(JS)"; + }else{ + return "(Java)"; + } + } + + static private String formatInner(Object obj){ + if(obj instanceof JS.TrapHolder){ + JS.TrapHolder th = (JS.TrapHolder)obj; + return format(th.target())+" . "+th.key()+" ++= "+format(th.function()); + }else if(obj instanceof JS){ + JS js = (JS)obj; + try { + return JSON.marshal(js).coerceToString(); + } catch (JSExn e) { + return obj.toString() + " (Could not stringify: "+e.getMessage()+")"; + } + }else{ + return obj.toString(); + } + } + + static private String format(Object obj){ + String r = ""; + if(Memory.get(obj)!=null) + r+= Memory.get(obj).firstLine() + ":"; // JS object + r+= formatInner(obj); + return r; + } + + + static public String formatLine(PathElement e){ + String r = "\n"+objectClass(e.getObject())+" "+format(e.getObject()); + if(e.next!=null){ + PathElement next = e.next; + // UGLY this is unavoidably implementation specific, + // and may break if the JS.Obj implementation is changed + if(e.next.next!=null && e.next.next.next!=null && e.next.next.next.next!=null && + e.getObject() instanceof JS.Obj && + e.next.getObject() instanceof Map && + e.next.next.next.getObject() instanceof Map.Entry){ + + + Map.Entry me = (Map.Entry)e.next.next.next.getObject(); + Object v = me.getValue(); + boolean th = v instanceof TrapHolder; + r+="\n "+(th?"++= ":".")+me.getKey(); + next = e.next.next.next.next; + }else if(e.next.next!=null && e.next.next.next!=null && + e.getObject() instanceof Box && + e.next.getObject() instanceof BasicTree){ + Box child = (Box)e.next.next.next.getObject(); + r+="\n ["+child.getIndexInParent()+"]"; + next = e.next.next.next; + }else if(e.next.next!=null && e.next.next.next!=null && + e.getObject() instanceof JSFunction && + e.next.getObject() instanceof Scope){ + JSFunction func = (JSFunction)e.getObject(); + Scope scope = (Scope)e.next.getObject(); + Object variable = e.next.next.next.getObject(); + Integer j = JSUX.scopeLookup(scope, variable); + if(j!=null){ + ScopeInfo si = RTScopeInfo.Map.getScopeInfo(func); + String varname = ScopeInfoManager.reverseLookupScopeInfo(si, j); + r+="\n var "+varname; + next = e.next.next.next; + } + + } + + r+=formatLine(next); + } + return r; + } + + /** BFS scan of incomming refs*/ + static private String findRoots(Map objects, Object obj) { + Set visited = new HashSet(); Entry fin = (Entry)objects.get(obj); assert(fin!=null); @@ -141,7 +231,7 @@ Iterator it = act.getItem().staticRefs(); if (it.hasNext()) { Field fld = (Field)it.next(); - return fld + "-> (from static)\n" + act; + return "(Static Root) "+format(fld)+ formatLine(act); } // follow incomming @@ -174,6 +264,8 @@ stat = EMPTY; } + public Object get(){ return obj; } + void addOut(Object o) { out = append(out, o); } @@ -205,25 +297,6 @@ ret[origLen] = add; return ret; } - - public String toString() { - String r = ""; - if(Memory.get(obj)!=null) - r+= Memory.get(obj).firstLine() + ":"; // JS object - else - r+= " "; // non-JS object - - if(obj instanceof JS){ - try { - return r+=JSON.marshal((JS)obj).coerceToString() + " JS"; - } catch (JSExn e) { - return r+=obj.toString() + " (Could not stringify: "+e.getMessage()+")"; - } - }else{ - r+=obj.toString() + " java"; - } - return r; - //return obj.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(obj)); - } + } } Modified: branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memory/Memory.java =================================================================== --- branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memory/Memory.java 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memory/Memory.java 2014-05-10 14:21:51 UTC (rev 4695) @@ -20,85 +20,135 @@ import org.ibex.js.JS; import org.ibex.js.JSExn; import org.ibex.js.JSU; +import org.ibex.js.RTScopeInfo; +import org.ibex.js.parse.Parser.ScopeInfo; import org.ibex.util.Basket; import org.vexi.util.Log; // FIXME - move devl js implementation out of here -public class Memory extends JS.Immutable implements Instr.Memory { +public class Memory extends JS.Immutable implements Instr.Memory, Instr.Compilation { static int counter = 0; static class Marker extends JS.Obj{ final int id = counter++; - public void finalize(){ Log.warn(Memory.class, "*** MARKER("+id+" finalized ***"); } + int references = 1; + public void finalize(){ Log.warn(Memory.class, "*** MARKER("+id+") finalized ***"); } } - static Marker MARKER = new Marker(); - static Reference MARKER_REF; + //static Marker MARKER = new Marker(); + static Reference MARKER_REF = new SoftReference(null); public Memory() { Instr.devl = this; Instr.memory = this; + Instr.compilation = this; new Panel().go(); } + public Marker getMarker(){ + Marker marker = (Marker)MARKER_REF.get(); + if(marker==null){ + marker = new Marker(); + MARKER_REF = new SoftReference(marker); + Log.warn(Memory.class, "*** MARKER("+marker.id+") set ***"); + }else{ + Log.warn(Memory.class, "*** MARKER("+marker.id+") reused "+(++marker.references)+" time(s) ***"); + } + return marker; + } + public JS get(JS key_) throws JSExn { String key = JSU.toString(key_); if("MARKER".equals(key)){ - if(MARKER == null) - return null; - Marker r = MARKER; - MARKER_REF = new SoftReference(MARKER); - MARKER = null; - Log.warn(Memory.class, "*** MARKER("+r.id+") set ***"); - return r; + return getMarker(); + }else if("MARKER_SINGLEUSE".equals(key)){ + if(MARKER_REF.get()!=null) return null; + return getMarker(); } return null; } public void assertCollection(){ - if(MARKER != null) Log.warn(Memory.class, "MARKER has not been set yet"); - else{ - try{ - GCUtil.assertGC("MARKER not collected", MARKER_REF); - }finally{ - MARKER = new Marker(); - } - } + GCUtil.assertGC("MARKER not referenced", MARKER_REF); } - public void dumpStacks(){ - System.err.println(); - System.err.println("*** Object creation report"); - System.err.println("Unique stacks:" + stackToCount.size()); - System.err.println("Top 15"); - List l = new ArrayList(stackToCount.keySet()); - Collections.sort(l, new Comparator(){ - public int compare(Object sa, Object sb) { - int ca = ((Integer)stackToCount.get(sa)).intValue(); - int cb = ((Integer)stackToCount.get(sb)).intValue(); - if(ca==cb) return 0; - if(ca>cb) return -1; - return 1; + + + //////// + // MEMORY LEAK TRACKING + ///// + static class BookKeeper<O>{ + final String name; + final private Map<Integer,ObjInfo> hashToObjInfo = new HashMap(); + final private Map stackToCount = new HashMap(); + public BookKeeper(String name) { + this.name = name; + } + + synchronized void clear(){ + hashToObjInfo.clear(); + stackToCount.clear(); + } + + synchronized ObjInfo register(O o, String title){ + Integer hash = System.identityHashCode(o); + ObjInfo oi = objInfo(o,title); + hashToObjInfo.put(hash, oi); + + Integer c = (Integer)stackToCount.get(oi.bt); + if(c==null) stackToCount.put(oi.bt,1); + else { + stackToCount.put(oi.bt,c.intValue()+1); } - - }); + return oi; + } + + synchronized void unregister(O o){ + Integer hash =System.identityHashCode(o); + ObjInfo oi = (ObjInfo)hashToObjInfo.get(hash); + if(oi!=null){ + Integer c = (Integer)stackToCount.get(oi.bt); + if(c.intValue()==1) stackToCount.remove(oi.bt); + else stackToCount.put(oi.bt,new Integer(c.intValue()-1)); + } + } - for(int i=0;i<15; i++){ - Object s = l.get(i); - System.err.println(stackToCount.get(s)); - System.err.println(s); + + public ObjInfo get(Object o){ + Integer hash = System.identityHashCode(o); + return (ObjInfo) hashToObjInfo.get(hash); + } + + public void dumpStacks(){ + System.err.println(); + System.err.println("*** "+name+" creation report"); + System.err.println("Unique stacks:" + stackToCount.size()); + System.err.println("Top 15"); + List l = new ArrayList(stackToCount.keySet()); + Collections.sort(l, new Comparator(){ + public int compare(Object sa, Object sb) { + int ca = ((Integer)stackToCount.get(sa)).intValue(); + int cb = ((Integer)stackToCount.get(sb)).intValue(); + if(ca==cb) return 0; + if(ca>cb) return -1; + return 1; + } + + }); +// int n = Math.min(stackToCount.size(), 15); + for(int i=0;i<stackToCount.size(); i++){ + Object s = l.get(i); + System.err.println(stackToCount.get(s)); + System.err.println(s); + + } } } - - //////// - // MEMORY LEAK TRACKING - ///// - static private Map hashToObjInfo = new HashMap(); - static private Map stackToCount = new HashMap(); - + static final BookKeeper objects = new BookKeeper("Object"); + static final BookKeeper trapholders = new BookKeeper("TrapHolder"); static class ObjInfo{ final String bt; // the backtrace when it is created @@ -106,58 +156,38 @@ String firstLine(){ return bt.split("\\n")[0]; } } - static private boolean doesOverrideHashCode(Object o){ - try { - java.lang.reflect.Method m = o.getClass().getMethod("hashCode", new Class[]{}); - Class declaring = m.getDeclaringClass(); - if(Object.class!=declaring) - return false; - return true; - } catch (Exception e) { - throw new RuntimeException(e); - } - } static public ObjInfo get(Object o){ - if(!doesOverrideHashCode(o)) - return null; - - Integer hash = new Integer(o.hashCode()); - return (ObjInfo) hashToObjInfo.get(hash); + return (ObjInfo) objects.get(o); } + synchronized public void register(JS o){ if(!(o instanceof JSExn.Obj)){ - if(!doesOverrideHashCode(o)) - throw new RuntimeException("Cannot register objects with overridden hashcodes " + o.getClass().getName()); - - Integer hash = new Integer(o.hashCode()); - ObjInfo oi = objInfo(); - hashToObjInfo.put(hash, oi); - - Integer c = (Integer)stackToCount.get(oi.bt); - if(c==null) stackToCount.put(oi.bt,new Integer(1)); - else stackToCount.put(oi.bt,new Integer(c.intValue()+1)); + objects.register(o, o.getClass().getName()); + } } synchronized public void unregister(JS o){ if(!(o instanceof JSExn.Obj)){ - Integer hash = new Integer(o.hashCode()); - ObjInfo oi = (ObjInfo) hashToObjInfo.remove(hash); - - Integer c = (Integer)stackToCount.get(oi.bt); - if(c.intValue()==1) stackToCount.remove(oi.bt); - else stackToCount.put(oi.bt,new Integer(c.intValue()-1)); + objects.unregister(o); } } + public void register(JS.TrapHolder o){ + trapholders.register(o, o.function().coerceToString()); + } + public void unregister(JS.TrapHolder o){ + trapholders.unregister(o); + } - static public ObjInfo objInfo(){ + static public ObjInfo objInfo(Object o, String title){ Basket.List bt = JSU.backtrace(); - StringBuffer b = new StringBuffer(512); + StringBuilder b = new StringBuilder(512); + b.append(title); for(int i=0; i<bt.size(); i++){ - if(i!=0) b.append("\n"); + b.append("\n"); b.append(bt.get(i)); } return new ObjInfo(b.toString()); @@ -178,15 +208,17 @@ JButton button1 = new JButton("Restart collection"); button1.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { - // TODO + objects.clear(); + trapholders.clear(); } }); - button1.setEnabled(false); +// button1.setEnabled(false); JButton button2 = new JButton("Dump Stacks"); button2.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { - dumpStacks(); + objects.dumpStacks(); + trapholders.dumpStacks(); } }); @@ -209,7 +241,7 @@ JButton button4 = new JButton("GC"); button4.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { - System.gc(); + GCUtil.ensurecGC(null); System.runFinalization(); } }); @@ -224,7 +256,7 @@ JButton button6 = new JButton("Reset MARKER"); button6.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { - MARKER=new Marker(); + MARKER_REF.clear(); } }); @@ -238,4 +270,8 @@ frame.setVisible(true); } } + + public void putScopeInfo(ScopeInfo si) { + RTScopeInfo.Map.put(si); + } } Modified: branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memoryhist/MemoryHist.java =================================================================== --- branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memoryhist/MemoryHist.java 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-core.devtools/src/main/java/org/vexi/instrument/memoryhist/MemoryHist.java 2014-05-10 14:21:51 UTC (rev 4695) @@ -9,7 +9,13 @@ import org.ibex.js.*; -// FIXME - move devl js implementation out of here +// MEMORY HIST +// This is really for vexi core development. Not debugging a particular vexi +// program. +// +// Shows a histogram of object numbers vs their size in terms of properties and traps. +// From this we can decide how better to implement Objects (i.e. which cases need +// optimising for) public class MemoryHist extends JS.Immutable implements Instr.Memory { @@ -18,36 +24,19 @@ new Panel().go(); } - //////// - // MEMORY LEAK TRACKING - ///// static private Map hashToObj = new HashMap(); - static private boolean doesOverrideHashCode(Object o){ - try { - java.lang.reflect.Method m = o.getClass().getMethod("hashCode", new Class[]{}); - Class declaring = m.getDeclaringClass(); - if(Object.class!=declaring) - return false; - return true; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - + synchronized public void register(JS o){ if(!(o instanceof JSExn.Obj)){ - if(!doesOverrideHashCode(o)) - throw new RuntimeException("Cannot register objects with overridden hashcodes " + o.getClass().getName()); - - Integer hash = new Integer(o.hashCode()); + Integer hash = System.identityHashCode(o); hashToObj.put(hash, o); } } synchronized public void unregister(JS o){ if(!(o instanceof JSExn.Obj)){ - Integer hash = new Integer(o.hashCode()); + Integer hash = System.identityHashCode(o); hashToObj.remove(hash); } @@ -132,4 +121,10 @@ frame.setVisible(true); } } + + + public void register(JS.TrapHolder o){} + public void unregister(JS.TrapHolder o){} + + public JS getMarker() { return null; } } Modified: branches/vexi3/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp =================================================================== --- branches/vexi3/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp 2014-05-10 14:21:51 UTC (rev 4695) @@ -361,6 +361,9 @@ // Instance Methods ///////////////////////////////////////////////////////////////////// + // FIX not right. Really we want the constructor to be showing, and it does by default + // if it exists, but need to consider the case if a template is not present (or indeed + // if that should be possible). public String coerceToString() { return "box$" + Integer.toHexString(hashCode()); } // FEATURE: use cx2/cy2 format @@ -3074,7 +3077,7 @@ private final void insertNode(int p, Box b) { if (bt == null) bt = new BasicTree(); bt.insertNode(p,b); } // self - private final int getIndexInParent() { return parent == null ? 0 : parent.indexNode(this); } + public final int getIndexInParent() { return parent == null ? 0 : parent.indexNode(this); } public boolean hasParent() { return parent!=null; } Modified: branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/Instr.java =================================================================== --- branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/Instr.java 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/Instr.java 2014-05-10 14:21:51 UTC (rev 4695) @@ -7,6 +7,7 @@ static public JS devl; static public Interpreter interpreter; + static public Compilation compilation; static public Debug debug; static public Memory memory; @@ -21,6 +22,14 @@ public void handle(org.ibex.js.Interpreter interpreter); } + static public interface Compilation{ + /** Called from the parser. Preserves local variable name information + * + * @param si - ScopeInfo, maps scope slots to variable names + */ + public abstract void putScopeInfo(ScopeInfo si); + } + /** * Provides a link for hooking in a debugger. For the implementation see org.vexi.debug. * <br> @@ -31,13 +40,9 @@ * */ - static public interface Debug extends Interpreter { + static public interface Debug extends Interpreter,Compilation { - /** Called from the parser. Preserves local variable name information - * - * @param si - ScopeInfo, maps scope slots to variable names - */ - public abstract void putScopeInfo(ScopeInfo si); + //// // Thread stuff @@ -55,6 +60,10 @@ static public interface Memory { public void register(JS o); public void unregister(JS o); + + public void register(JS.TrapHolder o); + public void unregister(JS.TrapHolder o); + public JS getMarker(); } Modified: branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/JSU.java =================================================================== --- branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/JSU.java 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/JSU.java 2014-05-10 14:21:51 UTC (rev 4695) @@ -163,7 +163,7 @@ return false; } - static public JS constructorsOf(JS arg){ + static public JSArray constructorsOf(JS arg){ JSArray r = new JSArray(); if(!(arg instanceof JS.Obj)) return r; for(ConstructorList l = ((JS.Obj)arg).constructors;l!=null;l=l.next){ @@ -338,8 +338,8 @@ /** lets us put multi-level get/put/call keys all in the same method */ static public class Sub extends JS.Obj { - final JS main; - final JS key; + final public JS main; + final public JS key; public Sub(JS main, JS key) { this.main = main; this.key = key; @@ -353,6 +353,10 @@ public JS callMethod(JS this_, JS method, JS[] args) throws JSExn { return main.callMethod(this_, JSU.S(JSU.toString(this.key) + "." + JSU.toString(method)), args); } + + @Override public String coerceToString() { + return main.coerceToString()+"."+key; + } } Modified: branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/parse/Parser.java =================================================================== --- branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/parse/Parser.java 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-library.js/src/main/java/org/ibex/js/parse/Parser.java 2014-05-10 14:21:51 UTC (rev 4695) @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.Map; +import org.ibex.js.Instr; import org.ibex.util.Basket; import org.ibex.util.SourceException; import org.ibex.util.Vec; @@ -169,12 +170,15 @@ // Local variable management Basket.Array scopeStack = new Basket.Array(); static public class ScopeInfo { + final public ScopeInfo parent; int base; int end; int newScopeInsn; public Map mapping = new HashMap(); - ScopeInfo(){} + ScopeInfo(ScopeInfo parent){ + this.parent = parent; + } // For the debugger. // When debuggin it is necessary to keep ScopeInfo as it is required to recover variable //names (from the scope slot integer). At runtime the information we have is the base and the end. @@ -185,6 +189,14 @@ public Function jsfunc; // JSFunc which it belongs to public int pc; // pc where scope was created + public void init(Function b, int i) { + jsfunc = b; + pc = i; + if(Instr.compilation!=null){ + Instr.compilation.putScopeInfo(this); + } + } + } //JS declaree = null; @@ -225,7 +237,7 @@ } void scopePush(Function b) { ScopeInfo prev = (ScopeInfo) scopeStack.peek(); - ScopeInfo si = new ScopeInfo(); + ScopeInfo si = new ScopeInfo(prev); si.base = prev.end; si.end = si.base; si.newScopeInsn = b.size; @@ -233,8 +245,7 @@ b.add(parserLine, NEWSCOPE); // Add info required for hashing ScopeInfo uniquely - si.jsfunc = b; - si.pc = b.size-1; + si.init(b, b.size-1); } void scopePop(Function b) { @@ -282,7 +293,7 @@ public Function parseScript() throws IOException{ Function ret = new Function(sourceName, line); scopeStack.clear(); - ScopeInfo si = new ScopeInfo(); + ScopeInfo si = new ScopeInfo(null); si.jsfunc = ret; scopeStack.push(si); scopePush(ret); Modified: branches/vexi3/org.vexi-library.js/src/main/jpp/org/ibex/js/JS.jpp =================================================================== --- branches/vexi3/org.vexi-library.js/src/main/jpp/org/ibex/js/JS.jpp 2014-05-10 14:07:32 UTC (rev 4694) +++ branches/vexi3/org.vexi-library.js/src/main/jpp/org/ibex/js/JS.jpp 2014-05-10 14:21:51 UTC (rev 4695) @@ -1165,7 +1165,17 @@ static final public class TrapHolder implements Trap { private final JS target, key, function; private Trap next; - public TrapHolder(JS t, JS k, JS f, Trap n) { target = t; key = k; function = f; next = n; } + public TrapHolder(JS t, JS k, JS f, Trap n) { + target = t; key = k; function = f; next = n; + if (Instr.memory!=null) { + Instr.memory.register(this); + } + } + protected void finalize() throws Throwable { + if (Instr.memory!=null) { + Instr.memory.unregister(this); + } + } public JS key() { return key; } public JS target() { return target; } public JS function() { return function; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce _______________________________________________ Vexi-svn mailing list Vexi-svn@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/vexi-svn