Initial contribution of core script analysis code

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@622 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
dolby-oss 2007-02-02 17:25:09 +00:00
parent 5be4678a6e
commit d8f21f8ee5
51 changed files with 6832 additions and 0 deletions

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="source"/>
<classpathentry kind="src" path="dat"/>
<classpathentry exported="true" kind="lib" path="lib/js.jar"/>
<classpathentry exported="true" kind="lib" path="lib/xalan.jar"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1 @@
bin

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.ibm.wala.cast.js</name>
<comment></comment>
<projects>
<project>JavaScript</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,4 @@
output.js.jar = bin/
bin.includes = plugin.xml,\
lib/js.jar,\
lib/xalan.jar

43
com.ibm.wala.cast.js/build.xml Executable file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
=======================================================================
DOMO JavaScript Core build file
=======================================================================
-->
<project name="com.ibm.domo.js" default="jar" basedir=".">
<!-- Software version details -->
<property name="name" value="domojscore" />
<property name="module_name" value="com.ibm.domo.js" />
<property name="Name" value="DOMO JavaScript Core" />
<property name="version" value="1-alpha" />
<!-- Compilation switches -->
<property name="debug" value="true" />
<property name="deprecation" value="false" />
<property name="optimize" value="true" />
<property name="javacFailOnError" value="true" />
<property name="javacDebugInfo" value="on" />
<property name="javacVerbose" value="false" />
<!-- Set global properties for this build -->
<property name="src" value="source" />
<property name="dat" value="dat" />
<property name="build" value="build" />
<property name="build.result" value="${basedir}" />
<property name="build.tests" value="${basedir}" />
<property name="build.javadocs" value="${build}/javadocs" />
<property name="publish.javadocs" value="javadocs/com.ibm.domo.js" />
<property name="dist" value="dist" />
<property name="etc" value="etc" />
<property name="docs" value="docs" />
<property name="lib" value="lib" />
<property name="mainlib" value="../mainlib" />
<property name="sharedlib" value="../sharedlib" />
<property name="cvsroot" value="/gsa/watgsa/home/d/o/dolby/cvs/JTD"/>
<import file="${sharedlib}/scripts/common-targets.xml"/>
</project>

View File

@ -0,0 +1,102 @@
// the internal primitive mechanism
primitive = new Primitives();
// core definitions needed to make anything work, even what follows
Object = primitive("NewObject");
Function = primitive("NewFunction");
Array = primitive("NewArray");
String = primitive("NewString");
Number = primitive("NewNumber");
RegExp = primitive("NewRegExp");
/************************************************************************/
/* Global properties, see spec 15.1 */
/************************************************************************/
undefined = primitive("NewUndefined");
eval = function eval (x) {
return primitive("GlobalEval", x);
};
parseInt = function parseInt (string, radix) {
return primitive("GlobalParseInt", string, radix);
};
parseFloat = function parseFloat (string) {
return primitive("GlobalParseFloat", string);
};
isNaN = function isNaN (number) {
return primitive("GlobalIsNaN", number)
};
isFinite = function isFinite (number) {
return primitive("GlobalIsFinite", number);
};
decodeURI = primitive("GlobalDecodeURI");
decodeURIComponent = primitive("GlobalDecodeURIComponent");
encodeURI = primitive("GlobalEncodeURI");
encodeURIComponent = primitive("GlobalEncodeURIComponent");
/************************************************************************/
/* Object properties, see spec 15.2 */
/************************************************************************/
Object.prototype = {
prototype: null,
constructor: Object,
toString: function toString() {
return primitive("ObjectToString", this);
},
toLocaleString: function toLocaleString() {
return primitive("ObjectToLocaleString", this);
},
valueOf: function valueOf() { return this },
hasOwnProperty: function hasOwnProperty (V) {
return primitive("ObjectHasOwnProperty", this, V);
},
isPrototypeOf: function isPrototypeOf (V) {
return primitive("ObjectIsPrototypeOf", this, V);
},
propertyIsEnumerable: function propertyIsEnumerable (V) {
return primitive("ObjectPropertyIsEnumerable", this, V);
}
};
/************************************************************************/
/* Function properties, see spec 15.3 */
/************************************************************************/
Function.prototype = {
constructor: Function,
toString: function functionToString() {
return primitive("FunctionToString", this);
},
apply: function functionApply (thisArg, argArray) {
return primitive("FunctionApply", this, thisArg, argArray);
},
call: function functionCall (thisArg) {
arguments.shift();
return primitive("FunctionApply", this, thisArg, arguments);
}
};

View File

@ -0,0 +1,246 @@
// The following stuff has to be statically analyzed
// 1. readonly attributes
// 2. using setAttribute to register an event handler (this should be disallowed since it can be used like 'eval')
// 3. All methods properties assigned here are implicitly readonly
// 4. inheritance in this file is implemented by creating a new object for the prototype. Instead, the prototype object could be shared
// A combination of interfaces NodeList, NamedNodeMap, HTMLCollection
function NamedNodeList() {
var maxLength = 10;
var local = new Array(10);
var counter = -1;
function add(elem) {
checkAndIncrease();
local[counter++] = elem;
}
function getIndex(elem) {
for(var traverse = 0; traverse <= counter; traverse++) {
if(local[traverse] == elem) {
return traverse;
}
}
return -1;
}
function remove(elem) {
var found = getIndex(elem);
if(found > -1) {
for(traverse = found; traverse < counter; traverse++) {
local[traverse] = local[traverse+1];
}
counter--;
}
}
function replace(newElem, oldElem) {
var found = getIndex(oldElem);
if(found > -1) {
local[found] = newElem;
}
}
function insertBefore(newElem, oldElem) {
var found = getIndex(oldElem);
if(found > -1) {
checkAndIncrease();
var prev = newElem;
for(var traverse = counter + 1; traverse > found; traverse--) {
local[traverse] = local[traverse-1];
}
local[found] = newElem;
}
}
var checkAndIncrease = function() {
if(counter >= maxLength - 1) {
maxLength += 10;
var temp = new Array(maxLength);
for(traverse = 0; traverse <= counter; traverse++) {
temp[traverse] = local[traverse];
}
local = temp;
}
}
// implement a list of Nodes, accessible through names as well
}
function DOMNode() { // An impostor for the Node class
this.attributes = new NamedNodeList();
this.childNodes = new NamedNodeList();
this.insertBefore = function(newChild, refChild) {
this.childNodes.insertBefore(newChild, refChild);
}
this.replaceChild = function(newChild, oldChild) {
this.childNodes.replace(newChild, oldChild);
}
this.removeChild = function(oldChild) {
this.childNodes.remove(oldChild);
}
this.appendChild = function(newChild) {
this.childNodes.add(newChild);
newChild.parentNode = this;
}
this.hasChildNodes = function() {
return this.childNodes.hasElements();
}
this.ownerDocument = document;
}
function DOMDocument() {
this.prototype = new DOMNode();
this.createElement = function(name) {
// TODO : to be implemented accurately
var toReturn = new DOMHTMLGenericElement(name);
return toReturn;
}
}
function DOMHTMLDocument() {
this.prototype = new DOMDocument();
this.getElementsByName = function(name) {
// get the node in the tree with name attribute == name
}
}
// Creating the root document object
var document = new DOMHTMLDocument();
function DOMElement() { // An impostor for the Element class
// inherits from Node
this.prototype = new DOMNode();
// The get/set/remove attribute methods cannot be run using 'onclick','onmouseover', 'on...' kind of arguments for name.
// since that would be used as a workaround for eval
this.getAttribute = function(name) {
this.attributes.get(name);
}
this.setAttribute = function(name, value) {
this.attributes.set(name, value);
}
this.removeAttribute = function(name) {
this.attributes.remove(name);
}
this.getElementsByTagName = function(name) {
var toReturn = new NamedNodeList();
}
}
function DOMHTMLElement() { // An impostor for the HTMLElement class
// inherits from Element
this.prototype = new DOMElement();
// Set HTML Attribute Defaults
this.id = null;
this.title = null;
this.lang = null;
this.dir = null;
this.className = null;
// Set Javascript properties
this.getAttribute = function(name) {
if(name == "id") return this.id;
else if(name == "title") return this.title;
else if(name == "lang") return this.lang;
else if(name == "dir") return this.dir;
else if(name == "class") return this.className;
else return this.attributes.get(name);
}
this.setAttribute = function(name, value) {
if(name == "id") this.id = value;
else if(name == "title") this.title = value;
else if(name == "lang") this.lang = value;
else if(name == "dir") this.dir = value;
else if(name == "class") this.className = value;
else return this.attributes.set(name, value);
}
this.removeAttribute = function(name) {
if(name == "id") this.id = null;
else if(name == "title") this.title = null;
else if(name == "lang") this.lang = null;
else if(name == "dir") this.dir = null;
else if(name == "class") this.className = null;
else return this.attributes.remove(name);
}
}
// Just a hack until all HTML elements have corresponding constructors
function DOMHTMLGenericElement(tagName) {
// inherits from Element
this.prototype = new DOMElement();
// Set just the tag name
this.nodeName = tagName;
this.nodeValue = null;
}
function DOMHTMLFormElement() {
// inherits from HTMLElement
this.prototype = new DOMHTMLElement();
// Set Javascript properties
this.nodeName = "FORM";
this.elements = new NamedNodeList();
this.length = function() {
return this.elements.length;
}
this.submit = function() {
}
this.reset = function() {
}
// Set HTML Attribute Defaults
this.name = null;
this.acceptCharset = "UNKNOWN";
this.action = null;
this.enctype = "application/x-www-form-urlencoded";
this.method = "get";
this.target = null;
// Set Javascript properties
this.getAttribute = function(name) {
if(name == "name") return this.name;
else if(name == "accept-charset") return this.acceptCharset;
else if(name == "action") return this.action;
else if(name == "enctype") return this.enctype;
else if(name == "method") return this.method;
else if(name == "target") return this.target;
else return this.prototype.getAttribute(name);
}
this.setAttribute = function(name, value) {
if(name == "name") this.name = value;
else if(name == "accept-charset") this.acceptCharset = value;
else if(name == "action") this.action = value;
else if(name == "enctype") this.enctype = value;
else if(name == "method") this.method = value;
else if(name == "target") this.target = value;
else return this.prototype.setAttribute(name, value);
}
this.removeAttribute = function(name) {
if(name == "name") this.name = null;
else if(name == "accept-charset") this.acceptCharset = null;
else if(name == "action") this.action = null;
else if(name == "enctype") this.enctype = null;
else if(name == "method") this.method = null;
else if(name == "target") this.target = null;
else return this.prototype.removeAttribute(name);
}
}
function DOMHTMLTableElement () {
// inherits from HTMLElement
this.prototype = new DOMHTMLElement();
this.rows = function() {
}
}

View File

@ -0,0 +1,389 @@
// the internal primitive mechanism
primitive = new Primitives();
// core definitions needed to make anything work, even what follows
Object = primitive("NewObject");
Function = primitive("NewFunction");
Array = primitive("NewArray");
String = primitive("NewString");
Number = primitive("NewNumber");
RegExp = primitive("NewRegExp");
/************************************************************************/
/* Global properties, see spec 15.1 */
/************************************************************************/
NaN = primitive("GlobalNaN");
Infinity = primitive("GlobalInfinity");
undefined = primitive("NewUndefined");
eval = function eval (x) {
return primitive("GlobalEval", x);
};
parseInt = function parseInt (string, radix) {
return primitive("GlobalParseInt", string, radix);
};
parseFloat = function parseFloat (string) {
return primitive("GlobalParseFloat", string);
};
isNaN = function isNaN (number) {
return primitive("GlobalIsNaN", number)
};
isFinite = function isFinite (number) {
return primitive("GlobalIsFinite", number);
};
decodeURI = primitive("GlobalDecodeURI");
decodeURIComponent = primitive("GlobalDecodeURIComponent");
encodeURI = primitive("GlobalEncodeURI");
encodeURIComponent = primitive("GlobalEncodeURIComponent");
/************************************************************************/
/* Object properties, see spec 15.2 */
/************************************************************************/
Object.prototype = {
prototype: null,
constructor: Object,
toString: function toString() {
return primitive("ObjectToString", this);
},
toLocaleString: function toLocaleString() {
return primitive("ObjectToLocaleString", this);
},
valueOf: function valueOf() { return this },
hasOwnProperty: function hasOwnProperty (V) {
return primitive("ObjectHasOwnProperty", this, V);
},
isPrototypeOf: function isPrototypeOf (V) {
return primitive("ObjectIsPrototypeOf", this, V);
},
propertyIsEnumerable: function propertyIsEnumerable (V) {
return primitive("ObjectPropertyIsEnumerable", this, V);
}
};
/************************************************************************/
/* Function properties, see spec 15.3 */
/************************************************************************/
Function.prototype = {
constructor: Function,
toString: function functionToString() {
return primitive("FunctionToString", this);
},
apply: function functionApply (thisArg, argArray) {
return primitive("FunctionApply", this, thisArg, argArray);
},
call: function functionCall (thisArg) {
arguments.shift();
return primitive("FunctionApply", this, thisArg, arguments);
}
};
/************************************************************************/
/* Array properties, see spec 15.4 */
/************************************************************************/
Array.prototype = {
prototype: Object.prototype,
constructor: Array,
toString: function arrayToString () {
return this.join(",");
},
toLocaleString: function arrayToLocalString () {
var result = "";
var limit = this.length;
for(var k = 0; k < limit; k++) {
result = result.concat( this[k].toLocaleString() );
result = result.concat( "," );
}
return result;
},
concat: function concat () {
var result = new Array();
var n = 0;
for(var i = 0; i < this.length; i++)
result[n++] = this[i];
for(i = 0; i < arguments.length; i++)
for(var j = 0; j < arguments[i].length; j++)
result[n++] = arguments[i][j];
result.length = n;
return result;
},
join: function join (separator) {
var result = "";
var limit = this.length;
for(var k = 0; k < limit; k++) {
result = result.concat( this[k].toString() );
result = result.concat( separator );
}
return result;
},
pop: function pop () {
return this[ --this.length ];
},
push: function push () {
var n = this.length
for(var i = 0; i < arguments.length; i++) {
this[ n++ ] = arguments[i];
}
this.length = n;
return n;
},
reverse: function reverse () {
var n = this.length;
for (var k = 0; k < (n/2); k++) {
var tmp = this[k];
this[k] = this[n-k];
this[n-k] = tmp;
}
return this;
},
shift: function shift () {
var result = this[ 0 ];
for(var i = 0; i < this.length-1; i++)
this[i] = this[i+1];
this.length--;
return result;
},
slice: function slice (start, end) {
var j = 0;
if (start < 0) start = this.length + start;
if (end < 0) end = this.length + end;
var result = new Array();
for(var i = start; i < end; i++)
result[j++] = this[i];
result.length = j;
return result;
},
sort: function sort (fn) {
for(var l = 0; i < this.length; l++) {
var mindex = l;
for(var i = l; i < this.length; i++) {
if (fn(this[mindex], this[i]) < 0) {
mindex = i;
}
}
if (mindex != l) {
var tmp = this[l];
this[l] = this[mindex];
this[mindex] = this[l];
}
}
}
};
/************************************************************************/
/* String properties, see spec 15.4 */
/************************************************************************/
String.prototype = {
prototype: Object.prototype,
constructor: String,
$value: "",
toString: function stringToString() {
return this.$value;
},
valueOf: function stringValueOf() {
return this.$value;
},
charAt: function stringCharAt(pos) {
return new String(primitive("StringCharAt", pos));
},
charCodeAt: function stringCharCodeAt(pos) {
return new Number(primitive("StringCharCodeAt", pos));
},
toUpperCase: function toUpperCase() {
return new String(primitive("StringToUpperCase", this));
},
toLocaleUpperCase: function toLocaleUpperCase() {
return new String(primitive("StringToLocaleUpperCase", this));
},
toLowerCase: function toLowerCase() {
return new String(primitive("StringToLowerCase", this));
},
toLocaleLowerCase: function toLocaleLowerCase() {
return new String(primitive("StringToLocaleLowerCase", this));
},
indexOf: function indexOf(str) {
return new Number(primitive("StringIndexOf", this, str));
},
split: function stringSplit(separator, limit) {
var y = primitive("splitCount", this, separator, limit);
var x = new Array(y);
for(var i = 0; i < y; i++) {
x[i] = new String( primitive("splitNth", this, separator, limit, i) );
}
return x;
},
substring: function substring(from, to) {
return new String(primitive("StringSubString", this, from, to));
}
};
/************************************************************************/
/* Number properties, see spec 15.7 */
/************************************************************************/
Number.prototype = {
prototype: Object.prototype,
constructor: Number,
$value: 0
};
/************************************************************************/
/* Math properties, see spec 15.8 */
/************************************************************************/
Math = {
E: primitive("MathE"),
LN10: primitive("MathLN10"),
LN2: primitive("MathLN2"),
LOG2E: primitive("MathLOG2E"),
LOG10E: primitive("MathLOG10E"),
PI: primitive("PI"),
SQRT1_2: primitive("MathSQRT1_2"),
SQRT2: primitive("MathSQRT2"),
abs: function abs (x) { return (x<0)? -x: x; },
acos: function acos (x) { return primitive("MathACos", x); },
asin: function asin (x) { return primitive("MathASin", x); },
atan: function atan (x) { return primitive("MathATan", x); },
atan2: function atan2 (y, x) { return primitive("MathATan2", y, x); },
ceil: function ceil (x) { return primitive("MathCeil", x); },
cos: function cos (x) { return primitive("MathCos", x); },
exp: function exp (x) { return primitive("MathExp", x); },
floor: function floor (x) { return primitive("MathFloor", x); },
log: function log (x) { return primitive("MathLog", x); },
max: function max () {
var i = -Infinity;
for(var j = 0; j < arguments.length; j++)
if (arguments[j] > i)
i = arguments[j];
return i;
},
min: function min () {
var i = Infinity;
for(var j = 0; j < arguments.length; j++)
if (arguments[j] < i)
i = arguments[j];
return i;
},
pow: function pow (x, y) { return primitive("MathPow", x, y); },
random: function random() { return primitive("MathRandom"); },
round: function round (x) { return primitive("MathRound", x); },
sin: function sin (x) { return primitive("MathSin", x); },
sqrt: function sqrt (x) { return primitive("MathSqrt", x);},
tan: function tan (x) { return primitive("MathTan", x); }
};
/************************************************************************/
/* RegExp properties, see spec 15.10 */
/************************************************************************/
RegExp.prototype = {
prototype: Object.prototype,
constructor: RegExp
};

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin
id="com.ibm.domo.js"
name="JavaScript Plug-in"
version="1.0.0"
provider-name="IBM"
class="com.ibm.wala.cast.js.JavaScriptPlugin">
<runtime>
<library name="lib/js.jar">
<export name="*"/>
</library>
<library name="lib/xalan.jar">
<export name="*"/>
</library>
</runtime>
<requires>
<import plugin="org.eclipse.core.runtime"/>
<import plugin="com.ibm.wala.cast"/>
<import plugin="com.ibm.wala.core"/>
</requires>
</plugin>

View File

@ -0,0 +1,85 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.eclipse.core.runtime.Plugin;
import org.osgi.framework.BundleContext;
/**
* The main plugin class to be used in the desktop.
*/
public class JavaScriptPlugin extends Plugin {
//The shared instance.
private static JavaScriptPlugin plugin;
//Resource bundle.
private ResourceBundle resourceBundle;
/**
* The constructor.
*/
public JavaScriptPlugin() {
super();
plugin = this;
}
/**
* This method is called upon plug-in activation
*/
public void start(BundleContext context) throws Exception {
super.start(context);
}
/**
* This method is called when the plug-in is stopped
*/
public void stop(BundleContext context) throws Exception {
super.stop(context);
plugin = null;
resourceBundle = null;
}
/**
* Returns the shared instance.
*/
public static JavaScriptPlugin getDefault() {
return plugin;
}
/**
* Returns the string from the plugin's resource bundle,
* or 'key' if not found.
*/
public static String getResourceString(String key) {
ResourceBundle bundle = JavaScriptPlugin.getDefault().getResourceBundle();
try {
return (bundle != null) ? bundle.getString(key) : key;
} catch (MissingResourceException e) {
return key;
}
}
/**
* Returns the plugin's resource bundle,
*/
public ResourceBundle getResourceBundle() {
try {
if (resourceBundle == null)
resourceBundle = ResourceBundle.getBundle("com.ibm.domo.js.JavaScriptPluginResources");
} catch (MissingResourceException x) {
resourceBundle = null;
}
return resourceBundle;
}
}

View File

@ -0,0 +1,80 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.analysis.typeInference;
import com.ibm.wala.fixpoint.IVariable;
import com.ibm.wala.analysis.typeInference.*;
import com.ibm.wala.cast.analysis.typeInference.AstTypeInference;
import com.ibm.wala.cast.js.ssa.*;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ssa.*;
import com.ibm.wala.types.TypeReference;
public class JSTypeInference extends AstTypeInference {
public JSTypeInference(IR ir, ClassHierarchy cha) {
super(ir, cha, true);
}
protected void initialize() {
class JSTypeOperatorFactory
extends AstTypeOperatorFactory
implements com.ibm.wala.cast.js.ssa.InstructionVisitor
{
public void visitJavaScriptInvoke(JavaScriptInvoke inst) {
result = new DeclaredTypeOperator(new ConeType(cha.getRootClass(), cha));
}
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead inst) {
result = new DeclaredTypeOperator(new ConeType(cha.getRootClass(), cha));
}
public void visitTypeOf(JavaScriptTypeOfInstruction inst) {
result = new DeclaredTypeOperator(new PointType(cha.lookupClass(JavaScriptTypes.String), cha));
}
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite inst) {
}
};
class JSTypeVarFactory extends TypeVarFactory {
private TypeAbstraction make(TypeReference typeRef) {
return new PointType(cha.lookupClass( typeRef ), cha);
}
public IVariable makeVariable(int vn) {
if (ir.getSymbolTable().isStringConstant( vn )) {
return new TypeVariable(make(JavaScriptTypes.String), 1331*vn);
} else if (ir.getSymbolTable().isNumberConstant( vn )) {
return new TypeVariable(make(JavaScriptTypes.Number), 797*vn);
} else if (ir.getSymbolTable().isNullConstant( vn )) {
return new TypeVariable(make(JavaScriptTypes.Null), 4077*vn);
} else {
return super.makeVariable( vn );
}
}
};
init(ir, new JSTypeVarFactory(), new JSTypeOperatorFactory());
}
public TypeAbstraction getConstantType(int valueNumber) {
SymbolTable st = ir.getSymbolTable();
if (st.isStringConstant(valueNumber)) {
return new PointType(cha.lookupClass(JavaScriptTypes.String), cha);
} else if (st.isNullConstant(valueNumber)) {
return new PointType(cha.lookupClass(JavaScriptTypes.Null), cha);
} else {
return new PointType(cha.lookupClass(JavaScriptTypes.Number), cha);
}
}
}

View File

@ -0,0 +1,72 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.cfg;
import com.ibm.wala.cast.ir.cfg.AstInducedCFG;
import com.ibm.wala.cast.js.ssa.*;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ssa.SSAInstruction;
public class JSInducedCFG extends AstInducedCFG {
public JSInducedCFG(SSAInstruction[] instructions, IMethod method, Context context) {
super(instructions, method, context);
}
class JSPEIVisitor extends AstPEIVisitor implements InstructionVisitor {
JSPEIVisitor(boolean[] r) {
super(r);
}
public void visitJavaScriptInvoke(JavaScriptInvoke inst) {
breakBasicBlock();
}
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead inst) {
}
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite inst) {
}
public void visitTypeOf(JavaScriptTypeOfInstruction inst) {
}
}
class JSBranchVisitor extends AstBranchVisitor implements InstructionVisitor {
JSBranchVisitor(boolean[] r) {
super(r);
}
public void visitJavaScriptInvoke(JavaScriptInvoke inst) {
}
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead inst) {
}
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite inst) {
}
public void visitTypeOf(JavaScriptTypeOfInstruction inst) {
}
}
protected BranchVisitor makeBranchVisitor(boolean[] r) {
return new JSBranchVisitor(r);
}
protected PEIVisitor makePEIVisitor(boolean[] r) {
return new JSPEIVisitor(r);
}
}

View File

@ -0,0 +1,100 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.client;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.cast.ipa.callgraph.*;
import com.ibm.wala.cast.ir.ssa.*;
import com.ibm.wala.cast.js.client.impl.*;
import com.ibm.wala.cast.js.ipa.callgraph.*;
import com.ibm.wala.cast.js.loader.*;
import com.ibm.wala.cast.js.translator.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.client.*;
import com.ibm.wala.client.impl.*;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ipa.callgraph.*;
import com.ibm.wala.ipa.cha.*;
import java.io.*;
import java.util.jar.*;
public class JavaScriptAnalysisEngine extends AbstractAnalysisEngine {
protected JavaScriptLoaderFactory loaderFactory;
protected JavaScriptTranslatorFactory translatorFactory;
protected boolean keepIRs = true;
public JavaScriptAnalysisEngine() {
setCallGraphBuilderFactory(
new com.ibm.wala.cast.js.client.impl.ZeroCFABuilderFactory() );
}
protected void buildAnalysisScope() {
try {
loaderFactory = new JavaScriptLoaderFactory(translatorFactory);
SourceFileModule[] files = (SourceFileModule[])
moduleFiles.toArray(new SourceFileModule[ moduleFiles.size() ]);
scope = new CAstAnalysisScope( files, loaderFactory );
} catch (IOException e) {
Assertions.UNREACHABLE(e.toString());
}
}
protected ClassHierarchy buildClassHierarchy() {
try {
return
ClassHierarchy.make(
getScope(), loaderFactory, getWarnings(), JavaScriptTypes.Root);
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE(e.toString());
return null;
}
}
public void setTranslatorFactory(JavaScriptTranslatorFactory factory) {
this.translatorFactory = factory;
}
public void setJ2SELibraries(JarFile[] libs) {
Assertions.UNREACHABLE("Illegal to call setJ2SELibraries");
}
public void setJ2SELibraries(Module[] libs) {
Assertions.UNREACHABLE("Illegal to call setJ2SELibraries");
}
public AnalysisOptions getDefaultOptions(Entrypoints roots) {
final AnalysisOptions options =
new AnalysisOptions(
scope,
AstIRFactory.makeDefaultFactory(keepIRs),
roots);
options.setConstantType(String.class, JavaScriptTypes.String);
options.setConstantType(Integer.class, JavaScriptTypes.Number);
options.setConstantType(Float.class, JavaScriptTypes.Number);
options.setConstantType(Double.class, JavaScriptTypes.Number);
options.setConstantType(null, JavaScriptTypes.Null);
options.setUseConstantSpecificKeys( true );
options.setUseStacksForLexicalScoping( true );
options.getSSAOptions().setPreserveNames( true );
return options;
}
}

View File

@ -0,0 +1,48 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.client.impl;
import com.ibm.wala.cast.ipa.callgraph.*;
import com.ibm.wala.cast.js.ipa.callgraph.*;
import com.ibm.wala.client.CallGraphBuilderFactory;
import com.ibm.wala.ipa.callgraph.*;
import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.callgraph.propagation.cfa.*;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.util.warnings.WarningSet;
/**
* @author Julian Dolby (dolby@us.ibm.com)
*
* A factory to create call graph builders using 0-CFA
*/
public class ZeroCFABuilderFactory implements CallGraphBuilderFactory {
/*
* (non-Javadoc)
*
* @see com.ibm.domo.j2ee.client.CallGraphBuilderFactory#make(com.ibm.domo.ipa.callgraph.AnalysisOptions,
* com.ibm.domo.ipa.cha.ClassHierarchy, java.lang.ClassLoader,
* com.ibm.domo.j2ee.J2EEAnalysisScope,
* com.ibm.domo.util.warnings.WarningSet, boolean)
*/
public CallGraphBuilder make(AnalysisOptions options,
ClassHierarchy cha,
AnalysisScope scope,
WarningSet warnings,
boolean keepPointsTo)
{
com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha, warnings);
options.setSelector(new StandardFunctionTargetSelector(cha, options.getMethodTargetSelector()));
return new JSZeroXCFABuilder(cha, warnings, options, null, null, null, ZeroXInstanceKeys.NONE);
}
}

View File

@ -0,0 +1,33 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import com.ibm.wala.cast.ipa.callgraph.*;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.util.warnings.WarningSet;
/**
* @author sfink
*
* Common utilities for CFA-style call graph builders.
*/
public class JSCFABuilder extends JSSSAPropagationCallGraphBuilder {
/**
* @param cha
* @param warnings
*/
public JSCFABuilder(ClassHierarchy cha, WarningSet warnings, AnalysisOptions options) {
super(cha, warnings, options, new AstCFAPointerKeys());
}
}

View File

@ -0,0 +1,71 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import com.ibm.wala.cast.ipa.callgraph.*;
import com.ibm.wala.cast.js.cfg.*;
import com.ibm.wala.cast.js.ssa.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.cfg.*;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ipa.callgraph.*;
import com.ibm.wala.ipa.callgraph.impl.*;
import com.ibm.wala.ipa.cha.*;
import com.ibm.wala.ssa.*;
import com.ibm.wala.types.*;
import com.ibm.wala.util.warnings.WarningSet;
public class JSCallGraph extends AstCallGraph {
public JSCallGraph(ClassHierarchy cha, AnalysisOptions options, WarningSet warnings) {
super(cha, options, warnings);
}
public class JSFakeRoot extends ScriptFakeRoot {
public JSFakeRoot(ClassHierarchy cha, AnalysisOptions options) {
super(cha, options);
}
public InducedCFG makeControlFlowGraph() {
return new JSInducedCFG(getStatements(new WarningSet()), this, Everywhere.EVERYWHERE);
}
public SSANewInstruction addAllocation(TypeReference T, WarningSet warnings) {
if (cha.isSubclassOf(cha.lookupClass(T), cha.lookupClass(JavaScriptTypes.Root))) {
int instance = nextLocal++;
NewSiteReference ref = NewSiteReference.make(statements.size(), T);
SSANewInstruction result = new JavaScriptNewInstruction(instance, ref);
statements.add(result);
return result;
} else {
return super.addAllocation(T, warnings);
}
}
public SSAAbstractInvokeInstruction addDirectCall(int function,
int[] params,
CallSiteReference site)
{
CallSiteReference newSite = CallSiteReference.make(statements.size(), site.getDeclaredTarget(), site.getInvocationCode());
JavaScriptInvoke s =
new JavaScriptInvoke(function, nextLocal++, params, nextLocal++, newSite);
statements.add(s);
return s;
}
}
protected CGNode makeFakeRootNode() {
return findOrCreateNode(new JSFakeRoot(cha, options), Everywhere.EVERYWHERE);
}
}

View File

@ -0,0 +1,612 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import com.ibm.wala.util.debug.Trace;
import com.ibm.wala.fixpoint.IVariable;
import com.ibm.wala.fixedpoint.impl.*;
import com.ibm.wala.util.intset.*;
import com.ibm.wala.analysis.typeInference.TypeInference;
import com.ibm.wala.cast.ipa.callgraph.*;
import com.ibm.wala.cast.ir.ssa.EachElementHasNextInstruction;
import com.ibm.wala.cast.js.analysis.typeInference.JSTypeInference;
import com.ibm.wala.cast.js.ssa.*;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.fixpoint.IntSetVariable;
import com.ibm.wala.ipa.callgraph.*;
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
import com.ibm.wala.ipa.callgraph.propagation.*;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ssa.*;
import com.ibm.wala.ssa.SSACFG.BasicBlock;
import com.ibm.wala.util.warnings.WarningSet;
import com.ibm.wala.shrikeBT.BinaryOpInstruction;
import java.util.*;
public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraphBuilder {
public static final boolean DEBUG_LEXICAL = false;
public static final boolean DEBUG_TYPE_INFERENCE = false;
protected
JSSSAPropagationCallGraphBuilder(ClassHierarchy cha,
WarningSet warnings,
AnalysisOptions options,
PointerKeyFactory pointerKeyFactory)
{
super(cha, warnings, options, pointerKeyFactory);
}
protected boolean isConstantRef(SymbolTable symbolTable, int valueNumber) {
if (valueNumber == -1) {
return false;
}
return symbolTable.isConstant(valueNumber);
}
/////////////////////////////////////////////////////////////////////////////
//
// language specialization interface
//
/////////////////////////////////////////////////////////////////////////////
protected boolean useObjectCatalog() {
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// top-level node constraint generation
//
/////////////////////////////////////////////////////////////////////////////
protected ExplicitCallGraph createEmptyCallGraph(ClassHierarchy cha, AnalysisOptions options) {
return new JSCallGraph(cha, options, getWarnings());
}
protected TypeInference makeTypeInference(IR ir, ClassHierarchy cha) {
TypeInference ti = new JSTypeInference(ir, cha);
ti.solve();
if (DEBUG_TYPE_INFERENCE) {
Trace.println("IR of " + ir.getMethod());
Trace.println( ir );
Trace.println("TypeInference of " + ir.getMethod());
for(int i = 0; i < ir.getSymbolTable().getMaxValueNumber(); i++) {
if (ti.isUndefined(i)) {
Trace.println(" value " + i + " is undefined");
} else {
Trace.println(" value " + i + " has type " + ti.getType(i));
}
}
}
return ti;
}
protected void addAssignmentsForCatchPointerKey(PointerKey exceptionVar, Set catchClasses, PointerKey e) {
system.newConstraint(exceptionVar, assignOperator, e);
}
class JSInterestingVisitor
extends AstInterestingVisitor
implements com.ibm.wala.cast.js.ssa.InstructionVisitor
{
JSInterestingVisitor(int vn) {
super(vn);
}
public void visitBinaryOp(final SSABinaryOpInstruction instruction) {
bingo = true;
}
public void visitJavaScriptInvoke(JavaScriptInvoke instruction) {
bingo = true;
}
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction) {
bingo = true;
}
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction) {
bingo = true;
}
public void visitTypeOf(JavaScriptTypeOfInstruction inst) {
bingo = true;
}
}
protected InterestingVisitor makeInterestingVisitor(int vn) {
return new JSInterestingVisitor(vn);
}
/////////////////////////////////////////////////////////////////////////////
//
// specialized pointer analysis
//
/////////////////////////////////////////////////////////////////////////////
protected class JSPointerFlowGraph extends AstPointerFlowGraph {
protected class JSPointerFlowVisitor
extends AstPointerFlowVisitor
implements com.ibm.wala.cast.js.ssa.InstructionVisitor
{
protected JSPointerFlowVisitor(CGNode node, IR ir, BasicBlock bb) {
super(node, ir, bb);
}
public void visitJavaScriptInvoke(JavaScriptInvoke instruction) {
}
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction) {
}
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction) {
}
public void visitTypeOf(JavaScriptTypeOfInstruction instruction) {
}
}
protected JSPointerFlowGraph(PointerAnalysis pa, CallGraph cg) {
super(pa,cg);
}
protected InstructionVisitor makeInstructionVisitor(CGNode node, IR ir, BasicBlock bb) {
return new JSPointerFlowVisitor(node,ir, bb);
}
}
public PointerFlowGraphFactory getPointerFlowGraphFactory() {
return new PointerFlowGraphFactory() {
public PointerFlowGraph make(PointerAnalysis pa, CallGraph cg) {
return new JSPointerFlowGraph(pa, cg);
}
};
}
/////////////////////////////////////////////////////////////////////////////
//
// function call handling
//
/////////////////////////////////////////////////////////////////////////////
class JSDispatchOperator extends UnaryOperator {
private final JavaScriptInvoke call;
private final ExplicitCallGraph.ExplicitNode node;
private final InstanceKey[][] constParams;
private final PointerKey uniqueCatch;
public boolean isLoadOperator() {
return false;
}
public String toString() {
return "JSDispatch of " + call.getCallSite();
}
public int hashCode() {
return call.getCallSite().hashCode() * node.hashCode();
}
public boolean equals(Object o) {
return (o instanceof JSDispatchOperator) &&
((JSDispatchOperator)o).node.equals(node) &&
((JSDispatchOperator)o).call.equals(call);
}
/**
* @param call
* @param node
*/
JSDispatchOperator(JavaScriptInvoke call, ExplicitCallGraph.ExplicitNode node, InstanceKey[][] constParams, PointerKey uniqueCatch) {
this.call = call;
this.node = node;
this.constParams = constParams;
this.uniqueCatch = uniqueCatch;
}
private MutableIntSet previousReceivers = IntSetUtil.getDefaultIntSetFactory().make();
public byte evaluate(IVariable lhs, IVariable rhs) {
final IntSetVariable receivers = (IntSetVariable) rhs;
if (receivers.getValue() != null) {
receivers.getValue().foreachExcluding(
previousReceivers,
new IntSetAction() {
public void act(int ptr) {
InstanceKey iKey = system.getInstanceKey(ptr);
CGNode target = getTargetForCall(node, call.getSite(), iKey);
if (target != null) {
processJSCall(node, call, target, iKey, constParams, uniqueCatch);
if (!haveAlreadyVisited(target)) {
markDiscovered(target);
}
}
}
}
);
previousReceivers.addAll( receivers.getValue() );
}
return NOT_CHANGED;
};
}
void processJSCall(CGNode caller,
JavaScriptInvoke instruction,
CGNode target,
InstanceKey function,
InstanceKey constParams[][],
PointerKey uniqueCatchKey)
{
caller.addTarget(instruction.getCallSite(), target);
if (!haveAlreadyVisited(target)) {
markDiscovered(target);
}
IR sourceIR = getCFAContextInterpreter().getIR(caller, getWarnings());
SymbolTable sourceST = sourceIR.getSymbolTable();
IR targetIR = getCFAContextInterpreter().getIR(target, getWarnings());
SymbolTable targetST = targetIR.getSymbolTable();
int av = -1;
for(int v = 0; v < targetST.getMaxValueNumber(); v++) {
String[] vns = targetIR.getLocalNames(1, v);
for(int n = 0; vns != null && n < vns.length; n++) {
if ("arguments".equals( vns[n] )) {
av = v;
break;
}
}
}
int paramCount = targetST.getParameterValueNumbers().length;
int argCount = instruction.getNumberOfParameters();
// pass actual arguments to formals in the normal way
for(int i = 0; i < Math.min(paramCount, argCount); i++) {
int fn = targetST.getConstant(i);
PointerKey F =
(i == 0)?
getFilteredPointerKeyForLocal(
target,
targetST.getParameter(i),
function):
getPointerKeyForLocal(target, targetST.getParameter(i));
if (constParams != null && constParams[i] != null) {
for(int j = 0; j < constParams[i].length; j++) {
system.newConstraint(F, constParams[i][j]);
}
if (av != -1) newFieldWrite(target, av, fn, constParams[i]);
} else {
PointerKey A = getPointerKeyForLocal(caller, instruction.getUse(i));
system.newConstraint(
F,
(F instanceof FilteredPointerKey)?
(UnaryOperator)filterOperator:
(UnaryOperator)assignOperator,
A);
if (av != -1) newFieldWrite(target, av, fn, F);
}
}
// extra actual arguments get assigned into the ``arguments'' object
if (paramCount < argCount) {
if (av != -1) {
for(int i = paramCount; i < argCount; i++) {
int fn = targetST.getConstant(i);
if (constParams != null && constParams[i] != null) {
newFieldWrite(target, av, fn, constParams[i]);
} else {
PointerKey A = getPointerKeyForLocal(caller, instruction.getUse(i));
newFieldWrite(target, av, fn, A);
}
}
}
}
// extra formal parameters get null (extra args are ignored here)
else if (argCount < paramCount) {
int nullvn = sourceST.getNullConstant();
DefUse sourceDU = getCFAContextInterpreter().getDU(caller, getWarnings());
InstanceKey[] nullkeys = getInvariantContents(sourceST, sourceDU, caller, nullvn, this);
for(int i = argCount; i < paramCount; i++) {
PointerKey F = getPointerKeyForLocal(target, targetST.getParameter(i));
for(int k = 0; k < nullkeys.length; k++) {
system.newConstraint(F, nullkeys[k]);
}
}
}
// write `length' in argument objects
if (av != -1) {
int svn = targetST.getConstant( argCount );
int lnv = targetST.getConstant("length");
newFieldWrite(target, av, lnv, svn);
}
// return values
if (instruction.getDef(0) != -1) {
PointerKey RF = getPointerKeyForReturnValue( target );
PointerKey RA = getPointerKeyForLocal(caller, instruction.getDef(0));
system.newConstraint(RA, assignOperator, RF);
}
PointerKey EF = getPointerKeyForExceptionalReturnValue( target );
if (SHORT_CIRCUIT_SINGLE_USES && uniqueCatchKey != null) {
// e has exactly one use. so, represent e implicitly
system.newConstraint(uniqueCatchKey, assignOperator, EF);
} else {
PointerKey EA = getPointerKeyForLocal(caller, instruction.getDef(1));
system.newConstraint(EA, assignOperator, EF);
}
}
/////////////////////////////////////////////////////////////////////////////
//
// string manipulation handling for binary operators
//
/////////////////////////////////////////////////////////////////////////////
private void handleBinaryOp(final SSABinaryOpInstruction instruction,
final CGNode node,
final SymbolTable symbolTable,
final DefUse du)
{
int lval = instruction.getDef(0);
PointerKey lk = getPointerKeyForLocal(node, lval);
final PointsToSetVariable lv = system.findOrCreatePointsToSet(lk);
final int arg1 = instruction.getUse(0);
final int arg2 = instruction.getUse(1);
class BinaryOperator extends AbstractOperator {
private CGNode getNode() {
return node;
}
private SSABinaryOpInstruction getInstruction() {
return instruction;
}
public String toString() {
return "BinOp: " + getInstruction();
}
public int hashCode() {
return 17 * getInstruction().getUse(0) * getInstruction().getUse(1);
}
public boolean equals(Object o) {
if (o instanceof BinaryOperator) {
BinaryOperator op = (BinaryOperator)o;
return
op.getNode().equals( getNode() ) &&
op.getInstruction().getUse(0) == getInstruction().getUse(0) &&
op.getInstruction().getUse(1) == getInstruction().getUse(1) &&
op.getInstruction().getDef(0) == getInstruction().getDef(0);
} else {
return false;
}
}
private InstanceKey[] getInstancesArray(int vn) {
if (contentsAreInvariant(symbolTable, du, vn)) {
return getInvariantContents(symbolTable, du, node, vn, JSSSAPropagationCallGraphBuilder.this);
} else {
PointsToSetVariable v =
system.findOrCreatePointsToSet(getPointerKeyForLocal(node,vn));
if (v.getValue() == null || v.size() == 0) {
return new InstanceKey[0];
} else {
final Set temp = new HashSet();
v.getValue().foreach(new IntSetAction() {
public void act(int keyIndex) {
temp.add( system.getInstanceKey(keyIndex) );
}
});
return (InstanceKey[])temp.toArray(new InstanceKey[temp.size()]);
}
}
}
private boolean isStringConstant(InstanceKey k) {
return
(k instanceof ConstantKey)
&&
k.getConcreteType().getReference().equals(JavaScriptTypes.String);
}
private boolean addKey(InstanceKey k) {
int n = system.findOrCreateIndexForInstanceKey( k );
if (! lv.contains(n)) {
lv.add( n );
return true;
} else {
return false;
}
}
public byte evaluate(IVariable lhs, final IVariable[] rhs) {
boolean doDefault = false;
byte changed = NOT_CHANGED;
InstanceKey[] iks1 = getInstancesArray( arg1 );
InstanceKey[] iks2 = getInstancesArray( arg2 );
if ( (instruction.getOperator() == BinaryOpInstruction.Operator.ADD)
&&
( getOptions().getTraceStringConstants() ) )
{
for(int i = 0 ; i < iks1.length; i++) {
if (isStringConstant(iks1[i])) {
for(int j = 0 ; j < iks2.length; j++) {
if (isStringConstant(iks2[j])) {
String v1 = (String)((ConstantKey)iks1[i]).getValue();
String v2 = (String)((ConstantKey)iks2[j]).getValue();
if (v1.indexOf(v2) == -1 && v2.indexOf(v1) == -1) {
InstanceKey lvalKey = getInstanceKeyForConstant(v1+v2);
if (addKey( lvalKey )) {
changed = CHANGED;
}
} else {
doDefault = true;
}
} else {
doDefault = true;
}
}
} else {
doDefault = true;
}
}
} else {
doDefault = true;
}
if (doDefault) {
for(int i = 0; i < iks1.length; i++) {
if (addKey(new ConcreteTypeKey(iks1[i].getConcreteType()))) {
changed = CHANGED;
}
}
for(int i = 0; i < iks2.length; i++) {
if (addKey(new ConcreteTypeKey(iks2[i].getConcreteType()))) {
changed = CHANGED;
}
}
}
return changed;
}
}
BinaryOperator B = new BinaryOperator();
if (contentsAreInvariant(symbolTable, du, arg1)) {
if (contentsAreInvariant(symbolTable, du, arg2)) {
B.evaluate(null, null);
} else {
system.newConstraint(lk, B, getPointerKeyForLocal(node, arg2));
}
} else {
PointerKey k1 = getPointerKeyForLocal(node, arg1);
if (contentsAreInvariant(symbolTable, du, arg2)) {
system.newConstraint(lk, B, k1);
} else {
system.newConstraint(lk, B, k1, getPointerKeyForLocal(node, arg2));
}
}
}
/////////////////////////////////////////////////////////////////////////////
//
// IR visitor specialization for JavaScript
//
/////////////////////////////////////////////////////////////////////////////
class JSConstraintVisitor extends AstConstraintVisitor implements InstructionVisitor {
public JSConstraintVisitor(ExplicitCallGraph.ExplicitNode node, IR ir, ExplicitCallGraph callGraph, DefUse du) {
super(node, ir, callGraph, du);
}
public void visitEachElementHasNext(EachElementHasNextInstruction inst) {
int lval = inst.getDef(0);
PointerKey lk = getPointerKeyForLocal(node, lval);
IClass bool = cha.lookupClass(JavaScriptTypes.Boolean);
InstanceKey key = new ConcreteTypeKey( bool );
system.newConstraint(lk, key);
}
public void visitTypeOf(JavaScriptTypeOfInstruction instruction) {
int lval = instruction.getDef(0);
PointerKey lk = getPointerKeyForLocal(node, lval);
IClass string = cha.lookupClass(JavaScriptTypes.String);
InstanceKey key = new ConcreteTypeKey( string );
system.newConstraint(lk, key);
}
public void visitBinaryOp(final SSABinaryOpInstruction instruction) {
handleBinaryOp( instruction, node, symbolTable, du );
}
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction) {
newFieldRead(node,
instruction.getUse(0),
instruction.getUse(1),
instruction.getDef(0));
}
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction) {
newFieldWrite(node,
instruction.getUse(0),
instruction.getUse(1),
instruction.getUse(2));
}
public void visitJavaScriptInvoke(JavaScriptInvoke instruction) {
PointerKey F = getPointerKeyForLocal(node, instruction.getFunction());
InstanceKey[][] consts = computeInvariantParameters(instruction);
PointerKey uniqueCatch = null;
if (hasUniqueCatchBlock(instruction, ir)) {
uniqueCatch = getUniqueCatchKey(instruction, ir, node);
}
if (contentsAreInvariant(symbolTable, du, instruction.getFunction())) {
system.recordImplicitPointsToSet(F);
InstanceKey[] ik = getInvariantContents(symbolTable, du, node, instruction.getFunction(), JSSSAPropagationCallGraphBuilder.this);
for (int i = 0; i < ik.length; i++) {
system.findOrCreateIndexForInstanceKey(ik[i]);
CGNode n = getTargetForCall(node, instruction.getCallSite(), ik[i]);
if (n != null) {
processJSCall(node, instruction, n, ik[i], consts, uniqueCatch);
}
}
} else {
system.newSideEffect(
new JSDispatchOperator(instruction, node, consts, uniqueCatch),
F);
}
}
}
protected ConstraintVisitor makeVisitor(ExplicitCallGraph.ExplicitNode node,
IR ir,
DefUse du,
ExplicitCallGraph callGraph)
{
return new JSConstraintVisitor(node, ir, callGraph, du);
}
}

View File

@ -0,0 +1,40 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.propagation.NodeKey;
public class JSSyntheticParameterKey extends NodeKey {
public static int lengthOffset = -1;
private final int param;
public JSSyntheticParameterKey(CGNode node, int param) {
super(node);
this.param = param;
}
public boolean equals(Object o) {
return (o instanceof JSSyntheticParameterKey) &&
((JSSyntheticParameterKey)o).param == param &&
internalEquals(o);
}
public int hashCode() {
return param*getNode().hashCode();
}
public String toString() {
return "p" + param + ":" + getNode().getMethod().getName();
}
}

View File

@ -0,0 +1,103 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import com.ibm.wala.ipa.callgraph.*;
import com.ibm.wala.ipa.callgraph.impl.*;
import com.ibm.wala.ipa.callgraph.propagation.*;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.util.warnings.WarningSet;
/**
* @author sfink
*
* 0-1-CFA Call graph builder, optimized to not disambiguate instances of
* "uninteresting" types
*/
public class JSZeroXCFABuilder extends JSCFABuilder {
/**
* @param cha
* @param warnings
* @param entrypoints
* @param bypass
* @param contextProvider
*/
public JSZeroXCFABuilder(ClassHierarchy cha,
WarningSet warnings,
AnalysisOptions options,
ContextSelector appContextSelector,
SSAContextInterpreter appContextInterpreter,
ReflectionSpecification reflect,
int instancePolicy) {
super(cha, warnings, options);
SSAContextInterpreter contextInterpreter =
makeDefaultContextInterpreters(appContextInterpreter, options, cha, reflect, warnings);
setContextInterpreter( contextInterpreter );
options.setSelector(
new JavaScriptConstructTargetSelector(
cha,
options.getMethodTargetSelector(),
contextInterpreter,
warnings));
ContextSelector def = new DefaultContextSelector(cha,options.getMethodTargetSelector());
ContextSelector contextSelector =
appContextSelector == null?
def:
new DelegatingContextSelector(appContextSelector, def);
setContextSelector(contextSelector);
setInstanceKeys(
new JavaScriptScopeMappingInstanceKeys(cha, this,
new ZeroXInstanceKeys(options, cha, contextInterpreter, warnings, instancePolicy)));
}
/**
* @param options
* options that govern call graph construction
* @param cha
* governing class hierarchy
* @param cl
* classloader that can find DOMO resources
* @param scope
* representation of the analysis scope
* @param xmlFiles
* set of Strings that are names of XML files holding bypass logic
* specifications.
* @param dmd
* deployment descriptor abstraction
* @return a 0-1-Opt-CFA Call Graph Builder.
*/
public static JSCFABuilder make(AnalysisOptions options, ClassHierarchy cha, ClassLoader cl, AnalysisScope scope,
String[] xmlFiles, WarningSet warnings, byte instancePolicy) {
com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha, warnings);
for (int i = 0; i < xmlFiles.length; i++) {
com.ibm.wala.ipa.callgraph.impl.Util.addBypassLogic(options, scope, cl, xmlFiles[i], cha);
}
return new JSZeroXCFABuilder(cha, warnings, options, null, null, options.getReflectionSpec(), instancePolicy);
}
/*
* (non-Javadoc)
*
* @see com.ibm.domo.ipa.callgraph.propagation.PropagationCallGraphBuilder#getDefaultDispatchBoundHeuristic()
*/
protected byte getDefaultDispatchBoundHeuristic() {
return AnalysisOptions.NO_DISPATCH_BOUND;
}
}

View File

@ -0,0 +1,549 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import java.io.*;
import java.util.*;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.debug.Trace;
import com.ibm.wala.cast.js.ipa.summaries.*;
import com.ibm.wala.cast.js.loader.*;
import com.ibm.wala.cast.js.ssa.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.cast.types.*;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ipa.callgraph.*;
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.summaries.MethodSummary;
import com.ibm.wala.ssa.*;
import com.ibm.wala.types.*;
import com.ibm.wala.util.warnings.WarningSet;
public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
private static final boolean DEBUG = false;
private final ClassHierarchy cha;
private final MethodTargetSelector base;
private final SSAContextInterpreter interpreter;
private final WarningSet warnings;
private final Map constructors = new HashMap();
private class JavaScriptConstructor extends JavaScriptSummarizedFunction {
private final String toStringExtra;
private JavaScriptConstructor(MethodReference ref,
MethodSummary summary,
IClass declaringClass,
String toStringExtra)
{
super(ref, summary, declaringClass);
this.toStringExtra = toStringExtra;
}
private JavaScriptConstructor(MethodReference ref,
MethodSummary summary,
IClass declaringClass)
{
this(ref, summary, declaringClass, "");
}
public String toString() {
return "<ctor for " + getReference().getDeclaringClass() + toStringExtra + ">";
}
}
public JavaScriptConstructTargetSelector(ClassHierarchy cha,
MethodTargetSelector base,
SSAContextInterpreter interpreter,
WarningSet warnings)
{
this.cha = cha;
this.base = base;
this.interpreter = interpreter;
this.warnings = warnings;
}
private IMethod record(Object key, IMethod m) {
constructors.put(key, m);
return m;
}
private IMethod makeNullaryValueConstructor(IClass cls, Object value) {
MethodReference ref =
JavaScriptMethods.makeCtorReference( cls.getReference() );
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
S.addStatement(new JavaScriptStaticPropertyRead(4, 1, "prototype"));
S.addStatement(
new JavaScriptNewInstruction(
5,
NewSiteReference.make(
S.getNextProgramCounter(),
JavaScriptTypes.Object)));
S.addStatement(new JavaScriptStaticPropertyWrite(5, "prototype", 4));
S.addConstant(new Integer(8), new ConstantValue(value));
S.addStatement(new JavaScriptStaticPropertyWrite(5, "$value", 8));
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeUnaryValueConstructor(IClass cls) {
MethodReference ref =
JavaScriptMethods.makeCtorReference( cls.getReference() );
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
S.addStatement(new JavaScriptStaticPropertyRead(5, 1, "prototype"));
S.addStatement(
new JavaScriptNewInstruction(
6,
NewSiteReference.make(
S.getNextProgramCounter(),
JavaScriptTypes.Object)));
S.addStatement(new JavaScriptStaticPropertyWrite(6, "prototype", 5));
S.addStatement(new JavaScriptStaticPropertyWrite(6, "$value", 2));
S.addStatement(SSAInstructionFactory.ReturnInstruction(6, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeValueConstructor(IClass cls, int nargs, Object value) {
Assertions._assert(nargs == 0 || nargs == 1);
Object key = new Pair(cls, new Integer(nargs));
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
else return
record(
key,
(nargs==0)?
makeNullaryValueConstructor(cls, value):
makeUnaryValueConstructor(cls));
}
private IMethod makeNullaryObjectConstructor(IClass cls) {
MethodReference ref =
JavaScriptMethods.makeCtorReference( JavaScriptTypes.Object );
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
S.addStatement(new JavaScriptStaticPropertyRead(4, 1, "prototype"));
S.addStatement(
new JavaScriptNewInstruction(
5,
NewSiteReference.make(
S.getNextProgramCounter(),
JavaScriptTypes.Object)));
S.addStatement(new JavaScriptStaticPropertyWrite(5, "prototype", 4));
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeUnaryObjectConstructor(IClass cls) {
MethodReference ref =
JavaScriptMethods.makeCtorReference( JavaScriptTypes.Object );
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
S.addStatement(SSAInstructionFactory.ReturnInstruction(2, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeObjectConstructor(IClass cls, int nargs) {
Assertions._assert(nargs == 0 || nargs == 1);
Object key = new Pair(cls, new Integer(nargs));
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
else return
record(
key,
(nargs==0)?
makeNullaryObjectConstructor(cls):
makeUnaryObjectConstructor(cls));
}
private IMethod makeObjectCall(IClass cls, int nargs) {
Assertions._assert(nargs == 0);
Object key = new Pair(cls, new Integer(nargs));
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
else return
record(
key,
makeNullaryObjectConstructor(cls));
}
private IMethod makeArrayLengthConstructor(IClass cls) {
MethodReference ref =
JavaScriptMethods.makeCtorReference( JavaScriptTypes.Array );
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
S.addStatement(new JavaScriptStaticPropertyRead(5, 1, "prototype"));
S.addStatement(
new JavaScriptNewInstruction(
6,
NewSiteReference.make(
S.getNextProgramCounter(),
JavaScriptTypes.Array)));
S.addStatement(new JavaScriptStaticPropertyWrite(6, "prototype", 5));
S.addStatement(new JavaScriptStaticPropertyWrite(6, "length", 2));
S.addStatement(SSAInstructionFactory.ReturnInstruction(6, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeArrayContentsConstructor(IClass cls, int nargs) {
MethodReference ref =
JavaScriptMethods.makeCtorReference( JavaScriptTypes.Array );
JavaScriptSummary S = new JavaScriptSummary(ref, nargs+1);
S.addConstant(new Integer(nargs+3), new ConstantValue("prototype"));
S.addStatement(new JavaScriptPropertyRead(nargs+4, 1, nargs+3));
S.addStatement(
new JavaScriptNewInstruction(
nargs+5,
NewSiteReference.make(
S.getNextProgramCounter(),
JavaScriptTypes.Array)));
S.addStatement(new JavaScriptStaticPropertyWrite(nargs+5, "prototype", nargs+4));
S.addConstant(new Integer(nargs+7), new ConstantValue(nargs));
S.addStatement(new JavaScriptStaticPropertyWrite(nargs+5, "length", nargs+7));
int vn = nargs+9;
for(int i = 0; i < nargs; i++, vn+=2) {
S.addConstant(new Integer(vn), new ConstantValue(i));
S.addStatement(new JavaScriptPropertyWrite(nargs+5, vn, i+1));
}
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeArrayConstructor(IClass cls, int nargs) {
Object key = new Pair(cls, new Integer(nargs));
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
else return
record(
key,
(nargs==1)?
makeArrayLengthConstructor(cls):
makeArrayContentsConstructor(cls, nargs));
}
private IMethod makeNullaryStringCall(IClass cls) {
MethodReference ref =
AstMethodReference.fnReference( JavaScriptTypes.String );
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
S.addConstant(new Integer(2), new ConstantValue(""));
S.addStatement(SSAInstructionFactory.ReturnInstruction(2, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeUnaryStringCall(IClass cls) {
MethodReference ref =
AstMethodReference.fnReference( JavaScriptTypes.String );
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
S.addStatement(new JavaScriptStaticPropertyRead(4, 2, "toString"));
CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());
S.addStatement(new JavaScriptInvoke(4, 5, new int[]{2}, 6, cs));
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeStringCall(IClass cls, int nargs) {
Assertions._assert(nargs == 0 || nargs == 1);
Object key = new Pair(cls, new Integer(nargs));
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
else return
record(
key,
(nargs==0)?
makeNullaryStringCall(cls):
makeUnaryStringCall(cls));
}
private IMethod makeNullaryNumberCall(IClass cls) {
MethodReference ref =
AstMethodReference.fnReference( JavaScriptTypes.Number );
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
S.addConstant(new Integer(2), new ConstantValue(0.0));
S.addStatement(SSAInstructionFactory.ReturnInstruction(2, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeUnaryNumberCall(IClass cls) {
MethodReference ref =
AstMethodReference.fnReference( JavaScriptTypes.Number );
JavaScriptSummary S = new JavaScriptSummary(ref, 2);
S.addStatement(new JavaScriptStaticPropertyRead(4, 2, "toNumber"));
CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());
S.addStatement(new JavaScriptInvoke(4, 5, new int[]{2}, 6, cs));
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
return new JavaScriptConstructor(ref, S, cls);
}
private IMethod makeNumberCall(IClass cls, int nargs) {
Assertions._assert(nargs == 0 || nargs == 1);
Object key = new Pair(cls, new Integer(nargs));
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
else return
record(
key,
(nargs==0)?
makeNullaryNumberCall(cls):
makeUnaryNumberCall(cls));
}
private IMethod makeFunctionConstructor(IClass receiver, IClass cls) {
if (constructors.containsKey(cls)) return (IMethod)constructors.get(cls);
MethodReference ref =
JavaScriptMethods.makeCtorReference( receiver.getReference() );
JavaScriptSummary S = new JavaScriptSummary(ref, 1);
S.addStatement(new JavaScriptStaticPropertyRead(4, 1, "prototype"));
S.addStatement(
new JavaScriptNewInstruction(
5,
NewSiteReference.make(
S.getNextProgramCounter(),
cls.getReference())));
S.addStatement(new JavaScriptStaticPropertyWrite(5, "prototype", 4));
S.addStatement(
new JavaScriptNewInstruction(
7,
NewSiteReference.make(
S.getNextProgramCounter(),
JavaScriptTypes.Object)));
S.addStatement(new JavaScriptStaticPropertyWrite(5, "prototype", 7));
S.addStatement(new JavaScriptStaticPropertyWrite(7, "constructor", 5));
S.addStatement(SSAInstructionFactory.ReturnInstruction(5, false));
if (receiver != cls)
return record(receiver, new JavaScriptConstructor(ref, S, receiver, "("+cls.getReference().getName()+")"));
else
return record(receiver, new JavaScriptConstructor(ref, S, receiver));
}
private int ctorCount = 0;
private IMethod makeFunctionConstructor(IR callerIR, SSAAbstractInvokeInstruction callStmt, IClass cls, int nargs) {
SymbolTable ST = callerIR.getSymbolTable();
if (nargs == 0) {
return makeFunctionConstructor(cls, cls);
} else if (nargs==1) {
if (ST.isStringConstant(callStmt.getUse(1))) {
TypeReference ref =
TypeReference.findOrCreate(
JavaScriptTypes.jsLoader,
TypeName.string2TypeName(
(String)ST.getStringValue(callStmt.getUse(1)) ));
if (DEBUG) {
Trace.println("ctor type name is " + (String)ST.getStringValue(callStmt.getUse(1)));
}
IClass cls2 = cha.lookupClass( ref );
if (cls2 != null) {
return makeFunctionConstructor(cls, cls2);
}
}
return makeFunctionConstructor(cls, cls);
} else {
Assertions._assert(nargs > 1);
JavaScriptLoader cl = (JavaScriptLoader)
cha.getLoader(JavaScriptTypes.jsLoader);
for(int i = 1; i < callStmt.getNumberOfUses(); i++)
if (! ST.isStringConstant(callStmt.getUse(i)))
return makeFunctionConstructor(cls, cls);
StringBuffer fun = new StringBuffer("function _fromctor (");
for(int j = 1; j < callStmt.getNumberOfUses()-1; j++) {
if (j != 1) fun.append(",");
fun.append( ST.getStringValue(callStmt.getUse(j)) );
}
fun.append(") {");
fun.append(ST.getStringValue(callStmt.getUse(callStmt.getNumberOfUses()-1)));
fun.append("}");
try {
String fileName = "ctor " + ++ctorCount;
File f = new File(System.getProperty("java.io.tmpdir")+File.separator+fileName);
FileWriter FO = new FileWriter(f);
FO.write( fun.toString() );
FO.close();
(Util.getTranslatorFactory().make(cl)).translate(new SourceFileModule(f, System.getProperty("java.io.tmpdir")), fileName);
f.delete();
IClass fcls = cl.lookupClass("Lctor " + ctorCount + "/_fromctor", cha);
cha.addClass( fcls );
if (DEBUG)
Trace.println("looking for ctor " + ctorCount + " and got " + fcls);
if (fcls != null)
return makeFunctionConstructor(cls, fcls);
} catch (IOException e) {
}
return makeFunctionConstructor(cls, cls);
}
}
private IMethod makeFunctionObjectConstructor(IClass cls, int nargs) {
Object key = new Pair(cls, new Integer(nargs));
if (constructors.containsKey(key)) return (IMethod)constructors.get(key);
MethodReference ref =
JavaScriptMethods.makeCtorReference( cls.getReference() );
JavaScriptSummary S = new JavaScriptSummary(ref, nargs+1);
S.addStatement(new JavaScriptStaticPropertyRead(nargs+4, 1, "prototype"));
S.addStatement(
new JavaScriptNewInstruction(
nargs+5,
NewSiteReference.make(
S.getNextProgramCounter(),
JavaScriptTypes.Object)));
S.addStatement(new JavaScriptStaticPropertyWrite(nargs+5, "prototype", nargs+4));
CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());
int[] args = new int[ nargs+1 ];
args[0] = nargs+5;
for(int i = 0; i < nargs; i++) args[i+1] = i+2;
S.addStatement(new JavaScriptInvoke(1, nargs+7, args, nargs+8, cs));
S.addStatement(SSAInstructionFactory.ReturnInstruction(nargs+7, false));
S.addStatement(SSAInstructionFactory.ReturnInstruction(nargs+5, false));
return record(key, new JavaScriptConstructor(ref, S, cls));
}
private IMethod findOrCreateConstructorMethod(IR callerIR, SSAAbstractInvokeInstruction callStmt, IClass receiver, int nargs) {
if (receiver.getReference().equals(JavaScriptTypes.Object))
return makeObjectConstructor(receiver, nargs);
else if (receiver.getReference().equals(JavaScriptTypes.Array))
return makeArrayConstructor(receiver, nargs);
else if (receiver.getReference().equals(JavaScriptTypes.String))
return makeValueConstructor(receiver, nargs, "");
else if (receiver.getReference().equals(JavaScriptTypes.Boolean)) {
Assertions._assert(nargs == 1);
return makeValueConstructor(receiver, nargs, null);
} else if (receiver.getReference().equals(JavaScriptTypes.Number))
return makeValueConstructor(receiver, nargs, new Integer(0));
else if (receiver.getReference().equals(JavaScriptTypes.Function))
return makeFunctionConstructor(callerIR, callStmt, receiver, nargs);
else if (cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.CodeBody)))
return makeFunctionObjectConstructor(receiver, nargs);
else {
return null;
}
}
private IMethod findOrCreateCallMethod(IR callerIR, SSAAbstractInvokeInstruction callStmt, IClass receiver, int nargs) {
if (receiver.getReference().equals(JavaScriptTypes.Object))
return makeObjectCall(receiver, nargs);
else if (receiver.getReference().equals(JavaScriptTypes.Array))
return makeArrayConstructor(receiver, nargs);
else if (receiver.getReference().equals(JavaScriptTypes.String))
return makeStringCall(receiver, nargs);
else if (receiver.getReference().equals(JavaScriptTypes.Number))
return makeNumberCall(receiver, nargs);
else if (receiver.getReference().equals(JavaScriptTypes.Function))
return makeFunctionConstructor(callerIR, callStmt, receiver, nargs);
else {
return null;
}
}
public IMethod getCalleeTarget(CGNode caller,
CallSiteReference site,
IClass receiver)
{
if (site.getDeclaredTarget().equals(JavaScriptMethods.ctorReference)) {
Assertions._assert(cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.Root)));
IR callerIR = interpreter.getIR(caller, warnings);
SSAAbstractInvokeInstruction callStmts[] = callerIR.getCalls( site );
Assertions._assert( callStmts.length == 1 );
int nargs = callStmts[0].getNumberOfUses();
return findOrCreateConstructorMethod(callerIR, callStmts[0], receiver, nargs-1);
} else {
return base.getCalleeTarget(caller, site, receiver);
}
}
public boolean mightReturnSyntheticMethod(CGNode caller,
CallSiteReference site)
{
return true;
}
public boolean mightReturnSyntheticMethod(MethodReference declaredTarget) {
return true;
}
}

View File

@ -0,0 +1,25 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import com.ibm.wala.cast.ipa.callgraph.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ipa.cha.*;
public class JavaScriptEntryPoints extends ScriptEntryPoints {
public JavaScriptEntryPoints(ClassHierarchy cha, IClassLoader loader) {
super(cha, loader.lookupClass(JavaScriptTypes.Script.getName(), cha));
}
}

View File

@ -0,0 +1,52 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys;
import com.ibm.wala.cast.js.loader.JavaScriptLoader.JavaScriptMethodObject;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.cast.loader.AstMethod.LexicalParent;
import com.ibm.wala.cast.types.*;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.ipa.callgraph.propagation.*;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.types.Selector;
public class JavaScriptScopeMappingInstanceKeys extends ScopeMappingInstanceKeys {
private final ClassHierarchy cha;
private final IClass codeBody;
public JavaScriptScopeMappingInstanceKeys(ClassHierarchy cha,
PropagationCallGraphBuilder builder,
InstanceKeyFactory basic)
{
super(builder, basic);
this.cha = cha;
this.codeBody = cha.lookupClass(JavaScriptTypes.CodeBody);
}
protected LexicalParent[] getParents(InstanceKey base) {
JavaScriptMethodObject function = (JavaScriptMethodObject)
base.getConcreteType().getMethod(AstMethodReference.fnSelector);
return function==null? new LexicalParent[0]: function.getParents();
}
protected boolean needsScopeMappingKey(InstanceKey base) {
return
cha.isSubclassOf(base.getConcreteType(), codeBody)
&&
getParents(base).length > 0;
}
}

View File

@ -0,0 +1,120 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import com.ibm.wala.cast.ipa.callgraph.*;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.loader.*;
import com.ibm.wala.cast.js.translator.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.cast.types.*;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ipa.callgraph.*;
import com.ibm.wala.ipa.cha.*;
import com.ibm.wala.types.*;
import com.ibm.wala.util.warnings.WarningSet;
public class Util extends com.ibm.wala.cast.ipa.callgraph.Util {
private static JavaScriptTranslatorFactory translatorFactory =
new JavaScriptTranslatorFactory.CAstRhinoFactory();
public static void setTranslatorFactory(JavaScriptTranslatorFactory translatorFactory) {
Util.translatorFactory = translatorFactory;
}
public static JavaScriptTranslatorFactory getTranslatorFactory() {
return translatorFactory;
}
public static AnalysisOptions
makeOptions(AnalysisScope scope,
boolean keepIRs,
ClassHierarchy cha,
Entrypoints roots,
final WarningSet warnings)
{
final AnalysisOptions options =
new AnalysisOptions(scope, AstIRFactory.makeDefaultFactory(keepIRs), roots);
com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha, warnings);
options.setSelector(new StandardFunctionTargetSelector(cha, options.getMethodTargetSelector()));
options.setConstantType(String.class, JavaScriptTypes.String);
options.setConstantType(Integer.class, JavaScriptTypes.Number);
options.setConstantType(Float.class, JavaScriptTypes.Number);
options.setConstantType(Double.class, JavaScriptTypes.Number);
options.setConstantType(null, JavaScriptTypes.Null);
options.setUseConstantSpecificKeys( true );
options.setUseStacksForLexicalScoping( true );
options.getSSAOptions().setPreserveNames( true );
return options;
}
public static JavaScriptLoaderFactory makeLoaders() {
return new JavaScriptLoaderFactory(translatorFactory);
}
public static AnalysisScope
makeScope(String[] files, JavaScriptLoaderFactory loaders)
throws IOException
{
return new CAstAnalysisScope( files, loaders );
}
public static AnalysisScope
makeScope(SourceFileModule[] files, JavaScriptLoaderFactory loaders)
throws IOException
{
return new CAstAnalysisScope( files, loaders );
}
public static AnalysisScope
makeScope(URL[] files, JavaScriptLoaderFactory loaders)
throws IOException
{
return new CAstAnalysisScope( files, loaders );
}
public static ClassHierarchy
makeHierarchy(AnalysisScope scope,
ClassLoaderFactory loaders,
WarningSet warnings)
throws ClassHierarchyException
{
return ClassHierarchy.make(
scope,
loaders,
warnings,
JavaScriptTypes.Root);
}
public static Entrypoints makeScriptRoots(ClassHierarchy cha) {
return new JavaScriptEntryPoints(
cha,
cha.getLoader( JavaScriptTypes.jsLoader ));
}
public static Collection getNodes(CallGraph CG, String funName) {
boolean ctor = funName.startsWith("ctor:");
TypeReference TR = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName( "L"+(ctor?funName.substring(5):funName) ));
MethodReference MR = ctor? JavaScriptMethods.makeCtorReference(TR): AstMethodReference.fnReference(TR);
return CG.getNodes(MR);
}
}

View File

@ -0,0 +1,39 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.summaries;
import com.ibm.wala.cast.js.cfg.JSInducedCFG;
import com.ibm.wala.cfg.InducedCFG;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.summaries.MethodSummary;
import com.ibm.wala.ipa.summaries.SummarizedMethod;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.util.warnings.WarningSet;
public class JavaScriptSummarizedFunction extends SummarizedMethod {
public JavaScriptSummarizedFunction(MethodReference ref,
MethodSummary summary,
IClass declaringClass)
{
super(ref, summary, declaringClass);
}
public boolean equals(Object o) {
return this==o;
}
public InducedCFG makeControlFlowGraph() {
return new JSInducedCFG(getStatements(new WarningSet()), this, Everywhere.EVERYWHERE);
}
}

View File

@ -0,0 +1,45 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.summaries;
import com.ibm.wala.cast.js.ssa.JavaScriptNewInstruction;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ipa.summaries.MethodSummary;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeReference;
public class JavaScriptSummary extends MethodSummary {
private final int declaredParameters;
public JavaScriptSummary(MethodReference ref, int declaredParameters) {
super(ref);
this.declaredParameters = declaredParameters;
addStatement(
new JavaScriptNewInstruction(
declaredParameters+1,
NewSiteReference.make(
getNextProgramCounter(),
JavaScriptTypes.Array)));
}
public int getNumberOfParameters() {
return declaredParameters;
}
public TypeReference getParameterType(int i) {
return JavaScriptTypes.Root;
}
}

View File

@ -0,0 +1,43 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.loader;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.cast.types.*;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
public class JSCallSiteReference extends CallSiteReference {
// this must be distinct from java invoke codes.
// see com.ibm.shrikeBT.BytecodeConstants
public static enum Dispatch implements IInvokeInstruction.IDispatch {
JS_CALL;
}
public JSCallSiteReference(MethodReference ref, int pc) {
super(pc, ref);
}
public JSCallSiteReference(int pc) {
this(AstMethodReference.fnReference(JavaScriptTypes.CodeBody), pc);
}
public IInvokeInstruction.IDispatch getInvocationCode() {
return Dispatch.JS_CALL;
}
public String toString() {
return "JSCall@" + getProgramCounter();
}
}

View File

@ -0,0 +1,352 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.loader;
import java.io.IOException;
import java.util.*;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.debug.Trace;
import com.ibm.wala.cast.js.translator.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.cast.loader.*;
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
import com.ibm.wala.cast.loader.AstMethod.LexicalInformation;
import com.ibm.wala.cast.tree.*;
import com.ibm.wala.cast.types.*;
import com.ibm.wala.cfg.AbstractCFG;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ipa.cha.*;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.*;
import com.ibm.wala.util.Atom;
public class JavaScriptLoader implements IClassLoader {
private final Map types = new HashMap();
private final JavaScriptTranslatorFactory translatorFactory;
private final ClassHierarchy cha;
JavaScriptLoader(ClassHierarchy cha,
JavaScriptTranslatorFactory translatorFactory)
{
this.cha = cha;
this.translatorFactory = translatorFactory;
}
class JavaScriptClass extends AstClass {
private IClass superClass;
private JavaScriptClass(IClassLoader loader,
TypeReference classRef,
TypeReference superRef,
CAstSourcePositionMap.Position sourcePosition) {
super(sourcePosition,
classRef.getName(),
loader,
(short)0,
Collections.EMPTY_MAP,
Collections.EMPTY_MAP);
types.put(classRef.getName(), this);
superClass = superRef==null? null: loader.lookupClass(superRef.getName(), cha);
}
public ClassHierarchy getClassHierarchy() {
return cha;
}
public String toString() {
return "JS:" + getReference().toString();
}
@Override
public Collection getDirectInterfaces() throws ClassHierarchyException {
return Collections.EMPTY_SET;
}
@Override
public IClass getSuperclass() throws ClassHierarchyException {
return superClass;
}
}
class JavaScriptRootClass extends AstDynamicPropertyClass {
private JavaScriptRootClass(IClassLoader loader,
CAstSourcePositionMap.Position sourcePosition)
{
super(sourcePosition,
JavaScriptTypes.Root.getName(),
loader,
(short)0,
Collections.EMPTY_MAP,
JavaScriptTypes.Root);
types.put(JavaScriptTypes.Root.getName(), this);
}
public ClassHierarchy getClassHierarchy() {
return cha;
}
public String toString() {
return "JS Root:" + getReference().toString();
}
public Collection getDirectInterfaces() throws ClassHierarchyException {
return Collections.EMPTY_SET;
}
public IClass getSuperclass() throws ClassHierarchyException {
return null;
}
}
class JavaScriptCodeBody extends AstFunctionClass {
public JavaScriptCodeBody(TypeReference codeName,
TypeReference parent,
IClassLoader loader,
CAstSourcePositionMap.Position sourcePosition)
{
super(codeName, parent, loader, sourcePosition);
types.put(codeName.getName(), this);
}
public ClassHierarchy getClassHierarchy() {
return cha;
}
private IMethod setCodeBody(IMethod codeBody) {
this.functionBody = codeBody;
return codeBody;
}
}
private final Set functionQualifiers;
{
functionQualifiers = new HashSet();
functionQualifiers.add(CAstQualifier.PUBLIC);
functionQualifiers.add(CAstQualifier.FINAL);
}
public class JavaScriptMethodObject extends AstMethod {
JavaScriptMethodObject(JavaScriptCodeBody cls,
AbstractCFG cfg,
SymbolTable symtab,
boolean hasCatchBlock,
TypeReference[][] caughtTypes,
LexicalInformation lexicalInfo,
DebuggingInformation debugInfo)
{
super(cls,
functionQualifiers,
cfg,
symtab,
AstMethodReference.fnReference(cls.getReference()),
hasCatchBlock,
caughtTypes,
lexicalInfo,
debugInfo);
}
public ClassHierarchy getClassHierarchy() {
return cha;
}
public String toString() {
return "<Code body of " + cls + ">";
}
public TypeReference[] getDeclaredExceptions() {
return null;
}
public LexicalParent[] getParents() {
if (lexicalInfo == null) return new LexicalParent[ 0 ];
final String[] parents = lexicalInfo.getScopingParents();
if (parents == null) return new LexicalParent[ 0 ];
LexicalParent result[] =
new LexicalParent[ parents.length ];
for(int i = 0; i < parents.length; i++) {
final int hack = i;
final AstMethod method = (AstMethod) lookupClass(parents[i], cha).getMethod(AstMethodReference.fnSelector);
result[i] = new LexicalParent() {
public String getName() { return parents[hack]; }
public AstMethod getMethod() { return method; }
};
Trace.println("parent " + result[i].getName() + " is " + result[i].getMethod());
}
return result;
}
public String getLocalVariableName(int bcIndex, int localNumber) {
return null;
}
public boolean hasLocalVariableTable() {
return false;
}
public int getMaxLocals() {
Assertions.UNREACHABLE();
return -1;
}
public int getMaxStackHeight() {
Assertions.UNREACHABLE();
return -1;
}
public TypeReference getParameterType(int i) {
return JavaScriptTypes.Root;
}
}
public IClass
defineCodeBodyType(String name,
TypeReference P,
CAstSourcePositionMap.Position sourcePosition)
{
return
new JavaScriptCodeBody(
TypeReference.findOrCreate(
JavaScriptTypes.jsLoader,
TypeName.string2TypeName( name )),
P,
this,
sourcePosition);
}
public IClass
defineFunctionType(String name, CAstSourcePositionMap.Position pos)
{
return defineCodeBodyType(name, JavaScriptTypes.Function, pos);
}
public IClass
defineScriptType(String name, CAstSourcePositionMap.Position pos)
{
return defineCodeBodyType(name, JavaScriptTypes.Script, pos);
}
public IMethod defineCodeBodyCode(String clsName,
AbstractCFG cfg,
SymbolTable symtab,
boolean hasCatchBlock,
TypeReference[][] caughtTypes,
LexicalInformation lexicalInfo,
DebuggingInformation debugInfo)
{
JavaScriptCodeBody C = (JavaScriptCodeBody) lookupClass(clsName, cha);
Assertions._assert(C != null, clsName);
return C.setCodeBody(new JavaScriptMethodObject(C, cfg, symtab, hasCatchBlock, caughtTypes, lexicalInfo, debugInfo));
}
final JavaScriptRootClass ROOT =
new JavaScriptRootClass(this, null);
final JavaScriptClass UNDEFINED =
new JavaScriptClass(this, JavaScriptTypes.Undefined, JavaScriptTypes.Root, null);
final JavaScriptClass PRIMITIVES =
new JavaScriptClass(this, JavaScriptTypes.Primitives, JavaScriptTypes.Root, null);
final JavaScriptClass STRING =
new JavaScriptClass(this, JavaScriptTypes.String, JavaScriptTypes.Root, null);
final JavaScriptClass NULL =
new JavaScriptClass(this, JavaScriptTypes.Null, JavaScriptTypes.Root, null);
final JavaScriptClass BOOLEAN =
new JavaScriptClass(this, JavaScriptTypes.Boolean, JavaScriptTypes.Root, null);
final JavaScriptClass NUMBER =
new JavaScriptClass(this, JavaScriptTypes.Number, JavaScriptTypes.Root, null);
final JavaScriptClass DATE =
new JavaScriptClass(this, JavaScriptTypes.Date, JavaScriptTypes.Root, null);
final JavaScriptClass REGEXP =
new JavaScriptClass(this, JavaScriptTypes.RegExp, JavaScriptTypes.Root, null);
final JavaScriptClass ARRAY =
new JavaScriptClass(this, JavaScriptTypes.Array, JavaScriptTypes.Root, null);
final JavaScriptClass OBJECT =
new JavaScriptClass(this, JavaScriptTypes.Object, JavaScriptTypes.Root, null);
final JavaScriptClass TYPE_ERROR =
new JavaScriptClass(this, JavaScriptTypes.TypeError, JavaScriptTypes.Root, null);
final JavaScriptClass CODE_BODY =
new JavaScriptClass(this, JavaScriptTypes.CodeBody, JavaScriptTypes.Root, null);
final JavaScriptClass FUNCTION =
new JavaScriptClass(this, JavaScriptTypes.Function, JavaScriptTypes.CodeBody, null);
final JavaScriptClass SCRIPT =
new JavaScriptClass(this, JavaScriptTypes.Script, JavaScriptTypes.CodeBody, null);
public IClass lookupClass(String className, ClassHierarchy cha) {
Assertions._assert(this.cha == cha);
return (IClass) types.get( TypeName.string2TypeName(className) );
}
public IClass lookupClass(TypeName className, ClassHierarchy cha) {
Assertions._assert(this.cha == cha);
return (IClass) types.get( className );
}
public ClassLoaderReference getReference() {
return JavaScriptTypes.jsLoader;
}
public Iterator iterateAllClasses() {
return types.values().iterator();
}
public int getNumberOfClasses() {
return 0;
}
public Atom getName() {
return getReference().getName();
}
public int getNumberOfMethods() {
return types.size();
}
public String getSourceFileName(IClass klass) {
return klass.getSourceFileName();
}
public IClassLoader getParent() {
// currently, JavaScript land does not interact with any other loaders
Assertions.UNREACHABLE("JavaScriptLoader.getParent() called?!?");
return null;
}
public void init(Set modules) throws IOException {
translatorFactory.make(this).translate(modules);
}
public void removeAll(Collection toRemove) {
Set keys = new HashSet();
for(Iterator EE = types.entrySet().iterator(); EE.hasNext(); ) {
Map.Entry E = (Map.Entry)EE.next();
if (toRemove.contains( E.getValue() )) {
keys.add( E.getKey() );
}
}
for(Iterator KK = keys.iterator(); KK.hasNext(); ) {
types.remove( KK.next() );
}
}
}

View File

@ -0,0 +1,34 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.loader;
import com.ibm.wala.cast.js.translator.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.cast.loader.*;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ipa.cha.*;
import com.ibm.wala.types.*;
public class JavaScriptLoaderFactory extends SingleClassLoaderFactory {
private final JavaScriptTranslatorFactory translatorFactory;
public JavaScriptLoaderFactory(JavaScriptTranslatorFactory factory) {
this.translatorFactory = factory;
}
protected IClassLoader makeTheLoader(ClassHierarchy cha) {
return new JavaScriptLoader( cha, translatorFactory );
}
public ClassLoaderReference getTheReference() {
return JavaScriptTypes.jsLoader;
}
}

View File

@ -0,0 +1,37 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.cast.ir.ssa.AstAbstractInstructionVisitor;
public class AbstractInstructionVisitor
extends AstAbstractInstructionVisitor
implements InstructionVisitor
{
public void visitJavaScriptInvoke(JavaScriptInvoke instruction) {
}
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction) {
}
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction) {
}
public void visitTypeOf(JavaScriptTypeOfInstruction instruction) {
}
}

View File

@ -0,0 +1,25 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.cast.ir.ssa.AstInstructionVisitor;
public interface InstructionVisitor extends AstInstructionVisitor {
public void visitJavaScriptInvoke(JavaScriptInvoke instruction);
public void visitTypeOf(JavaScriptTypeOfInstruction instruction);
public void visitJavaScriptPropertyRead(JavaScriptPropertyRead instruction);
public void visitJavaScriptPropertyWrite(JavaScriptPropertyWrite instruction);
}

View File

@ -0,0 +1,210 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.cast.ir.ssa.*;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ssa.*;
import java.util.*;
public class JavaScriptInvoke extends AbstractLexicalInvoke {
/**
* The value numbers of the arguments passed to the call.
*/
private final int[] params;
private int function;
public JavaScriptInvoke(int function, int result, int[] params, int exception, CallSiteReference site) {
super(result, exception, site);
this.function = function;
this.params = params;
}
private JavaScriptInvoke(int function, int result, int[] params, int exception, CallSiteReference site, Access[] lexicalReads, Access[] lexicalWrites) {
super(result, exception, site, lexicalReads, lexicalWrites);
this.function = function;
this.params = params;
}
/**
* Constructor InvokeInstruction. This case for void return values
* @param i
* @param params
*/
public JavaScriptInvoke(int function, int[] params, int exception, CallSiteReference site) {
this(function, -1, params, exception, site);
}
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
int fn = function;
int newParams[] = params;
Access[] reads = lexicalReads;
if (uses != null) {
int i = 0;
fn = uses[i++];
newParams = new int[ params.length ];
for(int j = 0; j < newParams.length; j++)
newParams[j] = uses[i++];
if (lexicalReads != null) {
reads = new Access[ lexicalReads.length ];
for(int j = 0; j < reads.length; j++)
reads[j] = new Access(lexicalReads[j].variableName, lexicalReads[j].variableDefiner, uses[i++]);
}
}
int newLval = result;
int newExp = exception;
Access[] writes = lexicalWrites;
if (defs != null) {
int i = 0;
newLval = defs[i++];
newExp = defs[i++];
if (lexicalWrites != null) {
writes = new Access[ lexicalWrites.length ];
for(int j = 0; j < writes.length; j++)
writes[j] = new Access(lexicalWrites[j].variableName, lexicalWrites[j].variableDefiner, defs[i++]);
}
}
return new JavaScriptInvoke(fn, newLval, newParams, newExp, site, reads, writes);
}
public String toString(SymbolTable symbolTable, ValueDecorator d) {
StringBuffer s = new StringBuffer();
if (result != -1) {
s.append(getValueString(symbolTable, d, result)).append(" = ");
}
if (site.getDeclaredTarget().equals(JavaScriptMethods.ctorReference))
s.append("construct ");
else
s.append("invoke ");
s.append(getValueString(symbolTable, d, function));
if (site != null) s.append("@").append(site.getProgramCounter());
if (params != null) {
if (params.length > 0) {
s.append(" ").append(getValueString(symbolTable, d, params[0]));
}
for (int i = 1; i < params.length; i++) {
s.append(",").append(getValueString(symbolTable, d, params[i]));
}
}
if (exception == -1) {
s.append(" exception: NOT MODELED");
} else {
s.append(" exception:").append(getValueString(symbolTable, d, exception));
}
if (lexicalReads != null) {
s.append(" (reads:");
for(int i = 0; i < lexicalReads.length; i++) {
s.append(" ").append(lexicalReads[i].variableName).append(":").append( getValueString(symbolTable, d, lexicalReads[i].valueNumber) );
}
s.append(")");
}
if (lexicalWrites != null) {
s.append(" (writes:");
for(int i = 0; i < lexicalWrites.length; i++) {
s.append(" ").append(lexicalWrites[i].variableName).append(":").append( getValueString(symbolTable, d, lexicalWrites[i].valueNumber) );
}
s.append(")");
}
return s.toString();
}
/**
* @see com.ibm.domo.ssa.Instruction#visit(Visitor)
*/
public void visit(IVisitor v) {
Assertions._assert(v instanceof InstructionVisitor);
((InstructionVisitor)v).visitJavaScriptInvoke(this);
}
public int getNumberOfParameters() {
if (params == null) {
return 1;
} else {
return params.length+1;
}
}
/**
* @see com.ibm.domo.ssa.Instruction#getUse(int)
*/
public int getUse(int j) {
if (j == 0)
return function;
else if (j <= params.length)
return params[j-1];
else {
return super.getUse(j);
}
}
public int getFunction() {
return function;
}
/* (non-Javadoc)
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
*/
public Collection getExceptionTypes() {
return Util.typeErrorExceptions();
}
public int hashCode() {
return site.hashCode() * function * 7529;
}
public boolean equals(Object obj) {
if (obj instanceof JavaScriptInvoke) {
JavaScriptInvoke other = (JavaScriptInvoke)obj;
if (site.equals(other.site)) {
if (getNumberOfUses() == other.getNumberOfUses()) {
for(int i = 0; i < getNumberOfUses(); i++) {
if (getUse(i) != other.getUse(i)) {
return false;
}
}
if (getNumberOfDefs() == other.getNumberOfDefs()) {
for(int i = 0; i < getNumberOfDefs(); i++) {
if (getDef(i) != other.getDef(i)) {
return false;
}
}
return true;
}
}
}
}
return false;
}
}

View File

@ -0,0 +1,35 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ssa.*;
import java.util.Collection;
public class JavaScriptNewInstruction extends SSANewInstruction {
public JavaScriptNewInstruction(int result, NewSiteReference site) {
super(result, site);
}
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
return
new JavaScriptNewInstruction(
defs==null? getDef(): defs[0],
getNewSite());
}
public Collection getExceptionTypes() {
return Util.typeErrorExceptions();
}
}

View File

@ -0,0 +1,54 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.cast.ir.ssa.*;
import com.ibm.wala.ssa.*;
import java.util.*;
public class JavaScriptPropertyRead extends AbstractReflectiveGet {
public JavaScriptPropertyRead(int result, int objectRef, int memberRef) {
super(result, objectRef, memberRef);
}
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
return
new JavaScriptPropertyRead(
defs==null? getDef(): defs[0],
uses==null? getObjectRef(): uses[0],
uses==null? getMemberRef(): uses[1]);
}
/* (non-Javadoc)
* @see com.ibm.domo.ssa.Instruction#isPEI()
*/
public boolean isPEI() {
return true;
}
/* (non-Javadoc)
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
*/
public Collection getExceptionTypes() {
return Util.typeErrorExceptions();
}
/**
/* (non-Javadoc)
* @see com.ibm.domo.ssa.SSAInstruction#visit(com.ibm.domo.ssa.SSAInstruction.Visitor)
*/
public void visit(IVisitor v) {
Assertions._assert(v instanceof InstructionVisitor);
((InstructionVisitor)v).visitJavaScriptPropertyRead(this);
}
}

View File

@ -0,0 +1,62 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.cast.ir.ssa.*;
import com.ibm.wala.ssa.*;
import java.util.*;
public class JavaScriptPropertyWrite extends AbstractReflectivePut {
public JavaScriptPropertyWrite(int objectRef, int memberRef, int value) {
super(objectRef, memberRef, value);
}
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
return
new JavaScriptPropertyWrite(
uses==null? getObjectRef(): uses[0],
uses==null? getMemberRef(): uses[1],
uses==null? getValue(): uses[2]);
}
public String toString(SymbolTable symbolTable, ValueDecorator d) {
return super.toString(symbolTable, d) +
" = " +
getValueString(symbolTable, d, getValue());
}
/**
* @see com.ibm.domo.ssa.Instruction#visit(Visitor)
*/
public void visit(IVisitor v) {
Assertions._assert(v instanceof InstructionVisitor);
((InstructionVisitor)v).visitJavaScriptPropertyWrite(this);
}
/* (non-Javadoc)
* @see com.ibm.domo.ssa.Instruction#isPEI()
*/
public boolean isPEI() {
return true;
}
/* (non-Javadoc)
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
*/
public Collection getExceptionTypes() {
return Util.typeErrorExceptions();
}
}

View File

@ -0,0 +1,57 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.cast.ir.ssa.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.ssa.*;
import com.ibm.wala.types.*;
import com.ibm.wala.util.*;
import java.util.*;
public class JavaScriptStaticPropertyRead extends SSAGetInstruction {
public JavaScriptStaticPropertyRead(int result,
int objectRef,
FieldReference memberRef) {
super(result, objectRef, memberRef);
}
public JavaScriptStaticPropertyRead(int result,
int objectRef,
String fieldName)
{
this(result,
objectRef,
FieldReference.findOrCreate(
JavaScriptTypes.Root,
Atom.findOrCreateUnicodeAtom(fieldName),
JavaScriptTypes.Root));
}
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
return
new JavaScriptStaticPropertyRead(
defs==null? getDef(): defs[0],
uses==null? getRef(): uses[0],
getDeclaredField());
}
/* (non-Javadoc)
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
*/
public Collection getExceptionTypes() {
return Util.typeErrorExceptions();
}
}

View File

@ -0,0 +1,58 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.cast.ir.ssa.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.ssa.*;
import com.ibm.wala.types.*;
import com.ibm.wala.util.*;
import java.util.*;
public class JavaScriptStaticPropertyWrite extends SSAPutInstruction {
public JavaScriptStaticPropertyWrite(int objectRef,
FieldReference memberRef,
int value) {
super(objectRef, value, memberRef);
}
public JavaScriptStaticPropertyWrite(int objectRef,
String fieldName,
int value)
{
this(objectRef,
FieldReference.findOrCreate(
JavaScriptTypes.Root,
Atom.findOrCreateUnicodeAtom(fieldName),
JavaScriptTypes.Root),
value);
}
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
return
new JavaScriptStaticPropertyWrite(
uses==null? getRef(): uses[0],
getDeclaredField(),
uses==null? getVal(): uses[1]);
}
/* (non-Javadoc)
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
*/
public Collection getExceptionTypes() {
return Util.typeErrorExceptions();
}
}

View File

@ -0,0 +1,42 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.ssa.SSAAbstractUnaryInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.ssa.ValueDecorator;
import java.util.Collection;
public class JavaScriptTypeOfInstruction extends SSAAbstractUnaryInstruction {
public JavaScriptTypeOfInstruction(int lval, int object) {
super(lval, object);
}
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
return new JavaScriptTypeOfInstruction((defs != null ? defs[0] : getDef(0)), (uses != null ? uses[0] : getUse(0)));
}
public String toString(SymbolTable symbolTable, ValueDecorator d) {
return getValueString(symbolTable, d, getDef(0)) + " = typeof(" + getValueString(symbolTable, d, getUse(0)) + ")";
}
public void visit(IVisitor v) {
((InstructionVisitor) v).visitTypeOf(this);
}
public Collection getExceptionTypes() {
return Util.noExceptions();
}
}

View File

@ -0,0 +1,31 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.cast.js.types.*;
import java.util.*;
class Util {
private static final Collection TYPE_ERROR_EXCEPTIONS =
Collections.unmodifiableCollection(
Collections.singleton( JavaScriptTypes.TypeError ));
public static Collection typeErrorExceptions() {
return TYPE_ERROR_EXCEPTIONS;
}
public static Collection noExceptions() {
return Collections.EMPTY_SET;
}
}

View File

@ -0,0 +1,34 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.translator;
import java.io.IOException;
import java.io.Reader;
import com.ibm.wala.cast.ir.translator.TranslatorToIR;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.classLoader.*;
public class CAstRhinoTranslator extends TranslatorBase {
private final JSAstTranslator CAstToIR;
public void translate(ModuleEntry M, String N) throws IOException {
CAstToIR.translate(
new RhinoToAstTranslator(new CAstImpl(), M, N).translate(),
N);
}
public CAstRhinoTranslator(JavaScriptLoader loader) {
this.CAstToIR = new JSAstTranslator(loader);
}
}

View File

@ -0,0 +1,306 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.translator;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.debug.Trace;
import com.ibm.wala.cast.ir.ssa.*;
import com.ibm.wala.cast.ir.translator.*;
import com.ibm.wala.cast.js.loader.*;
import com.ibm.wala.cast.js.ssa.*;
import com.ibm.wala.cast.js.types.*;
import com.ibm.wala.cast.loader.AstMethod.*;
import com.ibm.wala.cast.tree.*;
import com.ibm.wala.cast.tree.visit.*;
import com.ibm.wala.cast.types.*;
import com.ibm.wala.cfg.*;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ssa.*;
import com.ibm.wala.types.*;
import com.ibm.wala.shrikeBT.ConditionalBranchInstruction;
public class JSAstTranslator extends AstTranslator {
private final static boolean DEBUG = true;
public JSAstTranslator(JavaScriptLoader loader) {
super(loader);
}
protected boolean hasImplicitGlobals() {
return true;
}
protected boolean treatGlobalsAsLexicallyScoped() {
return true;
}
protected boolean useLocalValuesForLexicalVars() {
return true;
}
protected TypeReference defaultCatchType() {
return JavaScriptTypes.Root;
}
protected TypeReference makeType(CAstType type) {
Assertions.UNREACHABLE("JavaScript does not use CAstType");
return null;
}
protected void defineType(CAstEntity type, WalkContext wc) {
Assertions.UNREACHABLE("JavaScript doesn't have types. I suggest you look elsewhere for your amusement.");
}
protected void defineField(CAstEntity topEntity, WalkContext wc, CAstEntity n) {
Assertions.UNREACHABLE("JavaScript doesn't have fields, numb-nuts!");
}
protected String composeEntityName(WalkContext parent, CAstEntity f) {
if (f.getKind() == CAstEntity.SCRIPT_ENTITY)
return f.getName();
else
return parent.getName() + "/" + f.getName();
}
protected void declareFunction(CAstEntity N, WalkContext context) {
String fileName = context.file();
String fnName = composeEntityName(context, N);
if (N.getKind() == CAstEntity.SCRIPT_ENTITY) {
((JavaScriptLoader)loader).defineScriptType("L"+fnName, N.getPosition());
} else if (N.getKind() == CAstEntity.FUNCTION_ENTITY) {
((JavaScriptLoader)loader).defineFunctionType("L"+fnName, N.getPosition());
} else {
Assertions.UNREACHABLE();
}
}
protected void defineFunction(CAstEntity N,
WalkContext definingContext,
AbstractCFG cfg,
SymbolTable symtab,
boolean hasCatchBlock,
TypeReference[][] caughtTypes,
LexicalInformation LI,
DebuggingInformation debugInfo)
{
if (DEBUG) Trace.println("\n\nAdding code for " + N);
String fnName = composeEntityName(definingContext, N);
if (DEBUG) Trace.println( cfg );
((JavaScriptLoader)loader).defineCodeBodyCode("L"+fnName,
cfg,
symtab,
hasCatchBlock,
caughtTypes,
LI,
debugInfo);
}
protected void doThrow(WalkContext context, int exception) {
context.cfg().addInstruction(new NonExceptingThrowInstruction(exception));
}
protected void doCall(WalkContext context, CAstNode call, int result, int exception, CAstNode name, int receiver, int[] arguments) {
MethodReference ref =
name.getValue().equals("ctor")?
JavaScriptMethods.ctorReference:
AstMethodReference.fnReference(JavaScriptTypes.CodeBody);
context.cfg().addInstruction(
new JavaScriptInvoke(receiver, result, arguments, exception,
new JSCallSiteReference(ref, context.cfg().getCurrentInstruction())));
context.cfg().addPreNode(call, context.getUnwindState());
context.cfg().newBlock( true );
if (context.getControlFlow().getTarget(call, null) != null)
context.cfg().addPreEdge(call, context.getControlFlow().getTarget(call, null), true);
else
context.cfg().addPreEdgeToExit( call, true );
}
protected void doNewObject(WalkContext context, CAstNode newNode, int result, Object type, int[] arguments) {
Assertions._assert(arguments == null);
TypeReference typeRef =
TypeReference.findOrCreate(
JavaScriptTypes.jsLoader,
TypeName.string2TypeName( "L" + type ));
context.cfg().addInstruction(
new JavaScriptNewInstruction(
result,
NewSiteReference.make(
context.cfg().getCurrentInstruction(),
typeRef)));
}
protected void doMaterializeFunction(WalkContext context, int result, int exception, CAstEntity fn) {
int nm = context.currentScope().getConstantValue("L"+composeEntityName(context, fn));
int tmp = doGlobalRead(context, "Function");
context.cfg().addInstruction(
new JavaScriptInvoke(tmp, result, new int[]{ nm }, exception,
new JSCallSiteReference(
JavaScriptMethods.ctorReference,
context.cfg().getCurrentInstruction())));
}
protected void doArrayRead(WalkContext context, int result, int arrayValue, CAstNode arrayRef, int[] dimValues) {
Assertions.UNREACHABLE("JSAstTranslator.doArrayRead() called!");
}
protected void doArrayWrite(WalkContext context, int arrayValue, CAstNode arrayRef, int[] dimValues, int rval) {
Assertions.UNREACHABLE("JSAstTranslator.doArrayWrite() called!");
}
protected void doFieldRead(WalkContext context, int result, int receiver, CAstNode elt, CAstNode parent) {
walkNodes(elt, context);
int x = context.currentScope().allocateTempValue();
context.cfg().addInstruction(new AssignInstruction(x, receiver));
int u = doGlobalRead(context, "undefined");
context.cfg().newBlock( true );
PreBasicBlock iterB = context.cfg().getCurrentBlock();
if (elt.getKind() == CAstNode.CONSTANT && elt.getValue() instanceof String)
{
context.cfg().addInstruction(
new JavaScriptStaticPropertyRead(result, x, (String)elt.getValue() ));
} else {
context.cfg().addInstruction(
new JavaScriptPropertyRead(result, x, getValue(elt) ));
}
context.cfg().addInstruction(
new JavaScriptStaticPropertyRead(x, x, "prototype"));
context.cfg().addInstruction(
SSAInstructionFactory.ConditionalBranchInstruction(
ConditionalBranchInstruction.Operator.EQ, null, result, u));
context.cfg().addEdge(iterB, iterB);
context.cfg().newBlock( true );
}
protected void doFieldWrite(WalkContext context, int receiver, CAstNode elt, CAstNode parent, int rval) {
walkNodes(elt, context);
if (elt.getKind() == CAstNode.CONSTANT && elt.getValue() instanceof String)
{
context.cfg().addInstruction(
new JavaScriptStaticPropertyWrite(receiver, (String)elt.getValue(), rval));
} else {
context.cfg().addInstruction(
new JavaScriptPropertyWrite(receiver, getValue(elt), rval));
}
}
protected void doPrimitive(int resultVal, WalkContext context, CAstNode primitiveCall) {
try {
String name = (String)primitiveCall.getChild(0).getValue();
if (name.equals("GlobalNaN")) {
context.cfg().addInstruction(
new AssignInstruction(
resultVal,
context.currentScope().getConstantValue(new Float(Float.NaN))));
} else if (name.equals("GlobalInfinity")) {
context.cfg().addInstruction(
new AssignInstruction(
resultVal,
context.currentScope().getConstantValue(new Float(Float.POSITIVE_INFINITY))));
} else if (name.equals("MathE")) {
context.cfg().addInstruction(
new AssignInstruction(
resultVal,
context.currentScope().getConstantValue(new Double(Math.E))));
} else if (name.equals("MathPI")) {
context.cfg().addInstruction(
new AssignInstruction(
resultVal,
context.currentScope().getConstantValue(new Double(Math.PI))));
} else if (name.equals("MathSQRT1_2")) {
context.cfg().addInstruction(
new AssignInstruction(
resultVal,
context.currentScope().getConstantValue(new Double(Math.sqrt(.5)))));
} else if (name.equals("MathSQRT2")) {
context.cfg().addInstruction(
new AssignInstruction(
resultVal,
context.currentScope().getConstantValue(new Double(Math.sqrt(2)))));
} else if (name.equals("MathLN2")) {
context.cfg().addInstruction(
new AssignInstruction(
resultVal,
context.currentScope().getConstantValue(new Double(Math.log(2)))));
} else if (name.equals("MathLN10")) {
context.cfg().addInstruction(
new AssignInstruction(
resultVal,
context.currentScope().getConstantValue(new Double(Math.log(10)))));
} else if (name.equals("NewObject")) {
doNewObject(context, null, resultVal, "Object", null);
} else if (name.equals("NewArray")) {
doNewObject(context, null, resultVal, "Array", null);
} else if (name.equals("NewString")) {
doNewObject(context, null, resultVal, "String", null);
} else if (name.equals("NewNumber")) {
doNewObject(context, null, resultVal, "Number", null);
} else if (name.equals("NewRegExp")) {
doNewObject(context, null, resultVal, "RegExp", null);
} else if (name.equals("NewFunction")) {
doNewObject(context, null, resultVal, "Function", null);
} else if (name.equals("NewUndefined")) {
doNewObject(context, null, resultVal, "Undefined", null);
} else {
context.cfg().addInstruction(
new AssignInstruction(
resultVal,
context.currentScope().getConstantValue( null )));
}
} catch (ClassCastException e) {
throw new RuntimeException("Cannot translate primitive " + primitiveCall.getChild(0).getValue());
}
}
protected boolean doVisit(CAstNode n, Context cntxt, CAstVisitor visitor) {
WalkContext context = (WalkContext)cntxt;
switch (n.getKind()) {
case CAstNode.TYPE_OF: {
int result = context.currentScope().allocateTempValue();
walkNodes(n.getChild(0), context);
int ref = getValue(n.getChild(0));
context.cfg().addInstruction(
new JavaScriptTypeOfInstruction(result, ref));
setValue(n, result);
return true;
}
default: {
return false;
}
}
}
}

View File

@ -0,0 +1,27 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.translator;
import com.ibm.wala.cast.ir.translator.TranslatorToIR;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
public interface JavaScriptTranslatorFactory {
TranslatorToIR make(JavaScriptLoader loader);
public static class CAstRhinoFactory implements JavaScriptTranslatorFactory {
public TranslatorToIR make(JavaScriptLoader loader) {
return new CAstRhinoTranslator(loader);
}
}
}

View File

@ -0,0 +1,56 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.translator;
import com.ibm.wala.cast.ir.translator.TranslatorToIR;
import com.ibm.wala.classLoader.*;
import java.io.*;
import java.util.*;
public abstract class TranslatorBase implements TranslatorToIR {
protected static final Set bootstrapFileNames;
private static String prologueFileName = "prologue.js";
public static void resetPrologueFile() {
prologueFileName = "prologue.js";
}
public static void setPrologueFile(String name) {
prologueFileName = name;
}
public static void addBootstrapFile(String fileName) {
bootstrapFileNames.add( fileName );
}
static {
bootstrapFileNames = new HashSet();
bootstrapFileNames.add( prologueFileName );
}
public abstract void translate(ModuleEntry M, String N) throws IOException;
public void translate(Set modules) throws IOException {
translate(new SourceURLModule(getClass().getClassLoader().getResource(prologueFileName)), prologueFileName);
Iterator MS = modules.iterator();
while (MS.hasNext()) {
ModuleEntry M = (ModuleEntry) MS.next();
if (M instanceof SourceFileModule) {
translate(M, ((SourceFileModule)M).getClassName());
} else {
translate(M, M.getName());
}
}
}
}

View File

@ -0,0 +1,30 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.types;
import com.ibm.wala.cast.types.*;
import com.ibm.wala.types.*;
import com.ibm.wala.util.Atom;
public class JavaScriptMethods extends AstMethodReference {
public final static String ctorAtomStr = "ctor";
public final static Atom ctorAtom = Atom.findOrCreateUnicodeAtom(ctorAtomStr);
public final static String ctorDescStr = "()LRoot;";
public final static Descriptor ctorDesc = Descriptor.findOrCreateUTF8(ctorDescStr);
public final static MethodReference ctorReference =
MethodReference.findOrCreate(JavaScriptTypes.CodeBody, ctorAtom, ctorDesc);
public static MethodReference makeCtorReference(TypeReference cls) {
return MethodReference.findOrCreate(cls, ctorAtom, ctorDesc);
}
}

View File

@ -0,0 +1,72 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.types;
import com.ibm.wala.cast.types.*;
import com.ibm.wala.types.*;
import com.ibm.wala.util.Atom;
public class JavaScriptTypes extends AstTypeReference {
public static final String jsLoaderNameStr = "JavaScript";
public static final Atom jsLoaderName =
Atom.findOrCreateUnicodeAtom(jsLoaderNameStr);
public static final ClassLoaderReference jsLoader =
new ClassLoaderReference( jsLoaderName );
public static final TypeReference Root =
TypeReference.findOrCreate(jsLoader, rootTypeName);
public static final TypeReference Undefined =
TypeReference.findOrCreate(jsLoader, "LUndefined");
public static final TypeReference Null =
TypeReference.findOrCreate(jsLoader, "LNull");
public static final TypeReference Boolean =
TypeReference.findOrCreate(jsLoader, "LBoolean");
public static final TypeReference String =
TypeReference.findOrCreate(jsLoader, "LString");
public static final TypeReference Number =
TypeReference.findOrCreate(jsLoader, "LNumber");
public static final TypeReference Date =
TypeReference.findOrCreate(jsLoader, "LDate");
public static final TypeReference RegExp =
TypeReference.findOrCreate(jsLoader, "LRegExp");
public static final TypeReference Array =
TypeReference.findOrCreate(jsLoader, "LArray");
public static final TypeReference Object =
TypeReference.findOrCreate(jsLoader, "LObject");
public static final TypeReference CodeBody =
TypeReference.findOrCreate(jsLoader, functionTypeName);
public static final TypeReference Function =
TypeReference.findOrCreate(jsLoader, "LFunction");
public static final TypeReference Script =
TypeReference.findOrCreate(jsLoader, "LScript");
public static final TypeReference TypeError =
TypeReference.findOrCreate(jsLoader, "LTypeError");
public static final TypeReference Primitives =
TypeReference.findOrCreate(jsLoader, "LPrimitives");
}

View File

@ -0,0 +1,112 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.util;
import java.io.*;
import java.net.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
public class Generator {
public static final String preamble = "preamble.js", temp = "temp.js";
public static interface CallbackFactory {
HTMLEditorKit.ParserCallback createCallback(URL input, FileWriter out, FileWriter out2);
}
public static class HTMLCallbackFactory implements CallbackFactory {
public HTMLEditorKit.ParserCallback createCallback(URL input, FileWriter out, FileWriter out2) {
return new HTMLCallback(input, out, out2);
}
}
public static final CallbackFactory defaultCallbackFactory = new HTMLCallbackFactory();
private CallbackFactory callbackFactory;
private boolean ignoreCharset;
public Generator(boolean ignoreCharset, CallbackFactory factory) {
this.ignoreCharset = ignoreCharset;
this.callbackFactory = factory;
}
public Generator() {
this(false, defaultCallbackFactory);
}
private InputStreamReader getStream(String url) throws IOException {
return getStream( Generator.class.getClassLoader().getResource( url ) );
}
private InputStreamReader getStream(URL url) throws IOException {
URLConnection conn = url.openConnection();
conn.setDefaultUseCaches(false);
conn.setUseCaches(false);
return new InputStreamReader(conn.getInputStream());
}
public static void main(String args[]) throws IOException {
Generator g = new Generator();
if (new File(args[0]).exists()) {
g.generate(new URL("file:" + args[0]), new File(args[1]));
}
}
public void generate(URL input, File outFile) throws IOException {
InputStreamReader fr = getStream( input );
FileWriter out = new FileWriter(outFile);
FileWriter out2 = new FileWriter(temp);
ParserDelegator pd = new ParserDelegator();
HTMLEditorKit.ParserCallback cb = callbackFactory.createCallback(input, out, out2);
generatePreamble(out, cb);
out.write("//Generation of the DOM Tree Begins\n");
pd.parse(fr, cb, ignoreCharset);
out2.close();
out.write("//Generation of the DOM Tree Ends\n\n\n");
FileReader tmp = new FileReader(temp);
BufferedReader tempIn = new BufferedReader(tmp);
out.write("//Embedded Script Region Begins\n");
String line = tempIn.readLine();
while(line != null) {
out.write(line+"\n");
line = tempIn.readLine();
}
out.write("//Embedded Script Region Ends\n\n\n");
generateTrailer(out, cb);
out.close();
}
protected void generatePreamble(FileWriter out, HTMLEditorKit.ParserCallback cb) throws IOException {
InputStreamReader pm = getStream( preamble );
BufferedReader pmIn = new BufferedReader(pm);
out.write("//Preamble Begin\n");
String line = pmIn.readLine();
while(line != null) {
out.write(line+"\n");
line = pmIn.readLine();
}
out.write("//Preamble End\n\n\n");
}
protected void generateTrailer(FileWriter out, HTMLEditorKit.ParserCallback cb) throws IOException {
out.write("//Trailer Begin\n");
out.write("//Trailer End\n");
}
}

View File

@ -0,0 +1,181 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.util;
import java.io.*;
import java.net.*;
import javax.swing.text.html.*;
import javax.swing.text.*;
import java.util.*;
public class HTMLCallback extends HTMLEditorKit.ParserCallback {
private final URL input;
private final FileWriter out, out2;
private int counter=0;
private boolean script = false;
private final HashMap constructors = new HashMap();
protected final Stack stack;
public HTMLCallback(URL input, FileWriter out, FileWriter out2) {
this.input = input;
this.out = out;
this.out2 = out2;
stack = new Stack();
constructors.put("FORM", "DOMHTMLFormElement");
constructors.put("TABLE", "DOMHTMLTableElement");
}
protected FileWriter getWriter() {
return out;
}
protected FileWriter getWriter2() {
return out2;
}
public void flush() throws BadLocationException {
}
public void handleText(char[] data, int pos) {
getScript(data);
}
private void getScript(char [] data) {
if(script) {
System.out.print(data);
try {
out2.write(data);
out2.write("\n");
} catch (IOException e) {
System.out.println("Error writing to second file");
}
}
}
public void handleComment(char[] data, int pos) {
getScript(data);
}
protected String createElement(HTML.Tag t, MutableAttributeSet a) {
String tag = t.toString().toUpperCase();
String varName = "node" + (counter++);
String cons = (String)constructors.get(tag);
if(tag.equals("SCRIPT")) {
Object value = a.getAttribute( HTML.Attribute.SRC );
// script is out-of-line
if (value != null) {
try {
URL scriptSrc = new URL(input, value.toString());
InputStreamReader scriptReader =
new InputStreamReader(
scriptSrc.openConnection().getInputStream());
int read;
char[] buffer = new char[ 1024 ];
while ( (read = scriptReader.read(buffer)) != -1 ) {
out2.write(buffer, 0, read);
}
scriptReader.close();
} catch (IOException e) {
System.out.println("bad input script " + value);
}
// script is inline
} else {
System.out.println("Entering Script");
script = true;
}
}
if(cons == null) cons = "DOMHTMLElement";
try {
writeElement(t, a, tag, cons, varName);
Enumeration enu = a.getAttributeNames();
while(enu.hasMoreElements()) {
Object attrObj = enu.nextElement();
String attr = attrObj.toString();
String value = a.getAttribute(attrObj).toString();
System.out.println(attr);
writeAttribute(t, a, attr, value, varName);
}
out.write("\n");
} catch (IOException e) {
System.out.println("Error writing to file");
System.exit(1);
}
return varName;
}
protected void writeElement(HTML.Tag t, MutableAttributeSet a, String tag, String cons, String varName) throws IOException {
out.write("var " + varName + " = new " + cons + "(" + tag + ");\n");
if(!stack.empty()) {
out.write(stack.peek() + ".appendChild(" + varName + ");\n");
} else {
out.write("document.appendChild(" + varName + ");\n");
}
}
protected void writeAttribute(HTML.Tag t, MutableAttributeSet a, String attr, String value, String varName) throws IOException {
writePortletAttribute(t, a, attr, value, varName);
writeEventAttribute(t, a, attr, value, varName);
}
protected void writeEventAttribute(HTML.Tag t, MutableAttributeSet a, String attr, String value, String varName) throws IOException {
if(attr.substring(0,2).equals("on")) {
out.write(varName + "." + attr + " = function " + attr + "_" + varName + "(event) {" + value + "};\n");
out2.write("\n\n" + varName + "." + attr + "(null);\n\n");
} else {
out.write(varName + ".setAttribute('" + attr + "', '" + value + "');\n");
}
}
protected void writePortletAttribute(HTML.Tag t, MutableAttributeSet a, String attr, String value, String varName) throws IOException {
if(attr.equals("portletid")) {
if(value.substring(value.length()-4).equals("vice")) {
out.write("\n\nfunction cVice() { var contextVice = " + varName + "; }\ncVice();\n\n");
} else if(value.substring(value.length()-4).equals("root")) {
out.write("\n\nfunction cRoot() { var contextRoot = " + varName + "; }\ncRoot();\n\n");
}
}
}
public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
System.out.println("Start" + t);
String varName = createElement(t,a);
stack.push(varName);
}
public void handleEndTag(HTML.Tag t, int pos) {
if(t.toString().toUpperCase().equals("SCRIPT")) {
System.out.println("Exiting Script");
script = false;
}
System.out.println("End" + t);
stack.pop();
}
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
System.out.println("Simple" + t);
createElement(t,a);
}
public void handleError(String errorMsg, int pos) {
System.out.println("Error" + errorMsg);
}
public void handleEndOfLineString(String eol) {
System.out.println("EOL");
}
}

View File

@ -0,0 +1,56 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.util;
import java.io.*;
import java.net.*;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.debug.Trace;
import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.util.warnings.*;
public class WebUtil {
private static final String outputDir;
private static final Generator defaultGenerator = new Generator();
static {
String dir = System.getProperty("java.io.tmpdir");
if (! dir.endsWith(File.separator))
dir = dir + File.separator;
outputDir = dir;
}
public static SourceFileModule extractScriptFromHTML(URL url) {
return extractScriptFromHTML(url, defaultGenerator);
}
public static SourceFileModule extractScriptFromHTML(URL url, Generator generator) {
try {
String urlFile = url.getFile();
String urlName = urlFile.substring(urlFile.lastIndexOf('/'));
File F = new File(outputDir + urlName);
Trace.println("making driver at " + F + " " + outputDir);
if (F.exists()) F.delete();
generator.generate(url, F);
return new SourceFileModule(F, urlName.substring(1));
} catch (IOException e) {
Assertions.UNREACHABLE("error processing " + url + ": " + e);
return null;
}
}
}

View File

@ -0,0 +1,42 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.ipa.callgraph.JSZeroXCFABuilder;
import com.ibm.wala.cast.js.ipa.callgraph.Util;
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.Entrypoints;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.util.warnings.WarningSet;
class dumpCallGraph {
public static void main(String[] args) throws Exception {
WarningSet warnings = new WarningSet();
JavaScriptLoaderFactory loaders = Util.makeLoaders();
AnalysisScope scope = Util.makeScope( args, loaders );
ClassHierarchy cha = Util.makeHierarchy( scope, loaders, warnings );
Entrypoints roots = Util.makeScriptRoots( cha );
AnalysisOptions options = Util.makeOptions(scope, false, cha, roots, warnings);
JSCFABuilder builder = new JSZeroXCFABuilder(cha, warnings, options, null, null, null, ZeroXInstanceKeys.ALLOCATIONS);
CallGraph cg = builder.makeCallGraph( options );
System.err.println( cg );
}
}

View File

@ -0,0 +1,42 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
import java.io.FileReader;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.Parser;
import org.mozilla.javascript.ScriptOrFnNode;
import org.mozilla.javascript.tools.ToolErrorReporter;
class dumpRhinoParse {
public static void main(String[] args) {
try {
ToolErrorReporter reporter = new ToolErrorReporter(true);
CompilerEnvirons compilerEnv = new CompilerEnvirons();
compilerEnv.setErrorReporter(reporter);
Parser P = new Parser(compilerEnv, compilerEnv.getErrorReporter());
ScriptOrFnNode N = P.parse(new FileReader(args[0]), args[0], 1);
System.out.println( N.toStringTree(N) );
System.out.println( P.getEncodedSource() );
}
catch (Exception e) {
System.err.println( e.getMessage() );
}
}
}

View File

@ -0,0 +1,599 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.FunctionNode;
import org.mozilla.javascript.Node;
import org.mozilla.javascript.Parser;
import org.mozilla.javascript.ScriptOrFnNode;
import org.mozilla.javascript.Token;
import org.mozilla.javascript.tools.ToolErrorReporter;
class walkRhinoTree {
private final Map results = new HashMap();
private int nextValue = 1;
private int nextValueNumber() {
return nextValue++;
}
private int setValue(Node n, int v) {
results.put(n, new Integer(v));
return v;
}
private int allocValue(Node n) {
return setValue(n, nextValueNumber());
}
private int getValue(Node n) {
return ((Integer)results.get(n)).intValue();
}
private interface Symbol {
int valueNumber();
boolean isParameter();
}
private final static int TYPE_LOCAL = 1;
private final static int TYPE_GLOBAL = 2;
private final static int TYPE_SCRIPT = 3;
private final static int TYPE_FUNCTION = 4;
private interface Scope {
int type();
void declare(String name);
boolean contains(String name);
Symbol lookup(String name);
}
private static abstract class AbstractScope implements Scope {
private final Scope parent;
private final Map values = new HashMap();
public void declare(String nm) {
if (! contains(nm)) {
values.put(nm, makeSymbol(nm));
}
}
AbstractScope(Scope parent) {
this.parent = parent;
}
abstract protected Symbol makeSymbol(String nm);
public Symbol lookup(String nm) {
if (contains(nm))
return (Symbol)values.get(nm);
else
return parent.lookup(nm);
}
public boolean contains(String nm) {
return values.containsKey(nm);
}
};
Scope makeScriptScope(final ScriptOrFnNode s, Scope parent) {
return new AbstractScope(parent) {
public int type() { return TYPE_SCRIPT; }
protected Symbol makeSymbol(final String nm) {
final int v = nextValueNumber();
return
new Symbol() {
public String toString() { return nm; }
public int valueNumber() { return v; }
public boolean isParameter() { return false; }
};
}
};
}
Scope makeLocalScope(Node s, Scope parent) {
return new AbstractScope(parent) {
public int type() { return TYPE_LOCAL; }
protected Symbol makeSymbol(final String nm) {
final int v = nextValueNumber();
return
new Symbol() {
public String toString() { return nm; }
public int valueNumber() { return v; }
public boolean isParameter() { return false; }
};
}
};
}
Scope makeFunctionScope(final FunctionNode f, Scope parent) {
Scope s = new AbstractScope(parent) {
public int type() { return TYPE_FUNCTION; }
protected Symbol makeSymbol(final String nm) {
final int v = nextValueNumber();
return
new Symbol() {
public String toString() { return nm; }
public int valueNumber() { return v; }
public boolean isParameter() {
return f.getParamOrVarIndex(nm)<f.getParamCount();
}
};
}
};
for(int i = 0; i < f.getParamCount(); i++)
s.declare( f.getParamOrVarName(i) );
return s;
}
private static Scope makeGlobalScope() {
return new Scope() {
public int type() { return TYPE_GLOBAL; }
public void declare(String nm) {
throw new UnsupportedOperationException();
}
public boolean contains(String nm) {
return nm.equals("Math");
}
public Symbol lookup(String nm) {
return new Symbol() {
public String toString() { return "Math"; }
public int valueNumber() { return -1; }
public boolean isParameter() { return false; }
};
}
};
}
private interface WalkContext {
ScriptOrFnNode top();
Scope scope();
boolean resultWanted();
Node getCatchFor(Object exceptionType);
Node getBreakFor(Object label);
Node getContinueFor(Object label);
Node getFinally();
}
private abstract class DelegatingContext implements WalkContext {
private final WalkContext parent;
DelegatingContext(WalkContext parent) {
this.parent = parent;
}
public ScriptOrFnNode top() { return parent.top(); }
public Scope scope() { return parent.scope(); }
public boolean resultWanted() { return parent.resultWanted(); }
public Node getCatchFor(Object l) { return parent.getCatchFor(l); }
public Node getBreakFor(Object l) { return parent.getBreakFor(l); }
public Node getContinueFor(Object l) { return parent.getContinueFor(l); }
public Node getFinally() { return parent.getFinally(); }
}
private class ScriptContext extends DelegatingContext {
private final Scope scriptScope;
ScriptContext(WalkContext parent, Scope scriptScope) {
super(parent);
this.scriptScope = scriptScope;
}
public Scope scope() { return scriptScope; }
}
private class LocalContext extends DelegatingContext {
private final Scope localScope;
LocalContext(WalkContext parent, Scope localScope) {
super(parent);
this.localScope = localScope;
}
public Scope scope() { return localScope; }
}
private class FunctionContext extends ScriptContext {
private final ScriptOrFnNode topNode;
FunctionContext(WalkContext parent, Scope funScope, ScriptOrFnNode s) {
super(parent, funScope);
this.topNode = s;
}
public ScriptOrFnNode top() { return topNode; }
}
private class LoopContext extends DelegatingContext {
private final Node breakTo;
private final Node continueTo;
LoopContext(WalkContext parent, Node breakTo, Node continueTo) {
super(parent);
this.breakTo = breakTo;
this.continueTo = continueTo;
}
public Node getBreakFor(Object l) {
return (l == null)? breakTo: super.getBreakFor(l);
}
public Node getContinueFor(Object l) {
return (l == null)? continueTo: super.getContinueFor(l);
}
}
private class TryCatchContext extends DelegatingContext {
private final Node catchNode;
private final Node finallyNode;
TryCatchContext(WalkContext parent, Node catchNode, Node finallyNode) {
super(parent);
this.catchNode = catchNode;
this.finallyNode = finallyNode;
}
public Node getCatchFor(Object l) { return catchNode; }
public Node getFinally() { return finallyNode; }
}
private void walkNodes(final Node n, WalkContext context) {
if (n instanceof ScriptOrFnNode) {
WalkContext child;
if (n instanceof FunctionNode) {
FunctionNode f = (FunctionNode)n;
System.err.println("function " + f.getFunctionName());
child = new FunctionContext(context, makeFunctionScope(f, context.scope()), f);
} else {
ScriptOrFnNode s = (ScriptOrFnNode)n;
System.err.println("program");
child = new ScriptContext(context, makeScriptScope(s, context.scope()));
}
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
walkNodes(c, child);
} else {
int NT = n.getType();
switch (NT) {
case Token.FUNCTION: {
int fnIndex = n.getExistingIntProp(Node.FUNCTION_PROP);
FunctionNode fn = context.top().getFunctionNode(fnIndex);
System.err.println("declaring " + fn.getFunctionName() );
context.scope().declare( fn.getFunctionName() );
walkNodes(fn, context);
break;
}
case Token.LOOP: {
Node contTo = ((Node.Jump)n).getContinue();
Node breakTo = ((Node.Jump)n).target;
WalkContext child = new LoopContext(context, breakTo, contTo);
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
walkNodes(c, child);
break;
}
case Token.LOCAL_BLOCK: {
WalkContext child = new LocalContext(context, makeLocalScope(n, context.scope()));
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
walkNodes(c, child);
break;
}
case Token.CATCH_SCOPE: {
Node id = n.getFirstChild();
context.scope().declare( id.getString() );
System.err.println( context.scope().lookup( id.getString() ).valueNumber() + " = caught exception");
break;
}
case Token.TRY: {
Node catchNode = ((Node.Jump)n).target;
Node finallyNode = ((Node.Jump)n).getFinally();
WalkContext child =
new TryCatchContext(context, catchNode, finallyNode);
Node c = n.getFirstChild();
for (; c != null; c = c.getNext()) {
if (c.getType() == Token.FINALLY) break;
walkNodes(c, child);
}
for (; c != null; c = c.getNext()) {
walkNodes(c, context);
}
break;
}
case Token.JSR: {
Node jsrTarget = ((Node.Jump)n).target;
Node finallyBlock = context.getFinally();
if (jsrTarget != finallyBlock) throw new Error();
Node finallyNode = jsrTarget.getNext();
walkNodes(finallyNode, context);
break;
}
case Token.WITH:
case Token.FINALLY:
case Token.BLOCK:
case Token.LABEL:
case Token.EXPR_VOID: {
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
walkNodes(c, context);
break;
}
case Token.CALL: {
int result = allocValue(n);
Node callee = n.getFirstChild();
int fun;
if (callee.getType() == Token.NAME)
fun = context.scope().lookup( callee.getString() ).valueNumber();
else {
walkNodes( callee, context );
fun = getValue( callee );
}
int children = 0;
for (Node c = callee.getNext(); c != null; c = c.getNext()) {
walkNodes(c, context);
children++;
}
int i = 0;
int arguments[] = new int[ children ];
for(Node arg = callee.getNext(); arg != null; arg = arg.getNext() )
arguments[i++] = getValue( arg );
System.err.print(result + " = CALL " + fun);
for(int j = 0; j < arguments.length; j++)
System.err.print( " " + arguments[j] );
System.err.print("\n");
break;
}
case Token.NAME: {
setValue(n, context.scope().lookup( n.getString() ).valueNumber() );
break;
}
case Token.STRING: {
int result = allocValue(n);
System.err.println(result + " = \"" + n.getString() + "\"");
break;
}
case Token.NUMBER: {
int result = allocValue(n);
System.err.println(result + " = " + n.getDouble());
break;
}
case Token.ADD:
case Token.EQ:
case Token.DIV:
case Token.NE:
case Token.GT:
case Token.LT: {
int result = allocValue(n);
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
walkNodes(c, context);
Node l = n.getFirstChild();
Node r = l.getNext();
System.err.println(result + " = " + getValue(l) + " " + Token.name(NT) + " " + getValue(r));
break;
}
case Token.VAR: {
Node nm = n.getFirstChild();
context.scope().declare(nm.getString());
if (nm.getFirstChild() != null) {
walkNodes( nm.getFirstChild(), context );
System.err.println(context.scope().lookup(nm.getString()) + " = " + getValue(nm.getFirstChild()) );
}
break;
}
case Token.RETURN: {
Node val = n.getFirstChild();
if (val != null) {
walkNodes(val, context);
System.err.println("return " + getValue(val));
} else {
System.err.println("return");
}
break;
}
case Token.SETNAME: {
Node nm = n.getFirstChild();
walkNodes( nm.getNext(), context);
System.err.println("set " + context.scope().lookup(nm.getString()).valueNumber() + "(" + nm.getString() + ") = " + getValue( nm.getNext() ));
break;
}
case Token.IFNE:
case Token.IFEQ: {
Node expr = n.getFirstChild();
walkNodes( expr, context );
System.err.println(Token.name(NT) + " " + getValue(expr) + " GOTO " + ((Node.Jump)n).target);
break;
}
case Token.GOTO: {
System.err.println("GOTO (" + Token.name(NT) + ") " + ((Node.Jump)n).target);
break;
}
case Token.BREAK: {
System.err.println("GOTO (" + Token.name(NT) + ") " + ((Node.Jump)n).getJumpStatement().target);
break;
}
case Token.TARGET: {
System.err.println("LABEL " + n);
break;
}
case Token.OR: {
Object label = new Object() { public String toString() { return "OR:" + System.identityHashCode(n); } };
Node l = n.getFirstChild();
walkNodes(l, context);
System.err.println(getValue(n) + " = " + getValue(l));
System.err.println("IFEQ " + getValue(n) + " GOTO " + label);
Node r = l.getNext();
walkNodes(r, context);
System.err.println(getValue(n) + " = " + getValue(r));
System.err.println("LABEL " + label);
break;
}
case Token.INC: {
int result = context.resultWanted()? allocValue(n): -1;
Node l = n.getFirstChild();
walkNodes(l, context);
int flags = n.getIntProp( Node.INCRDECR_PROP, -1 );
String op = ((flags&Node.DECR_FLAG)!=0)? "-": "+";
if ((flags&Node.POST_FLAG)!=0) {
if (context.resultWanted())
System.err.println(result + " = " + getValue(l));
System.err.println(getValue(l) + " = " + getValue(l) + " " + op + " 1");
} else {
System.err.println(getValue(l) + " = " + getValue(l) + " " + op + " 1");
if (context.resultWanted())
System.err.println(result + " = " + getValue(l));
}
break;
}
case Token.EMPTY:
case Token.ENTERWITH:
case Token.LEAVEWITH: {
break;
}
case Token.GETPROP:
case Token.GETELEM: {
int result = allocValue(n);
Node receiver = n.getFirstChild();
walkNodes(receiver, context);
Node elt = receiver.getNext();
if (elt.getType() == Token.STRING) {
System.err.println(result + " = getfield " + getValue(receiver) + "." + elt.getString());
} else {
walkNodes(elt, context);
System.err.println(result + " = reflective getfield " + getValue(receiver) + "." + getValue(elt));
}
break;
}
case Token.THROW: {
Node catchTarget = context.getCatchFor( null );
Node throwVal = n.getFirstChild();
walkNodes(throwVal, context);
if (catchTarget != null) {
System.err.println("THROW of " + getValue(throwVal) + " to " + catchTarget);
} else {
System.err.println("THROW out of " + getValue(throwVal));
}
break;
}
default: {
System.err.println("looking at unhandled " + n + "(" + NT + ")" + " of " + n.getClass());
for (Node c = n.getFirstChild(); c != null; c = c.getNext())
System.err.println(" with child " + c);
}
}
}
}
public static void main(String[] args) throws Exception {
ToolErrorReporter reporter = new ToolErrorReporter(true);
CompilerEnvirons compilerEnv = new CompilerEnvirons();
compilerEnv.setErrorReporter(reporter);
Parser P = new Parser(compilerEnv, compilerEnv.getErrorReporter());
final ScriptOrFnNode N = P.parse(new FileReader(args[0]), args[0], 1);
walkRhinoTree walker = new walkRhinoTree();
final Scope G = makeGlobalScope();
walker.walkNodes( N,
new WalkContext() {
public ScriptOrFnNode top() { return N; }
public Scope scope() { return G; }
public boolean resultWanted() { return true; }
public Node getCatchFor(Object exceptionType) { return null; }
public Node getBreakFor(Object label) { return null; }
public Node getContinueFor(Object label) { return null; }
public Node getFinally() { return null; }
} );
}
}