/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.visage.runtime;
/** Each DepChain is a linked list of Deps for a given bindeeVarNum.
* In addition, a DepChain may have two child DepChains that are
* organized as a binary trie.
*/
public class DepChain implements BinderLinkable {
int bindeeVarNum;
/** The lowest power of 2 such that {@code nextBit > bindeeVarNum}.
* If {@code child0 != null}, then {@code child0.nextBit > this.nextBit}.
* If {@code child1 != null}, then {@code child1.nextBit > this.nextBit}.
*/
int nextBit;
/** The chain of dependencies for the given bindeeVarNum. */
Dep dependencies;
/** Children that have the same varNum prefix string.
* We view varNum as a bit-string in little-endian order.
* For all p such that p is child0 or a descendant of child0,
* we have that {@code (p.varNum & nextBit) == 0} and {@code p.varNum & (nextBit-1) == varNum}.
* Likewise, for all p such that p is child1 or a descendant of child1,
* we have that {@code (p.varNum & nextBit) != 0} and {@code p.varNum & (nextBit-1) == varNum}.
*/
DepChain child0, child1;
Object /*union<DepChain,WeakBinderRef>*/ parent;
public void setNextBinder(Dep next) {
dependencies = next;
}
/** Find the DepChain for the given varNum, or return null if not found. */
public static DepChain find(int varNum, DepChain cur) {
for (;;) {
if (cur == null)
return null;
int curVarNum = cur.bindeeVarNum;
if (varNum == curVarNum)
return cur;
int curBit = cur.nextBit;
int mask = curBit-1;
if ((varNum & mask) != (curVarNum & mask))
return null;
cur = (varNum & curBit) == 0 ? cur.child0 : cur.child1;
}
}
/** Find the DepChain for the given varNum, or create it if not found. */
public static DepChain findForce(int varNum, DepChain cur, WeakBinderRef bindee) {
Object parent = bindee;
// If selector==-1 then cur == ((WeakBinderRef) parent).get().getDepChain$internal$()
// If selector==0 then cur == ((DepChain) parent).child0.
// If selector==1 then cur == ((DepChain) parent).child1.
int selector = -1;
for (;;) {
if (cur == null)
break;
int curVarNum = cur.bindeeVarNum;
if (varNum == curVarNum)
return cur;
int curBit = cur.nextBit;
int mask = curBit-1;
if ((varNum & mask) != curVarNum) {
DepChain p = new DepChain();
int nextBit = 1;
while ((varNum & nextBit) == (curVarNum & nextBit) &&
nextBit <= varNum)
nextBit <<= 1;
p.bindeeVarNum = varNum & (nextBit-1);
p.nextBit = nextBit;
replace(parent, selector, p);
if ((curVarNum & nextBit) == 0) {
p.child0 = cur;
selector = 1;
} else {
p.child1 = cur;
selector = 0;
}
p.parent = parent;
cur.parent = p;
if (p.bindeeVarNum == varNum)
return p;
parent = p;
break;
}
parent = cur;
if ((varNum & curBit) == 0) {
selector = 0;
cur = cur.child0;
}
else {
selector = 1;
cur = cur.child1;
}
}
cur = new DepChain();
cur.bindeeVarNum = varNum;
cur.parent = parent;
int nextBit = 1;
while (nextBit <= varNum)
nextBit <<= 1;
cur.nextBit = nextBit;
DepChain old = replace(parent, selector, cur);
if (old != null) {
if ((old.bindeeVarNum & nextBit) == 0)
cur.child0 = old;
else
cur.child1 = old;
}
return cur;
}
/** Replace parent.selector by dep, returning old value. */
private static DepChain replace(Object parent, int selector, DepChain dep) {
DepChain old = null;
if (selector == -1) {
WeakBinderRef wref = (WeakBinderRef) parent;
VisageObject visageObj = wref.get();
// FIXME : do we need this null check here?
if (visageObj != null) {
old = visageObj.getDepChain$internal$();
visageObj.setDepChain$internal$(dep);
}
}
else {
DepChain pchain = (DepChain) parent;
if (selector == 0) {
old = pchain.child0;
pchain.child0 = dep;
} else {
old = pchain.child1;
pchain.child1 = dep;
}
}
return old;
}
/** Replace this.parent by replacement. */
void replaceParent(DepChain replacement) {
if (parent instanceof WeakBinderRef) {
VisageObject obj = ((WeakBinderRef)parent).get();
// FIXME : do we need this null check here?
if (obj != null) {
obj.setDepChain$internal$(replacement);
}
} else {
DepChain pchain = (DepChain) parent;
if (pchain.child0 == this)
pchain.child0 = replacement;
if (pchain.child1 == this)
pchain.child1 = replacement;
}
}
/* DEBUGGING:
static int counter;
int id = ++counter;
public String toString() { return "DepChain#"+id+"-vn:"+bindeeVarNum; }
public static String xtoString(DepChain d) {
if (d==null) return "null";
return "DepChain[#"+d.id+"-vn:"+d.bindeeVarNum+" nB:"+d.nextBit+" ch0: "+xtoString(d.child0)+" ch1: "+xtoString(d.child1)
+" p:"+d.parent+" d:"+xstr(d.dependencies)+"]";
}
public static String xstr(Dep d) {
if (d == null)
return "";
if (d.nextInBinders==null) return ""+d;
return ""+d+" "+xstr(d.nextInBinders);
}
*/
}