001 
002 /*
003  *  JScripter Emulation 1.0 - To Script Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package org.jscripter.emu.gc;
021 
022 import js.ArrayLike;
023 import js.Index;
024 import js.Js;
025 import js.ObjectLike;
026 import jsx.core.ArrayLikes;
027 import jsx.core.ObjectLikes;
028 
029 /**
030  * <p>An <tt>internal</tt> abstract base class for DOM-enabled depth-first-search object visitors 
031  * emulating garbage collection based finalization in JavaScript.</p>
032  * <p>This class is only used internally by JS re-compiler implementations.</p>
033  * 
034  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
035  * 
036  * @javascript This class is only loaded and resolved by re-compiler implementations.
037  */
038 public abstract class DFS extends GC
039 {
040     /**
041      * <p>A global identifier for a configurable property of an object.</p>
042      * <p>The identified configurable property of an object is a reference 
043      * to an integer number that indicates how many times the object has been visited
044      * by the current process of finalization.</p>
045      * @since 1.0
046      * @javascript Re-compilers must report error on end-users directly using this identifier.
047      */
048     protected final static Index<Integer> COUNT = new Index<Integer>("$DFS.COUNT");
049     /**
050      * <p>A global identifier for a configurable property of an object.</p>
051      * <p>The identified configurable property of an object is a reference 
052      * to an integer number that indicates how many lives the object currently has.</p>
053      * @since 1.0
054      * @javascript Re-compilers must report error on end-users directly using this identifier.
055      */
056     protected final static Index<Integer> LIVES = new Index<Integer>("$DFS.LIVES");
057     /**
058      * <p>A global identifier for a configurable property of an object.</p>
059      * <p>The identified configurable property of an object is a reference 
060      * to an integer number that indicates the time stamp of the last finalization
061      * process that visited the object.</p>
062      * @since 1.0
063      * @javascript Re-compilers must report error on end-users directly using this identifier.
064      */
065     protected final static Index<Integer> TIMES = new Index<Integer>("$DFS.TIMES");
066 
067     /**
068      * <p>Internally constructs an object visitor of this type.</p>
069      * @since 1.0
070      * @javascript Re-compilers must report error on end-users directly using this constructor.
071      */
072     protected DFS() {}
073 
074     /**
075      * <p>Internally traverses all children of an object.</p>
076      * @param o An object to traverse.
077      * @since 1.0
078      * @javascript Re-compilers must report error on end-users directly using this method.
079      */
080     @Override
081     public void traverse(ObjectLike o) {
082         if (GCDOM.isElement(o)) {
083             super.traverse(o);
084         }
085         ArrayLike<String> keys = Js.keys(o);
086         for (int i = 0, len = ArrayLikes.length(keys); i < len; i++) {
087             Object c = o.var(keys.get(i));
088             if (isObjectLike(c) && isAllocated((ObjectLike)c) && c != o &&
089                 (!GCDOM.isElement(o) || !GCDOM.isNode((ObjectLike)c)) &&
090                 isRelevant((ObjectLike)c)
091             ) {
092                 visit((ObjectLike)c);
093             }
094         }
095     }
096 
097     private static int times = 0;
098 
099     /**
100      * <p>Internally gets the time stamp of garbage collection based finalization.</p>
101      * @return A unique integer number that identifies a finalization process.
102      * @since 1.0
103      * @javascript Re-compilers must report error on end-users directly using this method.
104      */
105     protected static int times() {
106         return times;
107     }
108 
109     /**
110      * <p>Internally starts a garbage collection based finalization from an object.</p>
111      * @param o An object from where to start a new finalization process.
112      * @since 1.0
113      * @javascript Re-compilers must report error on end-users directly using this method.
114      */
115     public static final void start(ObjectLike o) {
116         times++;
117         new DFSMarker().visit(o);
118         ObjectLikes.inc(o, REFS);
119         new DFSSearcher().visit(o);
120         ObjectLikes.dec(o, REFS);
121         new DFSSweeper().visit(o);
122     }
123 }