upgrades to lexical soping implements to address some performance issues

fixes to HTML model to capture use of local vars as window state in scripts


git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4176 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
dolby-oss 2011-05-23 16:27:07 +00:00
parent 10849fcf78
commit 3e573a992d
26 changed files with 1523 additions and 494 deletions

View File

@ -83,5 +83,9 @@ public class AnonymousGenerics {
Ops hack = ops;
hack.unary("whatever");
hack.nullary();
hack = strQuadrupler;
hack.unary("whatever");
hack.nullary();
}
}

View File

@ -9,6 +9,7 @@ import com.ibm.wala.cast.js.html.DomLessSourceExtractor;
import com.ibm.wala.cast.js.html.IdentityUrlResolver;
import com.ibm.wala.cast.js.html.JSSourceExtractor;
import com.ibm.wala.cast.js.html.MappedSourceModule;
import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
import com.ibm.wala.cast.js.html.WebUtil;
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
@ -22,7 +23,7 @@ import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.util.CancelException;
public class JsViewerDriver {
public class JsViewerDriver extends Util {
public static void main(String args[]) throws ClassHierarchyException, IllegalArgumentException, IOException, CancelException {
if (args.length != 1){
@ -39,7 +40,7 @@ public class JsViewerDriver {
SourceModule[] sources = getSources(domless, url);
JSCFABuilder builder = Util.makeCGBuilder(sources, false);
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, false);
builder.setBaseURL(url);
CallGraph cg = builder.makeCallGraph(builder.getOptions());

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHackRhino.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE" value="/tmp/forinhack.out"/>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.6"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.ibm.wala.cast.js.test.TestForInLoopHackRhino"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.ibm.wala.cast.js.rhino.test"/>
</launchConfiguration>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPagesRhino.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE" value="/tmp/rhinojs.out"/>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.6"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.ibm.wala.cast.js.test.TestMozillaBugPagesRhino"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.ibm.wala.cast.js.rhino.test"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
</launchConfiguration>

View File

@ -0,0 +1,263 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>
<script>
(function top () {
var c = n.jQuery = n.$ = function dollar (a, d) {
return new c.fn.init(a, d)
}
c.fn = c.prototype = {
init: function init (a, d) {
a = a || document;
if (a.nodeType) {
this[0] = a;
this.length = 1;
this.context = a;
return this
}
if (typeof a === "string") {
var f = r.exec(a);
if (f && (f[1] || !d)) if (f[1]) a = c.clean([f[1]], d);
else {
if ((d = document.getElementById(f[3])) && d.id != f[3]) return c().find(a);
f = c(d || []);
f.context = document;
f.selector = a;
return f
} else return c(d).find(a)
} else if (c.isFunction(a)) return c(document).ready(a);
if (a.selector && a.context) {
this.selector =
a.selector;
this.context = a.context
}
return this.setArray(c.isArray(a) ? a : c.makeArray(a))
}
};
c.extend = c.fn.extend = function extend () {
var a =
arguments[0] || {},
d = 1,
f = arguments.length,
j = false,
q;
if (typeof a === "boolean") {
j = a;
a = arguments[1] || {};
d = 2
}
if (typeof a !== "object" && !c.isFunction(a)) a = {};
if (f == d) {
a = this;
--d
}
for (; d < f; d++) if ((q = arguments[d]) != null) for (var t in q) {
var y = a[t],
A = q[t];
if (a !== A) if (j && A && typeof A === "object" && !A.nodeType) a[t] = c.extend(j, y || (A.length != null ? [] : {}), A);
else if (A !== void 0) a[t] = A
}
return a
};
c.extend({
noConflict: function noConflict (a) {
n.$ =
B;
if (a) n.jQuery = w;
return c
},
isFunction: 2,
each: function each (a, d, f) {
var j, q = 0,
t = a.length;
if (f) if (t === void 0) for (j in a) {
if (d.apply(a[j], f) === false) break
} else for (; q < t;) {
if (d.apply(a[q++], f) === false) break
} else if (t === void 0) for (j in a) {
if (d.call(a[j], j, a[j]) === false) break
} else for (f = a[0]; q < t && d.call(f, q, f) !== false; f = a[++q]);
return a
},
className: {
add: function add (a, d) {
c.each((d || "").split(/\s+/), function (f, j) {
if (a.nodeType == 1 && !c.className.has(a.className, j)) a.className += (a.className ? " " : "") + j
})
},
remove: function remove (a, d) {
if (a.nodeType == 1) a.className = d !== void 0 ? c.grep(a.className.split(/\s+/), function (f) {
return !c.className.has(d, f)
}).join(" ") : ""
},
has: function has (a, d) {
return a && c.inArray(d, (a.className || a).toString().split(/\s+/)) > -1
}
},
swap: function swap (a, d, f) {
var j = {};
for (var q in d) {
j[q] = a.style[q];
a.style[q] = d[q]
}
f.call(a);
for (q in d) a.style[q] = j[q]
},
css: function css (a, d, f, j) {
if (d == "width" || d == "height") {
var q;
f = {
position: "absolute",
visibility: "hidden",
display: "block"
};
var t = d == "width" ? ["Left", "Right"] : ["Top", "Bottom"],
y = function () {
q = d == "width" ? a.offsetWidth : a.offsetHeight;
j !== "border" && c.each(t, function () {
j || (q -= parseFloat(c.curCSS(a, "padding" + this, true)) || 0);
if (j === "margin") q += parseFloat(c.curCSS(a, "margin" + this, true)) || 0;
else q -= parseFloat(c.curCSS(a, "border" + this + "Width", true)) || 0
})
};
a.offsetWidth !== 0 ? y() : c.swap(a, f, y);
return Math.max(0, Math.round(q))
}
return c.curCSS(a, d, f)
},
curCSS: function curCSS (a, d, f) {
var j, q = a.style;
if (d == "opacity" && !c.support.opacity) {
j = c.attr(q, "opacity");
return j == "" ? "1" : j
}
if (d.match(/float/i)) d = W;
if (!f && q && q[d]) j = q[d];
else if (F.getComputedStyle) {
if (d.match(/float/i)) d = "float";
d = d.replace(/([A-Z])/g, "-$1").toLowerCase();
if (a = F.getComputedStyle(a, null)) j = a.getPropertyValue(d);
if (d == "opacity" && j == "") j = "1"
} else if (a.currentStyle) {
j = d.replace(/\-(\w)/g, function (t, y) {
return y.toUpperCase()
});
j = a.currentStyle[d] || a.currentStyle[j];
if (!/^\d+(px)?$/i.test(j) && /^\d/.test(j)) {
d = q.left;
f = a.runtimeStyle.left;
a.runtimeStyle.left = a.currentStyle.left;
q.left = j || 0;
j = q.pixelLeft + "px";
q.left = d;
a.runtimeStyle.left = f
}
}
return j
},
clean: function clean (a, d, f) {
d = d || document;
if (typeof d.createElement === "undefined") d = d.ownerDocument || d[0] && d[0].ownerDocument || document;
if (!f && a.length === 1 && typeof a[0] === "string") {
var j = /^<(\w+)\s*\/?>$/.exec(a[0]);
if (j) return [d.createElement(j[1])]
}
c.each(a, function (y, A) {
if (typeof A === "number") A += "";
if (A) {
if (typeof A === "string") {
A = A.replace(/(<(\w+)[^>]*?)\/>/g, function (M, Q, S) {
return S.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? M : Q + "></" + S + ">"
});
y = A.replace(/^\s+/, "").substring(0, 10).toLowerCase();
var L = !y.indexOf("<opt") && [1, "<select multiple='multiple'>", "</select>"] || !y.indexOf("<leg") && [1, "<fieldset>", "</fieldset>"] || y.match(/^<(thead|tbody|tfoot|colg|cap)/) && [1, "<table>", "</table>"] || !y.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] || (!y.indexOf("<td") || !y.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] || !y.indexOf("<col") && [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"] || !c.support.htmlSerialize && [1, "div<div>", "</div>"] || [0, "", ""];
for (t.innerHTML = L[1] + A + L[2]; L[0]--;) t = t.lastChild;
if (!c.support.tbody) {
var N = /<tbody/i.test(A);
y = !y.indexOf("<table") && !N ? t.firstChild && t.firstChild.childNodes : L[1] == "<table>" && !N ? t.childNodes : [];
for (L = y.length - 1; L >= 0; --L) c.nodeName(y[L], "tbody") && !y[L].childNodes.length && y[L].parentNode.removeChild(y[L])
}!c.support.leadingWhitespace && /^\s/.test(A) && t.insertBefore(d.createTextNode(A.match(/^\s*/)[0]), t.firstChild);
A = c.makeArray(t.childNodes)
}
if (A.nodeType) q.push(A);
else q = c.merge(q, A)
}
});
if (f) {
for (a = 0; q[a]; a++) if (c.nodeName(q[a], "script") && (!q[a].type || q[a].type.toLowerCase() === "text/javascript")) j.push(q[a].parentNode ? q[a].parentNode.removeChild(q[a]) : q[a]);
else {
q[a].nodeType === 1 && q.splice.apply(q, [a + 1, 0].concat(c.makeArray(q[a].getElementsByTagName("script"))));
f.appendChild(q[a])
}
return j
}
return q
},
attr: function attr (a, d, f) {
if (!(!a || a.nodeType == 3 || a.nodeType == 8)) {
var j = !c.isXMLDoc(a),
q = f !== void 0;
d = j && c.props[d] || d;
if (a.tagName) {
var t = /href|src|style/.test(d);
if (d in a && j && !t) {
if (q) {
if (d == "type" && c.nodeName(a, "input") && a.parentNode) throw "type property can't be changed";
a[d] = f
}
if (c.nodeName(a, "form") && a.getAttributeNode(d)) return a.getAttributeNode(d).nodeValue;
if (d == "tabIndex") return (d = a.getAttributeNode("tabIndex")) && d.specified ? d.value : a.nodeName.match(/(button|input|object|select|textarea)/i) ? 0 : a.nodeName.match(/^(a|area)$/i) && a.href ? 0 : void 0;
return a[d]
}
if (!c.support.style && j && d == "style") return c.attr(a.style, "cssText", f);
q && a.setAttribute(d, "" + f);
a = !c.support.hrefNormalized && j && t ? a.getAttribute(d, 2) : a.getAttribute(d);
return a === null ? void 0 : a
}
if (!c.support.opacity && d == "opacity") {
if (q) {
a.zoom = 1;
a.filter = (a.filter || "").replace(/alpha\([^)]*\)/, "") + (parseInt(f) + "" == "NaN" ? "" : "alpha(opacity=" + f * 100 + ")")
}
return a.filter && a.filter.indexOf("opacity=") >= 0 ? parseFloat(a.filter.match(/opacity=([^)]*)/)[1]) / 100 + "" : ""
}
d = d.replace(/-([a-z])/ig, function (y, A) {
return A.toUpperCase()
});
if (q) a[d] = f;
return a[d]
}
},
makeArray: function makeArray (a) {
var d = [];
if (a != null) {
var f = a.length;
if (f == null || typeof a === "string" || c.isFunction(a) || a.setInterval) d[0] = a;
else for (; f;) d[--f] = a[f]
}
return d
},
inArray: function inArray (a, d) {
for (var f = 0, j = d.length; f < j; f++) if (d[f] === a) return f;
return -1
},
merge: function merge (a, d) {
var f = 0,
j, q = a.length;
if (c.support.getAll) for (;
(j = d[f++]) != null;) a[q++] = j;
else for (;
(j =
d[f++]) != null;) if (j.nodeType != 8) a[q++] = j;
return a
},
});
})();
</script>

View File

@ -0,0 +1,288 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>
<script>
(function top () {
var c = n.jQuery = n.$ = function dollar (a, d) {
return new c.fn.init(a, d)
}
c.fn = c.prototype = {
init: function init (a, d) {
a = a || document;
if (a.nodeType) {
this[0] = a;
this.length = 1;
this.context = a;
return this
}
if (typeof a === "string") {
var f = r.exec(a);
if (f && (f[1] || !d)) if (f[1]) a = c.clean([f[1]], d);
else {
if ((d = document.getElementById(f[3])) && d.id != f[3]) return c().find(a);
f = c(d || []);
f.context = document;
f.selector = a;
return f
} else return c(d).find(a)
} else if (c.isFunction(a)) return c(document).ready(a);
if (a.selector && a.context) {
this.selector =
a.selector;
this.context = a.context
}
return this.setArray(c.isArray(a) ? a : c.makeArray(a))
}
};
c.extend = c.fn.extend = function extend () {
var a =
arguments[0] || {},
d = 1,
f = arguments.length,
j = false,
q;
if (typeof a === "boolean") {
j = a;
a = arguments[1] || {};
d = 2
}
if (typeof a !== "object" && !c.isFunction(a)) a = {};
if (f == d) {
a = this;
--d
}
for (; d < f; d++)
if ((q = arguments[d]) != null) {
for (var t in q) {
(function _forin_body_1(t) {
var y = a[t],
A = q[t];
if (a !== A)
if (j && A && typeof A === "object" && !A.nodeType) a[t] = c.extend(j, y || (A.length != null ? [] : {}), A);
else if (A !== void 0) a[t] = A
})(t);
}
}
return a
};
c.extend({
noConflict: function noConflict (a) {
n.$ =
B;
if (a) n.jQuery = w;
return c
},
isFunction: 2,
each: function each (a, d, f) {
var j, q = 0,
t = a.length;
if (f) if (t === void 0) { for (j in a) {
if ((function _forin_body_2(j) {
if (d.apply(a[j], f) === false) return true;
else return false;
})(j)) {
break;
}
} } else for (; q < t;) {
if (d.apply(a[q++], f) === false) break
} else if (t === void 0) { for (j in a) {
if ((function _forin_body_3(j) {
if (d.call(a[j], j, a[j]) === false)
return true;
else
return false;
})(j)) {
break
}
}
} else for (f = a[0]; q < t && d.call(f, q, f) !== false; f = a[++q]);
return a
},
className: {
add: function add (a, d) {
c.each((d || "").split(/\s+/), function (f, j) {
if (a.nodeType == 1 && !c.className.has(a.className, j)) a.className += (a.className ? " " : "") + j
})
},
remove: function remove (a, d) {
if (a.nodeType == 1) a.className = d !== void 0 ? c.grep(a.className.split(/\s+/), function (f) {
return !c.className.has(d, f)
}).join(" ") : ""
},
has: function has (a, d) {
return a && c.inArray(d, (a.className || a).toString().split(/\s+/)) > -1
}
},
swap: function swap (a, d, f) {
var j = {};
for (var q in d) {
(function _forin_body_4(q) {
j[q] = a.style[q];
a.style[q] = d[q]
})(q);
}
f.call(a);
for (q in d) {
(function _forin_body_5(q) {
a.style[q] = j[q]
})(q);
}
},
css: function css (a, d, f, j) {
if (d == "width" || d == "height") {
var q;
f = {
position: "absolute",
visibility: "hidden",
display: "block"
};
var t = d == "width" ? ["Left", "Right"] : ["Top", "Bottom"],
y = function () {
q = d == "width" ? a.offsetWidth : a.offsetHeight;
j !== "border" && c.each(t, function () {
j || (q -= parseFloat(c.curCSS(a, "padding" + this, true)) || 0);
if (j === "margin") q += parseFloat(c.curCSS(a, "margin" + this, true)) || 0;
else q -= parseFloat(c.curCSS(a, "border" + this + "Width", true)) || 0
})
};
a.offsetWidth !== 0 ? y() : c.swap(a, f, y);
return Math.max(0, Math.round(q))
}
return c.curCSS(a, d, f)
},
curCSS: function curCSS (a, d, f) {
var j, q = a.style;
if (d == "opacity" && !c.support.opacity) {
j = c.attr(q, "opacity");
return j == "" ? "1" : j
}
if (d.match(/float/i)) d = W;
if (!f && q && q[d]) j = q[d];
else if (F.getComputedStyle) {
if (d.match(/float/i)) d = "float";
d = d.replace(/([A-Z])/g, "-$1").toLowerCase();
if (a = F.getComputedStyle(a, null)) j = a.getPropertyValue(d);
if (d == "opacity" && j == "") j = "1"
} else if (a.currentStyle) {
j = d.replace(/\-(\w)/g, function (t, y) {
return y.toUpperCase()
});
j = a.currentStyle[d] || a.currentStyle[j];
if (!/^\d+(px)?$/i.test(j) && /^\d/.test(j)) {
d = q.left;
f = a.runtimeStyle.left;
a.runtimeStyle.left = a.currentStyle.left;
q.left = j || 0;
j = q.pixelLeft + "px";
q.left = d;
a.runtimeStyle.left = f
}
}
return j
},
clean: function clean (a, d, f) {
d = d || document;
if (typeof d.createElement === "undefined") d = d.ownerDocument || d[0] && d[0].ownerDocument || document;
if (!f && a.length === 1 && typeof a[0] === "string") {
var j = /^<(\w+)\s*\/?>$/.exec(a[0]);
if (j) return [d.createElement(j[1])]
}
c.each(a, function (y, A) {
if (typeof A === "number") A += "";
if (A) {
if (typeof A === "string") {
A = A.replace(/(<(\w+)[^>]*?)\/>/g, function (M, Q, S) {
return S.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? M : Q + "></" + S + ">"
});
y = A.replace(/^\s+/, "").substring(0, 10).toLowerCase();
var L = !y.indexOf("<opt") && [1, "<select multiple='multiple'>", "</select>"] || !y.indexOf("<leg") && [1, "<fieldset>", "</fieldset>"] || y.match(/^<(thead|tbody|tfoot|colg|cap)/) && [1, "<table>", "</table>"] || !y.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] || (!y.indexOf("<td") || !y.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] || !y.indexOf("<col") && [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"] || !c.support.htmlSerialize && [1, "div<div>", "</div>"] || [0, "", ""];
for (t.innerHTML = L[1] + A + L[2]; L[0]--;) t = t.lastChild;
if (!c.support.tbody) {
var N = /<tbody/i.test(A);
y = !y.indexOf("<table") && !N ? t.firstChild && t.firstChild.childNodes : L[1] == "<table>" && !N ? t.childNodes : [];
for (L = y.length - 1; L >= 0; --L) c.nodeName(y[L], "tbody") && !y[L].childNodes.length && y[L].parentNode.removeChild(y[L])
}!c.support.leadingWhitespace && /^\s/.test(A) && t.insertBefore(d.createTextNode(A.match(/^\s*/)[0]), t.firstChild);
A = c.makeArray(t.childNodes)
}
if (A.nodeType) q.push(A);
else q = c.merge(q, A)
}
});
if (f) {
for (a = 0; q[a]; a++) if (c.nodeName(q[a], "script") && (!q[a].type || q[a].type.toLowerCase() === "text/javascript")) j.push(q[a].parentNode ? q[a].parentNode.removeChild(q[a]) : q[a]);
else {
q[a].nodeType === 1 && q.splice.apply(q, [a + 1, 0].concat(c.makeArray(q[a].getElementsByTagName("script"))));
f.appendChild(q[a])
}
return j
}
return q
},
attr: function attr (a, d, f) {
if (!(!a || a.nodeType == 3 || a.nodeType == 8)) {
var j = !c.isXMLDoc(a),
q = f !== void 0;
d = j && c.props[d] || d;
if (a.tagName) {
var t = /href|src|style/.test(d);
if (d in a && j && !t) {
if (q) {
if (d == "type" && c.nodeName(a, "input") && a.parentNode) throw "type property can't be changed";
a[d] = f
}
if (c.nodeName(a, "form") && a.getAttributeNode(d)) return a.getAttributeNode(d).nodeValue;
if (d == "tabIndex") return (d = a.getAttributeNode("tabIndex")) && d.specified ? d.value : a.nodeName.match(/(button|input|object|select|textarea)/i) ? 0 : a.nodeName.match(/^(a|area)$/i) && a.href ? 0 : void 0;
return a[d]
}
if (!c.support.style && j && d == "style") return c.attr(a.style, "cssText", f);
q && a.setAttribute(d, "" + f);
a = !c.support.hrefNormalized && j && t ? a.getAttribute(d, 2) : a.getAttribute(d);
return a === null ? void 0 : a
}
if (!c.support.opacity && d == "opacity") {
if (q) {
a.zoom = 1;
a.filter = (a.filter || "").replace(/alpha\([^)]*\)/, "") + (parseInt(f) + "" == "NaN" ? "" : "alpha(opacity=" + f * 100 + ")")
}
return a.filter && a.filter.indexOf("opacity=") >= 0 ? parseFloat(a.filter.match(/opacity=([^)]*)/)[1]) / 100 + "" : ""
}
d = d.replace(/-([a-z])/ig, function (y, A) {
return A.toUpperCase()
});
if (q) a[d] = f;
return a[d]
}
},
makeArray: function makeArray (a) {
var d = [];
if (a != null) {
var f = a.length;
if (f == null || typeof a === "string" || c.isFunction(a) || a.setInterval) d[0] = a;
else for (; f;) d[--f] = a[f]
}
return d
},
inArray: function inArray (a, d) {
for (var f = 0, j = d.length; f < j; f++) if (d[f] === a) return f;
return -1
},
merge: function merge (a, d) {
var f = 0,
j, q = a.length;
if (c.support.getAll) for (;
(j = d[f++]) != null;) a[q++] = j;
else for (;
(j =
d[f++]) != null;) if (j.nodeType != 8) a[q++] = j;
return a
},
});
})();
</script>

View File

@ -0,0 +1,33 @@
<HTML>
<TITLE>Welcome!</TITLE>
Hi
<SCRIPT>
var x = function _f1() {
};
function _f2(x) {
x();
}
_f2(window.x);
window.z = function _f3() {
};
function _f4(x) {
x();
}
_f4(z);
</SCRIPT>
<BR>
Welcome to our system
</HTML>

View File

@ -69,4 +69,46 @@ function outer( x ) {
return x+z;
}
function c2() {
}
function c3() {
}
function fa2(x) {
x();
}
function fa3(x) {
x();
}
function aa() {
var c1 = function _c1() {
}
var fa = function _fa1(x) {
x();
}
function bb(x) {
fa = x;
}
fa(c1);
bb(fa2);
fa(c2);
bb(fa3);
fa(c3);
}
var result = outer( 5 );
aa();

View File

@ -45,6 +45,24 @@ public class TestForInLoopHack extends TestJSCallGraphShape {
Util.dumpCG(builder.getPointerAnalysis(), CG);
}
@Test public void testJQueryWithHack() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/jquery_hacked.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url);
addHackedForInLoopSensitivity(builder);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG);
}
/*
@Test public void testJQueryEx1WithHack() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/jquery/ex1.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url);
addHackedForInLoopSensitivity(builder);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG);
}
*/
private static final Object[][] assertionsForBadForin = new Object[][] {
new Object[] { ROOT,
new String[] { "tests/badforin.js" } },

View File

@ -32,6 +32,7 @@ public abstract class TestMediawikiCallGraphShape extends TestJSCallGraphShape {
URL url = new URL("http://en.wikipedia.org/wiki/2009_swine_flu_outbreak");
CallGraph CG = Util.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForSwineFlu);
System.err.println(CG);
}
}

View File

@ -281,12 +281,31 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
Util.makeHTMLCG(url);
}
private static final Object[][] assertionsForWindowx = new Object[][] {
new Object[] { ROOT, new String[] { "windowx.html" } },
new Object[] { "windowx.html", new String[] { "windowx.html/__WINDOW_MAIN__" } },
new Object[] { "windowx.html/__WINDOW_MAIN__", new String[] { "windowx.html/__WINDOW_MAIN__/_f2", "windowx.html/__WINDOW_MAIN__/_f4" } },
new Object[] { "windowx.html/__WINDOW_MAIN__/_f2", new String[] { "windowx.html/__WINDOW_MAIN__/_f1" } },
new Object[] { "windowx.html/__WINDOW_MAIN__/_f4", new String[] { "windowx.html/__WINDOW_MAIN__/_f3" } }
};
@Test public void testWindowx() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/windowx.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForWindowx);
}
/*
@Test public void testJQuery() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/jquery.html");
CallGraph CG = Util.makeHTMLCG(url);
}
*/
/*
@Test public void testDojoTest() throws IllegalArgumentException, IOException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/dojo/test.html");
CallGraph CG = Util.makeHTMLCG(url);

View File

@ -19,6 +19,7 @@ import java.util.Set;
import junit.framework.Assert;
import com.ibm.wala.cast.js.html.MappedSourceModule;
import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
import com.ibm.wala.cast.js.html.WebUtil;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.ipa.callgraph.JSZeroOrOneXCFABuilder;
@ -77,7 +78,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
public static CallGraph makeScriptCG(SourceModule[] scripts, boolean useOneCFA) throws IOException, IllegalArgumentException,
CancelException {
PropagationCallGraphBuilder b = makeCGBuilder(scripts, useOneCFA);
PropagationCallGraphBuilder b = makeCGBuilder(makeLoaders(), scripts, useOneCFA);
CallGraph CG = b.makeCallGraph(b.getOptions());
dumpCG(b.getPointerAnalysis(), CG);
return CG;
@ -86,7 +87,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
public static JSCFABuilder makeHTMLCGBuilder(URL url) throws IOException {
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
Set<MappedSourceModule> script = WebUtil.extractScriptFromHTML(url);
JSCFABuilder builder = makeCGBuilder(script.toArray(new SourceModule[script.size()]), false);
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), script.toArray(new SourceModule[script.size()]), false);
builder.setBaseURL(url);
return builder;
}
@ -105,8 +106,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
return CG;
}
public static JSCFABuilder makeCGBuilder(SourceModule[] scripts, boolean useOneCFA) throws IOException {
JavaScriptLoaderFactory loaders = makeLoaders();
public static JSCFABuilder makeCGBuilder(JavaScriptLoaderFactory loaders, SourceModule[] scripts, boolean useOneCFA) throws IOException {
AnalysisScope scope = makeScope(scripts, loaders, JavaScriptLoader.JS);
return makeCG(loaders, scope, useOneCFA);
}

View File

@ -15,7 +15,7 @@ note_post_parameters = function notePostParameters(url) {
// hook for analysis of Web pages
};
function NamedNodeList() {
NamedNodeList = function NamedNodeList() {
var maxLength = 10;
var local = new Array(10);
var counter = -1;
@ -85,7 +85,7 @@ function NamedNodeList() {
}
}
function DOMNode() { // An impostor for the Node class
DOMNode = function DOMNode() { // An impostor for the Node class
this.childNodes = new NamedNodeList();
this.insertBefore = function insertBefore(newChild, refChild) {
this.childNodes.insertBefore(newChild, refChild);
@ -116,7 +116,7 @@ function DOMNode() { // An impostor for the Node class
}
}
function DOMDocument() {
DOMDocument = function DOMDocument() {
this.temp = DOMNode;
this.temp();
@ -137,11 +137,11 @@ function DOMDocument() {
};
}
function HTMLBody(){
HTMLBody = function HTMLBody(){
this.innerHTML = new String();
}
function DOMHTMLDocument() {
DOMHTMLDocument = function DOMHTMLDocument() {
this.temp = DOMDocument;
this.temp();
this.URL = new String();
@ -150,7 +150,7 @@ function DOMHTMLDocument() {
}
function Location(){
Location = function Location(){
this.host = new String();
this.hostname = new String();
this.href = new String();
@ -163,14 +163,14 @@ function Location(){
}
function DOMWindow(){
DOMWindow = function DOMWindow(){
this.name = new String();
this.open = function window_open(url, stuff) {
note_url(url);
};
}
function DOJOObj(){
DOJOObj = function DOJOObj(){
this.moduleUrl = function module_url(str1, str2){
return str1 + str2;
}
@ -194,7 +194,7 @@ window.XMLHttpRequest = XMLHttpRequest;
var dojo = new DOJOObj();
function DOMElement() { // An impostor for the Element class
DOMElement = function DOMElement() { // An impostor for the Element class
// inherits from Node
this.temp = DOMNode;
this.temp();
@ -215,7 +215,7 @@ function DOMElement() { // An impostor for the Element class
}
function DOMHTMLElement() { // An impostor for the HTMLElement class
DOMHTMLElement = function DOMHTMLElement() { // An impostor for the HTMLElement class
// inherits from Element
this.temp = DOMElement;
this.temp();
@ -234,7 +234,7 @@ function DOMHTMLElement() { // An impostor for the HTMLElement class
var dynamic_node = 0;
// Just a hack until all HTML elements have corresponding constructors
function DOMHTMLGenericElement(tagName) {
DOMHTMLGenericElement = function DOMHTMLGenericElement(tagName) {
// inherits from Element
this.temp = DOMHTMLElement;
this.temp();
@ -253,7 +253,7 @@ function DOMHTMLGenericElement(tagName) {
var formCount = 0;
function DOMHTMLFormElement() {
DOMHTMLFormElement = function DOMHTMLFormElement() {
// inherits from HTMLElement
this.temp = DOMHTMLElement;
this.temp();
@ -281,7 +281,7 @@ function DOMHTMLFormElement() {
this.target = null;
}
function DOMHTMLTableElement () {
DOMHTMLTableElement = function DOMHTMLTableElement () {
// inherits from HTMLElement
this.temp = DOMHTMLElement;
this.temp();

View File

@ -0,0 +1,91 @@
package com.ibm.wala.cast.js.html;
import com.ibm.wala.cast.ir.translator.TranslatorToIR;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.cast.js.ssa.JSInstructionFactory;
import com.ibm.wala.cast.js.translator.JSAstTranslator;
import com.ibm.wala.cast.js.translator.JavaScriptTranslatorFactory;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.cast.tree.impl.CAstOperator;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.ipa.cha.IClassHierarchy;
public class WebPageLoaderFactory extends JavaScriptLoaderFactory {
public WebPageLoaderFactory(JavaScriptTranslatorFactory factory) {
super(factory);
}
@Override
protected IClassLoader makeTheLoader(IClassHierarchy cha) {
return new JavaScriptLoader( cha, translatorFactory ) {
@Override
protected TranslatorToIR initTranslator() {
return new JSAstTranslator(this) {
private final CAst Ast = new CAstImpl();
private boolean isScriptBody(WalkContext context) {
return context.top().getName().equals( "__WINDOW_MAIN__" );
}
@Override
protected int doGlobalRead(CAstNode n, WalkContext context, String name) {
int result = context.currentScope().allocateTempValue();
if (isScriptBody(context) && ! "$$undefined".equals(name) && ! "window".equals(name)) {
// check if field is defined on 'window'
int windowVal = super.doLocalRead(context, "this");
int isDefined = context.currentScope().allocateTempValue();
context.currentScope().getConstantValue(name);
doIsFieldDefined(context, isDefined, windowVal, Ast.makeConstant(name));
context.cfg().addInstruction(
insts.ConditionalBranchInstruction(
translateConditionOpcode(CAstOperator.OP_NE),
null,
isDefined,
context.currentScope().getConstantValue(new Integer(0))));
PreBasicBlock srcB = context.cfg().getCurrentBlock();
// field lookup of value
context.cfg().newBlock(true);
context.cfg().addInstruction(((JSInstructionFactory) insts).GetInstruction(result, windowVal, name));
context.cfg().addInstruction(insts.GotoInstruction());
PreBasicBlock trueB = context.cfg().getCurrentBlock();
// read global
context.cfg().newBlock(false);
PreBasicBlock falseB = context.cfg().getCurrentBlock();
int sr = super.doGlobalRead(n, context, name);
context.cfg().addInstruction(((JSInstructionFactory) insts).AssignInstruction(result, sr));
// end
context.cfg().newBlock(true);
context.cfg().addEdge(trueB, context.cfg().getCurrentBlock());
context.cfg().addEdge(srcB, falseB);
return result;
} else {
return super.doGlobalRead(n, context, name);
}
}
@Override
protected void doLocalWrite(WalkContext context, String nm, int rval) {
if (isScriptBody(context)) {
int windowVal = super.doLocalRead(context, "this");
context.currentScope().getConstantValue(nm);
context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(windowVal, rval, nm));
}
super.doLocalWrite(context, nm, rval);
}
};
}
};
}
}

View File

@ -482,7 +482,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
IR sourceIR = getCFAContextInterpreter().getIR(caller);
SymbolTable sourceST = sourceIR.getSymbolTable();
IR targetIR = getCFAContextInterpreter().getIR(target);
SymbolTable targetST = targetIR.getSymbolTable();
@ -504,7 +504,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
// pass actual arguments to formals in the normal way
for (int i = 0; i < Math.min(paramCount, argCount); i++) {
int fn = targetST.getConstant(i);
InstanceKey[] fn = new InstanceKey[]{ getInstanceKeyForConstant(JavaScriptTypes.Number, i) };
PointerKey F = getTargetPointerKey(target, i);
if (constParams != null && constParams[i] != null) {
@ -528,7 +528,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
if (paramCount < argCount) {
if (av != -1) {
for (int i = paramCount; i < argCount; i++) {
int fn = targetST.getConstant(i);
InstanceKey[] fn = new InstanceKey[]{ getInstanceKeyForConstant(JavaScriptTypes.Number, i) };
if (constParams != null && constParams[i] != null) {
targetVisitor.newFieldWrite(target, av, fn, constParams[i]);
} else {
@ -554,8 +554,8 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
// write `length' in argument objects
if (av != -1) {
int svn = targetST.getConstant(argCount);
int lnv = targetST.getConstant("length");
InstanceKey[] svn = new InstanceKey[]{ getInstanceKeyForConstant(JavaScriptTypes.Number, argCount) };
InstanceKey[] lnv = new InstanceKey[]{ getInstanceKeyForConstant(JavaScriptTypes.String, "length") };
targetVisitor.newFieldWrite(target, av, lnv, svn);
}

View File

@ -10,6 +10,7 @@
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import com.ibm.wala.cast.ipa.callgraph.LexicalScopingResolverContexts;
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingKeysContextSelector;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
@ -42,6 +43,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder {
ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def);
contextSelector = new ScopeMappingKeysContextSelector(contextSelector);
contextSelector = new JavaScriptConstructorContextSelector(contextSelector);
contextSelector = new LexicalScopingResolverContexts(this, contextSelector);
if (doOneCFA) {
contextSelector = new nCFAContextSelector(1, contextSelector);
}

View File

@ -58,7 +58,7 @@ public class Util extends com.ibm.wala.cast.ipa.callgraph.Util {
* the translator factory to be used for analysis TODO: pass the factory where
* needed instead of using a global?
*/
private static JavaScriptTranslatorFactory translatorFactory;
protected static JavaScriptTranslatorFactory translatorFactory;
/**
* Set up the translator factory. This method should be called before invoking

View File

@ -21,7 +21,7 @@ import com.ibm.wala.types.ClassLoaderReference;
* Creates the single {@link IClassLoader class loader} used for JavaScript.
*/
public class JavaScriptLoaderFactory extends SingleClassLoaderFactory {
private final JavaScriptTranslatorFactory translatorFactory;
protected final JavaScriptTranslatorFactory translatorFactory;
public JavaScriptLoaderFactory(JavaScriptTranslatorFactory factory) {
this.translatorFactory = factory;

View File

@ -58,7 +58,7 @@ public class JSAstTranslator extends AstTranslator {
}
protected boolean treatGlobalsAsLexicallyScoped() {
return true;
return false;
}
protected boolean useLocalValuesForLexicalVars() {
@ -145,12 +145,7 @@ public class JSAstTranslator extends AstTranslator {
// force creation of these constants by calling the getter methods
symtab.getNullConstant();
symtab.getConstant("arguments");
symtab.getConstant("length");
for (int i = 0; i < 20; i++) {
symtab.getConstant(i);
}
((JavaScriptLoader) loader).defineCodeBodyCode("L" + fnName, cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, LI,
debugInfo);
}

View File

@ -17,6 +17,7 @@ import java.util.Set;
import com.ibm.wala.analysis.reflection.ReflectionContextInterpreter;
import com.ibm.wala.cast.ipa.callgraph.AstCallGraph.AstCGNode;
import com.ibm.wala.cast.ipa.callgraph.LexicalScopingResolverContexts.Resolver;
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys.ScopeMappingInstanceKey;
import com.ibm.wala.cast.ir.ssa.AbstractLexicalInvoke;
import com.ibm.wala.cast.ir.ssa.AstAssertInstruction;
@ -26,6 +27,7 @@ import com.ibm.wala.cast.ir.ssa.AstGlobalWrite;
import com.ibm.wala.cast.ir.ssa.AstIRFactory.AstIR;
import com.ibm.wala.cast.ir.ssa.AstInstructionVisitor;
import com.ibm.wala.cast.ir.ssa.AstIsDefinedInstruction;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
import com.ibm.wala.cast.ir.ssa.AstLexicalWrite;
@ -301,39 +303,30 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
return ((AstPointerKeyFactory) getBuilder().getPointerKeyFactory()).getPointerKeysForReflectedFieldWrite(I, F);
}
private void visitLexical(final LexicalOperator op) {
final PointerKey function = getPointerKeyForLocal(1);
if (contentsAreInvariant(symbolTable, du, 1)) {
op.doLexicalPointerKeys();
} else {
system.newSideEffect(op, function);
private void visitLexical(AstLexicalAccess instruction, final LexicalOperator op) {
op.doLexicalPointerKeys(false);
if (! checkLexicalInstruction(instruction)) {
system.newSideEffect(op, getPointerKeyForLocal(1));
}
// when a new caller is added for node, re-process the lexical access
class LexicalScopingCallback implements Function<Object, Object> {
public Object apply(Object ignore) {
op.doLexicalPointerKeys();
return null;
}
private LexicalOperator getOperator() {
return op;
}
public int hashCode() {
return op.hashCode();
}
public boolean equals(Object o) {
return (o instanceof LexicalScopingCallback) && ((LexicalScopingCallback) o).getOperator().equals(op);
}
}
((AstCGNode) node).addCallback(new LexicalScopingCallback());
}
public void visitAstLexicalRead(AstLexicalRead instruction) {
visitLexical(new LexicalOperator((AstCGNode) node, instruction.getAccesses(), true) {
private boolean checkLexicalInstruction(AstLexicalAccess instruction) {
Resolver r = (Resolver)node.getContext().get(LexicalScopingResolverContexts.RESOLVER);
if (r == null) {
return false;
} else {
for(Access a : instruction.getAccesses()) {
if (r.getLexicalSites(a) == null) {
return false;
}
}
}
return true;
}
public void visitAstLexicalRead(AstLexicalRead instruction) {
visitLexical(instruction, new LexicalOperator((AstCGNode) node, instruction.getAccesses(), true) {
protected void action(PointerKey lexicalKey, int vn) {
PointerKey lval = getPointerKeyForLocal(vn);
if (lexicalKey instanceof LocalPointerKey) {
@ -360,7 +353,7 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
}
public void visitAstLexicalWrite(AstLexicalWrite instruction) {
visitLexical(new LexicalOperator((AstCGNode) node, instruction.getAccesses(), false) {
visitLexical(instruction, new LexicalOperator((AstCGNode) node, instruction.getAccesses(), false) {
protected void action(PointerKey lexicalKey, int vn) {
PointerKey rval = getPointerKeyForLocal(vn);
if (contentsAreInvariant(symbolTable, du, vn)) {
@ -403,11 +396,10 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
} catch (UTFDataFormatException e) {
Assertions.UNREACHABLE();
}
int fieldNameVn = symtab.getConstant(fieldName);
final PointerKey objKey = getPointerKeyForLocal(objVn);
final InstanceKey[] fieldNameKeys = getInvariantContents(fieldNameVn);
final InstanceKey[] fieldNameKeys = new InstanceKey[]{ getInstanceKeyForConstant(fieldName) };
assert fieldNameKeys.length == 1;
if (contentsAreInvariant(symtab, du, objVn)) {
@ -539,12 +531,14 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
// callees where the name is not written;
// in such cases, the original value (rk) is preserved
PointerKey rk = getBuilder().getPointerKeyForLocal(node, r.valueNumber);
PointerKey wk = getBuilder().getPointerKeyForLocal(node, w.valueNumber);
if (contentsAreInvariant(symbolTable, du, r.valueNumber)) {
PointerKey wk = getBuilder().getPointerKeyForLocal(node, w.valueNumber);
if (contentsAreInvariant(node.getIR().getSymbolTable(), du, r.valueNumber)) {
system.recordImplicitPointsToSet(rk);
for (InstanceKey ik : getInvariantContents(r.valueNumber)) {
system.newConstraint(wk, ik);
}
final InstanceKey[] objKeys = getInvariantContents(r.valueNumber);
for (int i = 0; i < objKeys.length; i++) {
system.newConstraint(wk, objKeys[0]);
}
} else {
system.newConstraint(wk, assignOperator, rk);
}
@ -600,7 +594,8 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
* {@link AstConstraintVisitor#handleRootLexicalReference(String, String, CGNode)}
* .
*/
private void doLexicalPointerKeys() {
private void doLexicalPointerKeys(boolean funargsOnly) {
Resolver r = (Resolver)node.getContext().get(LexicalScopingResolverContexts.RESOLVER);
for (int i = 0; i < accesses.length; i++) {
final String name = accesses[i].variableName;
final String definer = accesses[i].variableDefiner;
@ -609,49 +604,31 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
if (AstTranslator.DEBUG_LEXICAL)
System.err.println(("looking up lexical parent " + definer));
for (Iterator<CGNode> DS = getLexicalDefiners(node, definer).iterator(); DS.hasNext();) {
final CGNode D = DS.next();
Iterator PS = new NumberedDFSDiscoverTimeIterator<CGNode>(getBuilder().getCallGraph(), node) {
/**
*
*/
private static final long serialVersionUID = 4546217460630659884L;
protected void visitEdge(CGNode callee, CGNode caller) {
CGNode from = (CGNode) caller;
CGNode to = (CGNode) callee;
for (Iterator SS = cg.getPossibleSites(from, to); SS.hasNext();) {
CallSiteReference site = (CallSiteReference) SS.next();
PointerKey V = isLoad ? getLocalReadKey(from, site, name, definer, D) : getLocalWriteKey(from, site, name,
definer, D);
Iterator<Pair<CallSiteReference,CGNode>> sites;
if (r != null && (sites = r.getLexicalSites(accesses[i])) != null) {
if (! funargsOnly) {
while(sites.hasNext()) {
Pair<CallSiteReference,CGNode> x = sites.next();
PointerKey V =
isLoad ? getLocalReadKey(x.snd, x.fst, name, definer) : getLocalWriteKey(x.snd, x.fst, name, definer);
if (V != null) {
action(V, vn);
}
}
}
protected Iterator<? extends CGNode> getConnected(CGNode n) {
if (n.equals(D))
return EmptyIterator.instance();
else
// traverse backwards
return G.getPredNodes(n);
}
};
while (PS.hasNext()) {
PS.next();
}
}
} else {
Set<CGNode> creators = getLexicalDefiners(node, Pair.make(name, definer));
for(CGNode n : creators) {
PointerKey funargKey = handleRootLexicalReference(name, definer, n);
action(funargKey, vn);
}
}
}
}
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
doLexicalPointerKeys();
doLexicalPointerKeys(true);
return NOT_CHANGED;
}
@ -699,7 +676,7 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
}
}
private Set<CGNode> getLexicalDefiners(final CGNode opNode, final String definer) {
private Set<CGNode> getLexicalDefiners(final CGNode opNode, final Pair<String,String> definer) {
if (definer == null) {
return Collections.singleton(getBuilder().getCallGraph().getFakeRootNode());
@ -716,7 +693,10 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
for (int f = 0; f < functionKeys.length; f++) {
system.findOrCreateIndexForInstanceKey(functionKeys[f]);
ScopeMappingInstanceKey K = (ScopeMappingInstanceKey) functionKeys[f];
result.add(K.getDefiningNode(definer));
Iterator<CGNode> x = K.getFunargNodes(definer);
while (x.hasNext()) {
result.add(x.next());
}
}
} else {
PointsToSetVariable FV = system.findOrCreatePointsToSet(F);
@ -726,7 +706,10 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
InstanceKey iKey = system.getInstanceKey(ptr);
if (iKey instanceof ScopeMappingInstanceKey) {
ScopeMappingInstanceKey K = (ScopeMappingInstanceKey) iKey;
result.add(K.getDefiningNode(definer));
Iterator<CGNode> x = K.getFunargNodes(definer);
while (x.hasNext()) {
result.add(x.next());
}
} else {
Assertions.UNREACHABLE("unexpected instance key " + iKey);
}
@ -842,163 +825,135 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
* now know the name is accessed by some transitive callee), thereby
* requiring marking of the IR as mutated.
*/
private PointerKey getLocalReadKey(CGNode n, CallSiteReference callSite, String name, String definer, CGNode definingNode) {
IMethod M = n.getMethod();
if (n == getBuilder().getCallGraph().getFakeRootNode()) {
return handleRootLexicalReference(name, definer, definingNode);
private PointerKey getLocalReadKey(CGNode n, CallSiteReference callSite, String name, String definer) {
AstIR ir = (AstIR) n.getIR();
int pc = callSite.getProgramCounter();
LexicalInformation L = ((AstIR) n.getIR()).lexicalInfo();
AbstractLexicalInvoke I = (AbstractLexicalInvoke) ir.getInstructions()[pc];
// find existing explicit lexical use
for (int i = I.getNumberOfParameters(); i <= I.getLastLexicalUse(); i++) {
Access A = I.getLexicalUse(i);
if (A.variableName.equals(name) && isEqual(A.variableDefiner, definer)) {
return getBuilder().getPointerKeyForLocal(n, A.valueNumber);
}
}
else if (M instanceof AstMethod) {
AstIR ir = (AstIR) n.getIR();
int pc = callSite.getProgramCounter();
LexicalInformation L = ((AstIR) n.getIR()).lexicalInfo();
// make new lexical use
int values[] = L.getExposedUses(pc);
Pair names[] = L.getExposedNames();
if (names != null && names.length > 0) {
for (int i = 0; i < names.length; i++) {
if (name.equals(names[i].fst) && isEqual(definer, names[i].snd)) {
if (values[i] == -1)
return null;
// some people have no lexical uses at all
if (L == null) {
return null;
}
I.addLexicalUse(new Access(name, definer, values[i]));
AbstractLexicalInvoke I = (AbstractLexicalInvoke) ir.getInstructions()[pc];
if (SSAConversion.DEBUG_UNDO)
System.err.println(("copy use #" + (-i - 1) + " to use #" + (I.getNumberOfUses() - 1) + " at inst " + pc));
// find existing explicit lexical use
for (int i = I.getNumberOfParameters(); i <= I.getLastLexicalUse(); i++) {
Access A = I.getLexicalUse(i);
if (A.variableName.equals(name) && isEqual(A.variableDefiner, definer)) {
return getBuilder().getPointerKeyForLocal(n, A.valueNumber);
SSAConversion.copyUse(ir, pc, -i - 1, pc, I.getNumberOfUses() - 1);
((AstCallGraph.AstCGNode) n).setLexicallyMutatedIR(ir);
return getBuilder().getPointerKeyForLocal(n, values[i]);
}
}
// make new lexical use
int values[] = L.getExposedUses(pc);
Pair names[] = L.getExposedNames();
if (names != null && names.length > 0) {
for (int i = 0; i < names.length; i++) {
if (name.equals(names[i].fst) && isEqual(definer, names[i].snd)) {
if (values[i] == -1)
return null;
I.addLexicalUse(new Access(name, definer, values[i]));
if (SSAConversion.DEBUG_UNDO)
System.err.println(("copy use #" + (-i - 1) + " to use #" + (I.getNumberOfUses() - 1) + " at inst " + pc));
SSAConversion.copyUse(ir, pc, -i - 1, pc, I.getNumberOfUses() - 1);
((AstCallGraph.AstCGNode) n).setLexicallyMutatedIR(ir);
return getBuilder().getPointerKeyForLocal(n, values[i]);
}
}
}
return null;
} else {
return null;
}
}
private PointerKey getLocalWriteKey(CGNode n, CallSiteReference callSite, String name, String definer, CGNode definingNode) {
IMethod M = n.getMethod();
if (n == getBuilder().getCallGraph().getFakeRootNode()) {
return handleRootLexicalReference(name, definer, definingNode);
}
else if (M instanceof AstMethod) {
AstMethod AstM = (AstMethod) M;
AstIR ir = (AstIR) n.getIR();
LexicalInformation L = ir.lexicalInfo();
return null;
// some people have no lexical uses at all
if (L == null)
return null;
}
int pc = callSite.getProgramCounter();
AbstractLexicalInvoke I = (AbstractLexicalInvoke) ir.getInstructions()[pc];
private PointerKey getLocalWriteKey(CGNode n, CallSiteReference callSite, String name, String definer) {
AstMethod AstM = (AstMethod) n.getMethod();;
AstIR ir = (AstIR) n.getIR();
LexicalInformation L = ir.lexicalInfo();
// find existing explicit lexical def
for (int i = 2; i < I.getNumberOfDefs(); i++) {
Access A = I.getLexicalDef(i);
if (A.variableName.equals(name) && isEqual(A.variableDefiner, definer)) {
return getBuilder().getPointerKeyForLocal(n, A.valueNumber);
}
int pc = callSite.getProgramCounter();
AbstractLexicalInvoke I = (AbstractLexicalInvoke) ir.getInstructions()[pc];
// find existing explicit lexical def
for (int i = 2; i < I.getNumberOfDefs(); i++) {
Access A = I.getLexicalDef(i);
if (A.variableName.equals(name) && isEqual(A.variableDefiner, definer)) {
return getBuilder().getPointerKeyForLocal(n, A.valueNumber);
}
}
// make new lexical def
int values[] = L.getExposedUses(pc);
Pair names[] = L.getExposedNames();
if (names != null && names.length > 0) {
for (int i = 0; i < names.length; i++) {
if (name.equals(names[i].fst) && isEqual(definer, names[i].snd)) {
if (values[i] == -1)
return null;
// make new lexical def
int values[] = L.getExposedUses(pc);
Pair names[] = L.getExposedNames();
if (names != null && names.length > 0) {
for (int i = 0; i < names.length; i++) {
if (name.equals(names[i].fst) && isEqual(definer, names[i].snd)) {
if (values[i] == -1)
return null;
// find calls that may be altered, and clear their caches
DefUse newDU = getAnalysisCache().getSSACache().findOrCreateDU(ir, n.getContext());
Iterator<SSAInstruction> insts = newDU.getUses(values[i]);
while (insts.hasNext()) {
SSAInstruction inst = insts.next();
if (inst instanceof SSAAbstractInvokeInstruction) {
System.err.println("clearing for " + inst);
CallSiteReference cs = ((SSAAbstractInvokeInstruction) inst).getCallSite();
((AstCallGraph.AstCGNode) n).clearMutatedCache(cs);
}
// find calls that may be altered, and clear their caches
DefUse newDU = getAnalysisCache().getSSACache().findOrCreateDU(ir, n.getContext());
Iterator<SSAInstruction> insts = newDU.getUses(values[i]);
while (insts.hasNext()) {
SSAInstruction inst = insts.next();
if (inst instanceof SSAAbstractInvokeInstruction) {
System.err.println("clearing for " + inst);
CallSiteReference cs = ((SSAAbstractInvokeInstruction) inst).getCallSite();
((AstCallGraph.AstCGNode) n).clearMutatedCache(cs);
}
}
// if values[i] was altered by copy propagation, we must undo
// that to ensure we do not bash the wrong value number in the
// the next steps.
SSAConversion.undoCopyPropagation(ir, pc, -i - 1);
// if values[i] was altered by copy propagation, we must undo
// that to ensure we do not bash the wrong value number in the
// the next steps.
SSAConversion.undoCopyPropagation(ir, pc, -i - 1);
// possibly new instruction due to renames, so get it again
I = (AbstractLexicalInvoke) ir.getInstructions()[pc];
// possibly new instruction due to renames, so get it again
I = (AbstractLexicalInvoke) ir.getInstructions()[pc];
// we assume that the callee might not necessarily write,
// so the call becomes like a phi node. hence it needs a
// read of the old value
ensureRead: {
for (int l = 0; l < I.getNumberOfUses(); l++) {
if (I.isLexicalUse(l)) {
Access r = I.getLexicalUse(l);
if (name.equals(r.variableName)) {
if (definer == null ? r.variableDefiner == null : definer.equals(r.variableDefiner)) {
break ensureRead;
}
// we assume that the callee might not necessarily write,
// so the call becomes like a phi node. hence it needs a
// read of the old value
ensureRead: {
for (int l = 0; l < I.getNumberOfUses(); l++) {
if (I.isLexicalUse(l)) {
Access r = I.getLexicalUse(l);
if (name.equals(r.variableName)) {
if (definer == null ? r.variableDefiner == null : definer.equals(r.variableDefiner)) {
break ensureRead;
}
}
}
I.addLexicalUse(new Access(name, definer, values[i]));
}
// add new lexical definition
I.addLexicalDef(new Access(name, definer, values[i]));
if (SSAConversion.DEBUG_UNDO)
System.err.println("new def of " + values[i] + " at inst " + pc + ": " + I);
// new def has broken SSA form for values[i], so fix for that
// value
MutableIntSet vs = IntSetUtil.make();
vs.add(values[i]);
SSAConversion.convert(AstM, ir, getOptions().getSSAOptions());
// force analysis to be redone
// TODO: only values[i] uses need to be re-done.
ir.lexicalInfo().handleAlteration();
((AstCallGraph.AstCGNode) n).setLexicallyMutatedIR(ir);
getAnalysisCache().getSSACache().invalidateDU(M, n.getContext());
getBuilder().markChanged(n);
// get SSA-renamed def from call site instruction
return getLocalWriteKey(n, callSite, name, definer, definingNode);
I.addLexicalUse(new Access(name, definer, values[i]));
}
// add new lexical definition
I.addLexicalDef(new Access(name, definer, values[i]));
if (SSAConversion.DEBUG_UNDO)
System.err.println("new def of " + values[i] + " at inst " + pc + ": " + I);
// new def has broken SSA form for values[i], so fix for that value
MutableIntSet vs = IntSetUtil.make();
vs.add(values[i]);
SSAConversion.convert(AstM, ir, getOptions().getSSAOptions());
// force analysis to be redone
// TODO: only values[i] uses need to be re-done.
ir.lexicalInfo().handleAlteration();
((AstCallGraph.AstCGNode) n).setLexicallyMutatedIR(ir);
getAnalysisCache().getSSACache().invalidateDU(AstM, n.getContext());
getBuilder().markChanged(n);
// get SSA-renamed def from call site instruction
return getLocalWriteKey(n, callSite, name, definer);
}
}
return null;
} else {
return null;
}
return null;
}
// /////////////////////////////////////////////////////////////////////////
@ -1074,74 +1029,10 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
system.recordImplicitPointsToSet(fieldKey);
InstanceKey[] fieldsKeys = getInvariantContents(symtab, du, opNode, fieldsVn);
for (int o = 0; o < objKeys.length; o++) {
PointerKey objCatalog = getPointerKeyForObjectCatalog(objKeys[o]);
for (int f = 0; f < fieldsKeys.length; f++) {
if (isLoadOperation) {
for (Iterator keys = getPointerKeysForReflectedFieldRead(objKeys[o], fieldsKeys[f]); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, true, true);
action.action(key);
}
} else {
if (objCatalog != null) {
system.newConstraint(objCatalog, fieldsKeys[f]);
}
for (Iterator keys = getPointerKeysForReflectedFieldWrite(objKeys[o], fieldsKeys[f]); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, true, true);
action.action(key);
}
}
}
}
newFieldOperationObjectAndFieldConstant(isLoadOperation, action, objKeys, fieldsKeys);
} else {
if (!isLoadOperation) {
for (int o = 0; o < objKeys.length; o++) {
PointerKey objCatalog = getPointerKeyForObjectCatalog(objKeys[o]);
if (objCatalog != null) {
system.newConstraint(objCatalog, assignOperator, fieldKey);
}
}
}
system.newSideEffect(new UnaryOperator<PointsToSetVariable>() {
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
final IntSetVariable fields = (IntSetVariable) rhs;
if (fields.getValue() != null) {
fields.getValue().foreach(new IntSetAction() {
public void act(int fptr) {
InstanceKey field = system.getInstanceKey(fptr);
for (int o = 0; o < objKeys.length; o++) {
for (Iterator keys = isLoadOperation ? getPointerKeysForReflectedFieldRead(objKeys[o], field)
: getPointerKeysForReflectedFieldWrite(objKeys[o], field); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, false, true);
action.action(key);
}
}
}
});
}
return NOT_CHANGED;
}
public int hashCode() {
return System.identityHashCode(this);
}
public boolean equals(Object o) {
return o == this;
}
public String toString() {
return "field op" + objVn + ", " + fieldsVn;
}
}, fieldKey);
newFieldOperationOnlyObjectConstant(isLoadOperation, action, fieldKey, objKeys);
}
} else {
@ -1149,101 +1040,10 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
system.recordImplicitPointsToSet(fieldKey);
final InstanceKey[] fieldsKeys = getInvariantContents(symtab, du, opNode, fieldsVn);
system.newSideEffect(new UnaryOperator<PointsToSetVariable>() {
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
final IntSetVariable objects = (IntSetVariable) rhs;
if (objects.getValue() != null) {
objects.getValue().foreach(new IntSetAction() {
public void act(int optr) {
InstanceKey object = system.getInstanceKey(optr);
PointerKey objCatalog = getPointerKeyForObjectCatalog(object);
for (int f = 0; f < fieldsKeys.length; f++) {
if (isLoadOperation) {
for (Iterator keys = getPointerKeysForReflectedFieldRead(object, fieldsKeys[f]); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, true, false);
action.action(key);
}
} else {
if (objCatalog != null) {
system.newConstraint(objCatalog, fieldsKeys[f]);
}
for (Iterator keys = getPointerKeysForReflectedFieldWrite(object, fieldsKeys[f]); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, true, false);
action.action(key);
}
}
}
}
});
}
return NOT_CHANGED;
}
public int hashCode() {
return System.identityHashCode(this);
}
public boolean equals(Object o) {
return o == this;
}
public String toString() {
return "field op" + objVn + ", " + fieldsVn;
}
}, objKey);
newFieldOperationOnlyFieldConstant(isLoadOperation, action, objKey, fieldsKeys);
} else {
system.newSideEffect(new AbstractOperator<PointsToSetVariable>() {
public byte evaluate(PointsToSetVariable lhs, final PointsToSetVariable[] rhs) {
final IntSetVariable receivers = (IntSetVariable) rhs[0];
final IntSetVariable fields = (IntSetVariable) rhs[1];
if (receivers.getValue() != null && fields.getValue() != null) {
receivers.getValue().foreach(new IntSetAction() {
public void act(int rptr) {
final InstanceKey receiver = system.getInstanceKey(rptr);
if (!isLoadOperation) {
PointerKey cat = getPointerKeyForObjectCatalog(receiver);
if (cat != null) {
system.newConstraint(cat, assignOperator, fieldKey);
}
}
fields.getValue().foreach(new IntSetAction() {
public void act(int fptr) {
InstanceKey field = system.getInstanceKey(fptr);
for (Iterator keys = isLoadOperation ? getPointerKeysForReflectedFieldRead(receiver, field)
: getPointerKeysForReflectedFieldWrite(receiver, field); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, false, false);
action.action(key);
}
}
});
}
});
}
return NOT_CHANGED;
}
public String toString() {
return "field op";
}
public boolean equals(Object o) {
return o == this;
}
public int hashCode() {
return System.identityHashCode(this);
}
}, objKey, fieldKey);
newFieldFullOperation(isLoadOperation, action, objKey, fieldKey);
}
}
@ -1251,6 +1051,210 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
System.err.println("finished\n");
}
}
protected void newFieldOperationFieldConstant(CGNode opNode,
final boolean isLoadOperation,
final ReflectedFieldAction action,
final int objVn,
final InstanceKey[] fieldsKeys)
{
IR ir = getBuilder().getCFAContextInterpreter().getIR(opNode);
SymbolTable symtab = ir.getSymbolTable();
DefUse du = getBuilder().getCFAContextInterpreter().getDU(opNode);
PointerKey objKey = getBuilder().getPointerKeyForLocal(opNode, objVn);
if (contentsAreInvariant(symtab, du, objVn)) {
system.recordImplicitPointsToSet(objKey);
InstanceKey[] objectKeys = getInvariantContents(symtab, du, opNode, objVn);
newFieldOperationObjectAndFieldConstant(isLoadOperation, action, objectKeys, fieldsKeys);
} else {
newFieldOperationOnlyFieldConstant(isLoadOperation, action, objKey, fieldsKeys);
}
}
private void newFieldFullOperation(final boolean isLoadOperation, final ReflectedFieldAction action, PointerKey objKey,
final PointerKey fieldKey) {
system.newSideEffect(new AbstractOperator<PointsToSetVariable>() {
public byte evaluate(PointsToSetVariable lhs, final PointsToSetVariable[] rhs) {
final IntSetVariable receivers = (IntSetVariable) rhs[0];
final IntSetVariable fields = (IntSetVariable) rhs[1];
if (receivers.getValue() != null && fields.getValue() != null) {
receivers.getValue().foreach(new IntSetAction() {
public void act(int rptr) {
final InstanceKey receiver = system.getInstanceKey(rptr);
if (!isLoadOperation) {
PointerKey cat = getPointerKeyForObjectCatalog(receiver);
if (cat != null) {
system.newConstraint(cat, assignOperator, fieldKey);
}
}
fields.getValue().foreach(new IntSetAction() {
public void act(int fptr) {
InstanceKey field = system.getInstanceKey(fptr);
for (Iterator keys = isLoadOperation ? getPointerKeysForReflectedFieldRead(receiver, field)
: getPointerKeysForReflectedFieldWrite(receiver, field); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, false, false);
action.action(key);
}
}
});
}
});
}
return NOT_CHANGED;
}
public String toString() {
return "field op";
}
public boolean equals(Object o) {
return o == this;
}
public int hashCode() {
return System.identityHashCode(this);
}
}, objKey, fieldKey);
}
private void newFieldOperationOnlyFieldConstant(final boolean isLoadOperation,
final ReflectedFieldAction action,
final PointerKey objKey,
final InstanceKey[] fieldsKeys)
{
system.newSideEffect(new UnaryOperator<PointsToSetVariable>() {
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
final IntSetVariable objects = (IntSetVariable) rhs;
if (objects.getValue() != null) {
objects.getValue().foreach(new IntSetAction() {
public void act(int optr) {
InstanceKey object = system.getInstanceKey(optr);
PointerKey objCatalog = getPointerKeyForObjectCatalog(object);
for (int f = 0; f < fieldsKeys.length; f++) {
if (isLoadOperation) {
for (Iterator keys = getPointerKeysForReflectedFieldRead(object, fieldsKeys[f]); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, true, false);
action.action(key);
}
} else {
if (objCatalog != null) {
system.newConstraint(objCatalog, fieldsKeys[f]);
}
for (Iterator keys = getPointerKeysForReflectedFieldWrite(object, fieldsKeys[f]); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, true, false);
action.action(key);
}
}
}
}
});
}
return NOT_CHANGED;
}
public int hashCode() {
return System.identityHashCode(this);
}
public boolean equals(Object o) {
return o == this;
}
public String toString() {
return "field op" + objKey;
}
}, objKey);
}
private void newFieldOperationOnlyObjectConstant(final boolean isLoadOperation,
final ReflectedFieldAction action,
final PointerKey fieldKey,
final InstanceKey[] objKeys)
{
if (!isLoadOperation) {
for (int o = 0; o < objKeys.length; o++) {
PointerKey objCatalog = getPointerKeyForObjectCatalog(objKeys[o]);
if (objCatalog != null) {
system.newConstraint(objCatalog, assignOperator, fieldKey);
}
}
}
system.newSideEffect(new UnaryOperator<PointsToSetVariable>() {
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
final IntSetVariable fields = (IntSetVariable) rhs;
if (fields.getValue() != null) {
fields.getValue().foreach(new IntSetAction() {
public void act(int fptr) {
InstanceKey field = system.getInstanceKey(fptr);
for (int o = 0; o < objKeys.length; o++) {
for (Iterator keys = isLoadOperation ? getPointerKeysForReflectedFieldRead(objKeys[o], field)
: getPointerKeysForReflectedFieldWrite(objKeys[o], field); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, false, true);
action.action(key);
}
}
}
});
}
return NOT_CHANGED;
}
public int hashCode() {
return System.identityHashCode(this);
}
public boolean equals(Object o) {
return o == this;
}
public String toString() {
return "field op" + fieldKey;
}
}, fieldKey);
}
private void newFieldOperationObjectAndFieldConstant(final boolean isLoadOperation, final ReflectedFieldAction action,
final InstanceKey[] objKeys, InstanceKey[] fieldsKeys) {
for (int o = 0; o < objKeys.length; o++) {
PointerKey objCatalog = getPointerKeyForObjectCatalog(objKeys[o]);
for (int f = 0; f < fieldsKeys.length; f++) {
if (isLoadOperation) {
for (Iterator keys = getPointerKeysForReflectedFieldRead(objKeys[o], fieldsKeys[f]); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, true, true);
action.action(key);
}
} else {
if (objCatalog != null) {
system.newConstraint(objCatalog, fieldsKeys[f]);
}
for (Iterator keys = getPointerKeysForReflectedFieldWrite(objKeys[o], fieldsKeys[f]); keys.hasNext();) {
AbstractFieldPointerKey key = (AbstractFieldPointerKey) keys.next();
if (DEBUG_PROPERTIES)
action.dump(key, true, true);
action.action(key);
}
}
}
}
}
public void newFieldWrite(CGNode opNode, int objVn, int fieldsVn, int rhsVn) {
IR ir = getBuilder().getCFAContextInterpreter().getIR(opNode);
@ -1265,46 +1269,61 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
}
}
public void newFieldWrite(CGNode opNode, int objVn, int fieldsVn, final InstanceKey[] rhsFixedValues) {
try {
private final class ConstantWriter implements ReflectedFieldAction {
private final InstanceKey[] rhsFixedValues;
private ConstantWriter(InstanceKey[] rhsFixedValues) {
this.rhsFixedValues = rhsFixedValues;
}
newFieldOperation(opNode, objVn, fieldsVn, false, new ReflectedFieldAction() {
public void dump(AbstractFieldPointerKey fieldKey, boolean constObj, boolean constProp) {
System.err.println(("writing fixed rvals to " + fieldKey + " " + constObj + ", " + constProp));
for (int i = 0; i < rhsFixedValues.length; i++) {
System.err.println(("writing " + rhsFixedValues[i]));
}
public void dump(AbstractFieldPointerKey fieldKey, boolean constObj, boolean constProp) {
System.err.println(("writing fixed rvals to " + fieldKey + " " + constObj + ", " + constProp));
for (int i = 0; i < rhsFixedValues.length; i++) {
System.err.println(("writing " + rhsFixedValues[i]));
}
}
public void action(AbstractFieldPointerKey fieldKey) {
if (!representsNullType(fieldKey.getInstanceKey())) {
for (int i = 0; i < rhsFixedValues.length; i++) {
system.findOrCreateIndexForInstanceKey(rhsFixedValues[i]);
system.newConstraint(fieldKey, rhsFixedValues[i]);
}
public void action(AbstractFieldPointerKey fieldKey) {
if (!representsNullType(fieldKey.getInstanceKey())) {
for (int i = 0; i < rhsFixedValues.length; i++) {
system.findOrCreateIndexForInstanceKey(rhsFixedValues[i]);
system.newConstraint(fieldKey, rhsFixedValues[i]);
}
}
}
});
} catch (RuntimeException e) {
System.err.println("error: " + e);
System.err.println(getBuilder().getCFAContextInterpreter().getIR(opNode));
throw e;
}
}
}
public void newFieldWrite(CGNode opNode, int objVn, int fieldsVn, final InstanceKey[] rhsFixedValues) {
newFieldOperation(opNode, objVn, fieldsVn, false, new ConstantWriter(rhsFixedValues));
}
public void newFieldWrite(CGNode opNode, int objVn, InstanceKey[] fieldKeys, final InstanceKey[] rhsValues) {
newFieldOperationFieldConstant(opNode, false, new ConstantWriter(rhsValues), objVn, fieldKeys);
}
private final class NormalWriter implements ReflectedFieldAction {
private final PointerKey rhs;
private NormalWriter(PointerKey rhs) {
this.rhs = rhs;
}
public void dump(AbstractFieldPointerKey fieldKey, boolean constObj, boolean constProp) {
System.err.println(("write " + rhs + " to " + fieldKey + " " + constObj + ", " + constProp));
}
public void action(AbstractFieldPointerKey fieldKey) {
if (!representsNullType(fieldKey.getInstanceKey())) {
system.newConstraint(fieldKey, assignOperator, rhs);
}
}
};
public void newFieldWrite(CGNode opNode, int objVn, int fieldsVn, final PointerKey rhs) {
newFieldOperation(opNode, objVn, fieldsVn, false, new ReflectedFieldAction() {
public void dump(AbstractFieldPointerKey fieldKey, boolean constObj, boolean constProp) {
System.err.println(("write " + rhs + " to " + fieldKey + " " + constObj + ", " + constProp));
}
newFieldOperation(opNode, objVn, fieldsVn, false, new NormalWriter(rhs));
}
public void action(AbstractFieldPointerKey fieldKey) {
if (!representsNullType(fieldKey.getInstanceKey())) {
system.newConstraint(fieldKey, assignOperator, rhs);
}
}
});
public void newFieldWrite(CGNode opNode, int objVn, InstanceKey[] fieldKeys, final PointerKey rhs) {
newFieldOperationFieldConstant(opNode, false, new NormalWriter(rhs), objVn, fieldKeys);
}
protected void newFieldRead(CGNode opNode, int objVn, int fieldsVn, int lhsVn) {

View File

@ -0,0 +1,220 @@
package com.ibm.wala.cast.ipa.callgraph;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.cast.loader.AstMethod.LexicalInformation;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextItem;
import com.ibm.wala.ipa.callgraph.ContextKey;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder;
import com.ibm.wala.util.collections.CompoundIterator;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.collections.MapIterator;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.functions.Function;
import com.ibm.wala.util.intset.IntSet;
public final class LexicalScopingResolverContexts implements ContextSelector {
public static final ContextKey RESOLVER = new ContextKey() {
public final String toString() {
return "Resolver Key";
}
};
public static class Resolver extends HashMap<Pair<String,String>, Object> implements ContextItem {
private final Map<Pair<String,String>,CGNode> funargKeys = new HashMap<Pair<String,String>,CGNode>();
private final Resolver parent;
private Resolver(Resolver parent) {
super(1);
this.parent = parent;
}
private static Iterator<Pair<CallSiteReference,CGNode>> getLexicalSitesRec(final Object x) {
if (x == null) {
return null;
} else if (x instanceof CGNode) {
return new MapIterator<CallSiteReference,Pair<CallSiteReference,CGNode>>(
((CGNode)x).iterateCallSites(),
new Function<CallSiteReference,Pair<CallSiteReference,CGNode>>() {
public Pair<CallSiteReference, CGNode> apply(CallSiteReference object) {
return Pair.make(object, (CGNode)x);
}
});
} else if (x instanceof Pair) {
return new NonNullSingletonIterator(x);
} else {
Iterator<Pair<CallSiteReference,CGNode>> result = EmptyIterator.instance();
Iterator<?> c = ((Collection<?>) x).iterator();
while(c.hasNext()) {
result = new CompoundIterator<Pair<CallSiteReference,CGNode>>(result, getLexicalSitesRec(c.next()));
}
return result;
}
}
private void add(Pair<String,String> name, Pair<CallSiteReference,CGNode> site) {
if (! containsKey(name)) {
put(name, site);
} else {
Object x = get(name);
if (! x.equals(site)) {
if (x instanceof Collection) {
((Collection)x).add(site);
} else {
Collection<Object> s = new HashSet<Object>(2);
s.add(x);
s.add(site);
put(name,s);
}
}
}
}
public Iterator<Pair<CallSiteReference,CGNode>> getLexicalSites(Pair<String,String> p) {
return getLexicalSitesRec(get(p));
}
public Iterator<Pair<CallSiteReference,CGNode>> getLexicalSites(Access a) {
return getLexicalSites(Pair.make(a.variableName, a.variableDefiner));
}
public void addFunarg(Pair<String,String> var, CGNode target) {
funargKeys.put(var, target);
}
public CGNode getFunarg(Pair<String,String> var) {
return funargKeys.get(var);
}
}
private class LexicalScopingResolverContext implements Context {
private final Resolver governingCallSites;
private final Context base;
public int hashCode() {
return governingCallSites==null? 1077651: governingCallSites.keySet().hashCode();
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (getClass().equals(o.getClass())) {
LexicalScopingResolverContext c = (LexicalScopingResolverContext)o;
return (base==null? c.base==null: base.equals(c.base))
&&
(governingCallSites.equals(c.governingCallSites));
} else {
return false;
}
}
public ContextItem get(ContextKey name) {
return name.equals(RESOLVER)? governingCallSites: base!=null? base.get(name): null;
}
private LexicalScopingResolverContext(Resolver governingCallSites, Context base) {
this.base = base;
this.governingCallSites = governingCallSites;
}
private LexicalScopingResolverContext(CGNode source, CallSiteReference callSite, Context base) {
Context srcContext = source.getContext();
Resolver srcResolver = (Resolver) srcContext.get(RESOLVER);
this.base = base;
this.governingCallSites = new Resolver(srcResolver);
if (source.getMethod() instanceof AstMethod) {
LexicalInformation LI = ((AstMethod)source.getMethod()).lexicalInfo();
int[] exposedUses = LI.getExposedUses(callSite.getProgramCounter());
int[] exposedExitUses = LI.getExitExposedUses();
if (exposedUses.length > 0) {
Pair<String,String> exposedNames[] = LI.getExposedNames();
for(int i = 0; i < exposedUses.length; i++) {
if (exposedUses[i] != -1) {
governingCallSites.add(exposedNames[i], Pair.make(callSite, source));
}
if (exposedExitUses[i] != -1) {
governingCallSites.addFunarg(exposedNames[i], source);
}
}
}
}
if (srcResolver != null) {
for(Pair<String,String> x : srcResolver.keySet()) {
Iterator<Pair<CallSiteReference,CGNode>> sites = srcResolver.getLexicalSites(x);
while (sites.hasNext()) {
governingCallSites.add(x, sites.next());
}
}
}
}
}
private final ContextSelector base;
private final PropagationCallGraphBuilder builder;
public LexicalScopingResolverContexts(PropagationCallGraphBuilder builder, ContextSelector base) {
this.base = base;
this.builder = builder;
}
private Context checkForRecursion(IMethod target, Resolver srcResolver) {
while (srcResolver != null) {
for(CGNode n : builder.getCallGraph().getNodes(target.getReference())) {
if (n.getContext().get(RESOLVER) == srcResolver) {
return n.getContext();
}
}
srcResolver = srcResolver.parent;
}
return null;
}
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) {
Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters);
Resolver resolver = (Resolver)caller.getContext().get(RESOLVER);
Context recursiveParent = checkForRecursion(callee, resolver);
if (recursiveParent != null) {
return recursiveParent;
}
if (caller.getMethod() instanceof AstMethod
&&
((AstMethod)caller.getMethod()).lexicalInfo().getExposedUses(site.getProgramCounter()).length > 0)
{
return new LexicalScopingResolverContext(caller, site, baseContext);
}
else if (resolver != null) {
return new LexicalScopingResolverContext(resolver, baseContext);
}
else {
return baseContext;
}
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
return base.getRelevantParameters(caller, site);
}
}

View File

@ -34,7 +34,7 @@ public class LexicalScopingSSAContextInterpreter extends AstContextInsensitiveSS
}
}
return getAnalysisCache().getSSACache().findOrCreateIR(node.getMethod(), node.getContext(), options.getSSAOptions());
return super.getIR(node);
}
public DefUse getDU(CGNode node) {
@ -45,7 +45,7 @@ public class LexicalScopingSSAContextInterpreter extends AstContextInsensitiveSS
}
}
return getAnalysisCache().getSSACache().findOrCreateDU(node.getMethod(), node.getContext(), options.getSSAOptions());
return super.getDU(node);
}
}

View File

@ -10,10 +10,9 @@
*****************************************************************************/
package com.ibm.wala.cast.ipa.callgraph;
import java.util.HashMap;
import java.util.Iterator;
import com.ibm.wala.cast.ir.translator.AstTranslator;
import com.ibm.wala.cast.ipa.callgraph.LexicalScopingResolverContexts.Resolver;
import com.ibm.wala.cast.loader.AstMethod.LexicalParent;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.NewSiteReference;
@ -21,11 +20,14 @@ import com.ibm.wala.classLoader.ProgramCounter;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.graph.impl.GraphInverter;
import com.ibm.wala.util.graph.traverse.DFS;
import com.ibm.wala.util.collections.CompoundIterator;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.intset.OrdinalSet;
/**
* An {@link InstanceKeyFactory} that returns {@link ScopeMappingInstanceKey}s
@ -33,12 +35,6 @@ import com.ibm.wala.util.graph.traverse.DFS;
*/
abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
/**
* return all {@link LexicalParent}s of methods represented by base (a single
* method for JavaScript, all instance methods in Java).
*/
protected abstract LexicalParent[] getParents(InstanceKey base);
/**
* does base require a scope mapping key? Typically, true if base is allocated
* in a nested lexical scope
@ -76,47 +72,16 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
*/
private final CGNode creator;
/**
* mapping from lexical parent names to the corresponding CGNodes
*/
private final HashMap<String, CGNode> scopeMap;
/**
* compute the {@link CGNode} correspond to each specified
* {@link LexicalParent} of {@link #base}, populating {@link #scopeMap}
*
*/
private void computeLexicalParentCGNodes() {
if (AstTranslator.DEBUG_LEXICAL)
System.err.println(("starting search for parents at " + creator));
final LexicalParent[] parents = getParents(base);
Iterator<CGNode> preds = DFS.iterateDiscoverTime(GraphInverter.invert(builder.getCallGraph()), creator);
int toDo = parents.length;
while (preds.hasNext()) {
CGNode pred = preds.next();
for (int i = 0; i < parents.length; i++) {
if (parents[i] != null) {
if (pred.getMethod() == parents[i].getMethod()) {
if (scopeMap.containsKey(parents[i].getName()))
assert scopeMap.get(parents[i].getName()) == pred;
else {
toDo--;
scopeMap.put(parents[i].getName(), pred);
if (AstTranslator.DEBUG_LEXICAL)
System.err.println(("Adding lexical parent " + parents[i].getName() + " for " + base + " at " + creator
+ "(toDo is now " + toDo + ")"));
}
}
}
}
}
}
private ScopeMappingInstanceKey(CGNode creator, InstanceKey base) {
this.creator = creator;
this.base = base;
this.scopeMap = HashMapFactory.make();
computeLexicalParentCGNodes();
}
public IClass getConcreteType() {
@ -128,8 +93,26 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
* @param definer
* @return
*/
CGNode getDefiningNode(String definer) {
return scopeMap.get(definer);
Iterator<CGNode> getFunargNodes(Pair<String,String> name) {
Iterator<CGNode> result = EmptyIterator.instance();
Resolver r = (Resolver)creator.getContext().get(LexicalScopingResolverContexts.RESOLVER);
if (r != null) {
CGNode def = r.getFunarg(name);
if (def != null) {
result = new NonNullSingletonIterator<CGNode>(def);
}
}
PointerKey funcKey = builder.getPointerKeyForLocal(creator, 1);
OrdinalSet<InstanceKey> funcPtrs = builder.getPointerAnalysis().getPointsToSet(funcKey);
for(InstanceKey x : funcPtrs) {
if (x instanceof ScopeMappingInstanceKey) {
result = new CompoundIterator<CGNode>(result, ((ScopeMappingInstanceKey)x).getFunargNodes(name));
}
}
return result;
}
public int hashCode() {
@ -146,10 +129,10 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
}
}
public InstanceKey getInstanceKeyForAllocation(CGNode node, NewSiteReference allocation) {
InstanceKey base = basic.getInstanceKeyForAllocation(node, allocation);
public InstanceKey getInstanceKeyForAllocation(CGNode creatorNode, NewSiteReference allocationSite) {
InstanceKey base = basic.getInstanceKeyForAllocation(creatorNode, allocationSite);
if (base != null && needsScopeMappingKey(base)) {
return new ScopeMappingInstanceKey(node, base);
return new ScopeMappingInstanceKey(creatorNode, base);
} else {
return base;
}

View File

@ -461,9 +461,13 @@ public class SSAConversion extends AbstractSSAConversion {
int[] exitLive = lexicalInfo.getExitExposedUses();
BitVector v = new BitVector();
if (exitLive != null)
for (int i = 0; i < exitLive.length; i++)
v.set(exitLive[i]);
if (exitLive != null) {
for (int i = 0; i < exitLive.length; i++) {
if (exitLive[i] > -1) {
v.set(exitLive[i]);
}
}
}
this.liveness = LiveAnalysis.perform(CFG, symtab, v);
if (DEBUG) {
@ -514,7 +518,7 @@ public class SSAConversion extends AbstractSSAConversion {
int[] exitLives = lexicalInfo.getExitExposedUses();
if (exitLives != null) {
for (int i = 0; i < exitLives.length; i++) {
if (!skip(exitLives[i])) {
if (exitLives[i] != -1 && !skip(exitLives[i])) {
assert !S[exitLives[i]].isEmpty();
exitLives[i] = top(exitLives[i]);
}

View File

@ -2245,11 +2245,15 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
}
}
private int[] buildLexicalUseArray(Pair<Pair<String, String>, Integer>[] exposedNames) {
private int[] buildLexicalUseArray(Pair<Pair<String, String>, Integer>[] exposedNames, String entityName) {
if (exposedNames != null) {
int[] lexicalUses = new int[exposedNames.length];
for (int j = 0; j < exposedNames.length; j++) {
lexicalUses[j] = exposedNames[j].snd;
if (entityName == null || entityName.equals(exposedNames[j].fst.snd)) {
lexicalUses[j] = exposedNames[j].snd;
} else {
lexicalUses[j] = -1;
}
}
return lexicalUses;
@ -2273,7 +2277,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
}
@SuppressWarnings("unchecked")
AstLexicalInformation(Scope scope, SSAInstruction[] instrs, Set<Pair<Pair<String, String>, Integer>> exposedNamesSet,
AstLexicalInformation(String entityName, Scope scope, SSAInstruction[] instrs, Set<Pair<Pair<String, String>, Integer>> exposedNamesSet,
Set<Access> accesses) {
Pair<Pair<String, String>, Integer>[] EN = null;
if (exposedNamesSet != null) {
@ -2285,12 +2289,12 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
// the value numbers stored in exitLexicalUses and instructionLexicalUses
// are identical at first; they will be updated
// as needed during the final SSA conversion
this.exitLexicalUses = buildLexicalUseArray(EN);
this.exitLexicalUses = buildLexicalUseArray(EN, entityName);
this.instructionLexicalUses = new int[instrs.length][];
for (int i = 0; i < instrs.length; i++) {
if (instrs[i] instanceof SSAAbstractInvokeInstruction) {
this.instructionLexicalUses[i] = buildLexicalUseArray(EN);
this.instructionLexicalUses[i] = buildLexicalUseArray(EN, null);
}
}
@ -2330,8 +2334,10 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
return exitLexicalUses;
}
private static final int[] NONE = new int[0];
public int[] getExposedUses(int instructionOffset) {
return instructionLexicalUses[instructionOffset];
return instructionLexicalUses[instructionOffset]==null? NONE: instructionLexicalUses[instructionOffset];
}
public IntSet getAllExposedUses() {
@ -2339,7 +2345,9 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
allExposedUses = IntSetUtil.make();
if (exitLexicalUses != null) {
for (int i = 0; i < exitLexicalUses.length; i++) {
allExposedUses.add(exitLexicalUses[i]);
if (exitLexicalUses[i] > 0) {
allExposedUses.add(exitLexicalUses[i]);
}
}
}
if (instructionLexicalUses != null) {
@ -2765,7 +2773,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
// (put here to allow subclasses to handle stuff in scoped entities)
// assemble lexical information
patchLexicalAccesses(cfg.getInstructions(), accesses.get(n));
AstLexicalInformation LI = new AstLexicalInformation((AbstractScope) functionContext.currentScope(), cfg.getInstructions(),
AstLexicalInformation LI = new AstLexicalInformation(getEntityName(n), (AbstractScope) functionContext.currentScope(), cfg.getInstructions(),
exposedNames.get(n), accesses.get(n));
DebuggingInformation DBG = new AstDebuggingInformation(n.getPosition(), line, nms);

View File

@ -48,7 +48,7 @@ public abstract class AstMethod implements IMethod {
public IntSet getAllExposedUses();
public Pair[] getExposedNames();
public Pair<String, String>[] getExposedNames();
public String[] getScopingParents();
@ -141,7 +141,7 @@ public abstract class AstMethod implements IMethod {
* methods containing state possibly referenced lexically in this
* method
*/
public abstract class LexicalParent {
public static abstract class LexicalParent {
public abstract String getName();
public abstract AstMethod getMethod();