blunt force trauma to CAst frond end:

1) Structural changes in the AstTranslator to allow retranslation and generation of custom IR.  This is mostly moving state from the translator itself into the context.
2) Some refactoring to share some AST generation code across the Java and JavaScript front ends.
3) Switching to the latest Rhino, release 1.7R3; this is a pervasive change to the JavaScript Rhino translator, since it involves switching to the new AST interface in Rhino.
4) Common code to, as an option, translate Do-style loops by replicating the loop body.  This allows the use of CAstNode.LOOP forms for such loops.
5) Some bug fixes to the mechanisms of the CAstRewriter to handle weird control flow cases.
6) An example of retranslation to specialize JavaScript methods based on how many arguments they receive at call sites.


git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4425 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
dolby-oss 2012-01-27 20:15:33 +00:00
parent 5a3470a674
commit 4c6d062dbb
60 changed files with 4863 additions and 1282 deletions

View File

@ -128,10 +128,11 @@ import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement; import org.eclipse.jdt.core.dom.WhileStatement;
import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol; import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.DoLoopTranslator;
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl; import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
import com.ibm.wala.cast.java.loader.Util; import com.ibm.wala.cast.java.loader.Util;
import com.ibm.wala.cast.java.translator.JavaProcedureEntity; import com.ibm.wala.cast.java.translator.JavaProcedureEntity;
import com.ibm.wala.cast.java.translator.TranslatorToCAst;
import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap; import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
@ -175,7 +176,7 @@ import com.ibm.wala.util.debug.Assertions;
// * enums (probably in simplename or something. but using resolveConstantExpressionValue() possible) // * enums (probably in simplename or something. but using resolveConstantExpressionValue() possible)
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class JDTJava2CAstTranslator implements TranslatorToCAst { public class JDTJava2CAstTranslator {
protected final CAst fFactory = new CAstImpl(); protected final CAst fFactory = new CAstImpl();
// /////////////////////////////////////////// // ///////////////////////////////////////////
@ -203,6 +204,8 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
protected ITypeBinding OutOfMemoryError; protected ITypeBinding OutOfMemoryError;
protected DoLoopTranslator doLoopTranslator;
private String fullPath; private String fullPath;
private CompilationUnit cu; private CompilationUnit cu;
@ -211,20 +214,7 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
// COMPILATION UNITS & TYPES // COMPILATION UNITS & TYPES
// //
public JDTJava2CAstTranslator(JavaSourceLoaderImpl sourceLoader) { public JDTJava2CAstTranslator(JavaSourceLoaderImpl sourceLoader, CompilationUnit astRoot, String fullPath, boolean replicateForDoLoops) {
this.fSourceLoader = sourceLoader;
}
public CAstEntity translate(Object astRoot, String fullPath) {
this.cu = (CompilationUnit) astRoot;
this.fullPath = fullPath;
ast = cu.getAST();
// FIXME: we might need one AST (-> "Object" class) for all files.
fIdentityMapper = new JDTIdentityMapper(fSourceLoader.getReference(), ast);
fTypeDict = new JDTTypeDictionary(ast, fIdentityMapper);
fDivByZeroExcType = FakeExceptionTypeBinding.arithmetic; fDivByZeroExcType = FakeExceptionTypeBinding.arithmetic;
fNullPointerExcType = FakeExceptionTypeBinding.nullPointer; fNullPointerExcType = FakeExceptionTypeBinding.nullPointer;
fClassCastExcType = FakeExceptionTypeBinding.classCast; fClassCastExcType = FakeExceptionTypeBinding.classCast;
@ -232,12 +222,27 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
ExceptionInInitializerError = FakeExceptionTypeBinding.initException; ExceptionInInitializerError = FakeExceptionTypeBinding.initException;
OutOfMemoryError = FakeExceptionTypeBinding.outOfMemory; OutOfMemoryError = FakeExceptionTypeBinding.outOfMemory;
this.fSourceLoader = sourceLoader;
this.cu = astRoot;
this.fullPath = fullPath;
ast = cu.getAST();
this.doLoopTranslator = new DoLoopTranslator(replicateForDoLoops, fFactory);
// FIXME: we might need one AST (-> "Object" class) for all files.
fIdentityMapper = new JDTIdentityMapper(fSourceLoader.getReference(), ast);
fTypeDict = new JDTTypeDictionary(ast, fIdentityMapper);
fRuntimeExcType = ast.resolveWellKnownType("java.lang.RuntimeException"); fRuntimeExcType = ast.resolveWellKnownType("java.lang.RuntimeException");
assert fRuntimeExcType != null; assert fRuntimeExcType != null;
}
public CAstEntity translateToCAst() {
List<CAstEntity> declEntities = new ArrayList<CAstEntity>(); List<CAstEntity> declEntities = new ArrayList<CAstEntity>();
for (Iterator iter = cu.types().iterator(); iter.hasNext();) { for (Iterator<CAstEntity> iter = cu.types().iterator(); iter.hasNext();) {
AbstractTypeDeclaration decl = (AbstractTypeDeclaration) iter.next(); AbstractTypeDeclaration decl = (AbstractTypeDeclaration) iter.next();
// can be of type AnnotationTypeDeclaration, EnumDeclaration, TypeDeclaration // can be of type AnnotationTypeDeclaration, EnumDeclaration, TypeDeclaration
declEntities.add(visit(decl, new RootContext())); declEntities.add(visit(decl, new RootContext()));
@ -2095,7 +2100,6 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
// //////////////// // ////////////////
private CAstNode visit(LabeledStatement n, WalkContext context) { private CAstNode visit(LabeledStatement n, WalkContext context) {
ASTNode breakTarget = makeBreakOrContinueTarget(n, n.getLabel().getIdentifier());
// find the first non-block statement ant set-up the label map (useful for breaking many fors) // find the first non-block statement ant set-up the label map (useful for breaking many fors)
ASTNode stmt = n.getBody(); ASTNode stmt = n.getBody();
@ -2108,10 +2112,12 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
CAstNode result; CAstNode result;
if (!(n.getBody() instanceof EmptyStatement)) { if (!(n.getBody() instanceof EmptyStatement)) {
ASTNode breakTarget = makeBreakOrContinueTarget(n, n.getLabel().getIdentifier());
CAstNode breakNode = visitNode(breakTarget, context);
WalkContext child = new BreakContext(context, n.getLabel().getIdentifier(), breakTarget); WalkContext child = new BreakContext(context, n.getLabel().getIdentifier(), breakTarget);
result = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, makeNode(context, fFactory, n, CAstNode.LABEL_STMT, fFactory result = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, makeNode(context, fFactory, n, CAstNode.LABEL_STMT, fFactory
.makeConstant(n.getLabel().getIdentifier()), visitNode(n.getBody(), child)), visitNode(breakTarget, context)); .makeConstant(n.getLabel().getIdentifier()), visitNode(n.getBody(), child)), breakNode);
} else { } else {
result = makeNode(context, fFactory, n, CAstNode.LABEL_STMT, fFactory.makeConstant(n.getLabel().getIdentifier()), visitNode(n result = makeNode(context, fFactory, n, CAstNode.LABEL_STMT, fFactory.makeConstant(n.getLabel().getIdentifier()), visitNode(n
.getBody(), context)); .getBody(), context));
@ -2163,7 +2169,10 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
Statement body = n.getBody(); Statement body = n.getBody();
ASTNode breakTarget = makeBreakOrContinueTarget(n, "breakLabel" + n.getStartPosition()); ASTNode breakTarget = makeBreakOrContinueTarget(n, "breakLabel" + n.getStartPosition());
CAstNode breakNode = visitNode(breakTarget, context);
ASTNode continueTarget = makeBreakOrContinueTarget(n, "continueLabel" + n.getStartPosition()); ASTNode continueTarget = makeBreakOrContinueTarget(n, "continueLabel" + n.getStartPosition());
CAstNode continueNode = visitNode(continueTarget, context);
String loopLabel = (String) context.getLabelMap().get(n); String loopLabel = (String) context.getLabelMap().get(n);
LoopContext lc = new LoopContext(context, loopLabel, breakTarget, continueTarget); LoopContext lc = new LoopContext(context, loopLabel, breakTarget, continueTarget);
@ -2172,8 +2181,8 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
* The following loop is created sligtly differently than in jscore. It doesn't have a specific target for continue. * The following loop is created sligtly differently than in jscore. It doesn't have a specific target for continue.
*/ */
return makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, makeNode(context, fFactory, n, CAstNode.LOOP, visitNode(cond, return makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, makeNode(context, fFactory, n, CAstNode.LOOP, visitNode(cond,
context), makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, visitNode(body, lc), visitNode(continueTarget, context))), context), makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, visitNode(body, lc), continueNode)),
visitNode(breakTarget, context)); breakNode);
} }
private CAstNode getSwitchCaseConstant(SwitchCase n, WalkContext context) { private CAstNode getSwitchCaseConstant(SwitchCase n, WalkContext context) {
@ -2282,22 +2291,21 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
} }
private CAstNode visit(DoStatement n, WalkContext context) { private CAstNode visit(DoStatement n, WalkContext context) {
ASTNode header = ast.newEmptyStatement();
ASTNode breakTarget = makeBreakOrContinueTarget(n, "breakLabel" + n.getStartPosition());
ASTNode continueTarget = makeBreakOrContinueTarget(n, "continue" + "Label" + n.getStartPosition());
CAstNode loopGoto = makeNode(context, fFactory, n, CAstNode.IFGOTO, visitNode(n.getExpression(), context));
context.cfg().map(loopGoto, loopGoto);
context.cfg().add(loopGoto, header, Boolean.TRUE);
String loopLabel = (String) context.getLabelMap().get(n); // set by visit(LabeledStatement) String loopLabel = (String) context.getLabelMap().get(n); // set by visit(LabeledStatement)
WalkContext loopContext = new LoopContext(context, loopLabel, breakTarget, continueTarget); String token = loopLabel==null? "at_" + n.getStartPosition(): loopLabel;
ASTNode breakTarget = makeBreakOrContinueTarget(n, "breakLabel_" + token);
CAstNode breakNode = visitNode(breakTarget, context);
ASTNode continueTarget = makeBreakOrContinueTarget(n, "continueLabel_" + token);
CAstNode continueNode = visitNode(continueTarget, context); CAstNode continueNode = visitNode(continueTarget, context);
CAstNode loopTest = visitNode(n.getExpression(), context);
return makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, visitNode(header, context), makeNode(context, fFactory, n, WalkContext loopContext = new LoopContext(context, loopLabel, breakTarget, continueTarget);
CAstNode.BLOCK_STMT, visitNode(n.getBody(), loopContext), continueNode), loopGoto, visitNode(breakTarget, context)); CAstNode loopBody = visitNode(n.getBody(), loopContext);
return doLoopTranslator.translateDoLoop(loopTest, loopBody, continueNode, breakNode, context);
} }
/** /**
@ -2889,24 +2897,12 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
* Contains things needed by in the visit() of some nodes to process the nodes. For example, pos() contains the source position * Contains things needed by in the visit() of some nodes to process the nodes. For example, pos() contains the source position
* mapping which each node registers * mapping which each node registers
*/ */
public static interface WalkContext { public static interface WalkContext extends TranslatorToCAst.WalkContext<WalkContext, ASTNode> {
// LEFTOUT: plenty of stuff
public CAstControlFlowRecorder cfg();
public void addScopedEntity(CAstNode newNode, CAstEntity visit);
public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type); public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type);
public CAstSourcePositionRecorder pos();
public CAstNodeTypeMapRecorder getNodeTypeMap();
public Map<ASTNode, String> getLabelMap(); public Map<ASTNode, String> getLabelMap();
public ASTNode getContinueFor(String label);
public ASTNode getBreakFor(String label);
public boolean needLValue(); public boolean needLValue();
} }
@ -2914,46 +2910,21 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
* Default context functions. When one context doesn't handle something, it the next one up does. For example, there is only one * Default context functions. When one context doesn't handle something, it the next one up does. For example, there is only one
* source pos. mapping per MethodContext, so loop contexts delegate it up. * source pos. mapping per MethodContext, so loop contexts delegate it up.
*/ */
public static class DelegatingContext implements WalkContext { public static class DelegatingContext extends TranslatorToCAst.DelegatingContext<WalkContext, ASTNode> implements WalkContext {
protected WalkContext parent;
public DelegatingContext(WalkContext parent) { public DelegatingContext(WalkContext parent) {
this.parent = parent; super(parent);
}
public CAstControlFlowRecorder cfg() {
return parent.cfg();
}
public CAstSourcePositionRecorder pos() {
return parent.pos();
}
public CAstNodeTypeMapRecorder getNodeTypeMap() {
return parent.getNodeTypeMap();
} }
public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type) { public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type) {
return parent.getCatchTargets(type); return parent.getCatchTargets(type);
} }
public void addScopedEntity(CAstNode newNode, CAstEntity visit) {
parent.addScopedEntity(newNode, visit);
}
public Map<ASTNode, String> getLabelMap() { public Map<ASTNode, String> getLabelMap() {
return parent.getLabelMap(); return parent.getLabelMap();
} }
public ASTNode getContinueFor(String label) { public boolean needLValue() {
return parent.getContinueFor(label);
}
public ASTNode getBreakFor(String label) {
return parent.getBreakFor(label);
}
public boolean needLValue() {
return parent.needLValue(); return parent.needLValue();
} }
} }
@ -2961,27 +2932,8 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
/* /*
* Root context. Doesn't do anything. * Root context. Doesn't do anything.
*/ */
public static class RootContext implements WalkContext { public static class RootContext extends TranslatorToCAst.RootContext<WalkContext, ASTNode> implements WalkContext {
public void addScopedEntity(CAstNode newNode, CAstEntity visit) { public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type) {
Assertions.UNREACHABLE("Rootcontext.addScopedEntity()");
}
public CAstControlFlowRecorder cfg() {
Assertions.UNREACHABLE("RootContext.cfg()");
return null;
}
public CAstSourcePositionRecorder pos() {
Assertions.UNREACHABLE("RootContext.pos()");
return null;
}
public CAstNodeTypeMapRecorder getNodeTypeMap() {
Assertions.UNREACHABLE("RootContext.getNodeTypeMap()");
return null;
}
public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type) {
Assertions.UNREACHABLE("RootContext.getCatchTargets()"); Assertions.UNREACHABLE("RootContext.getCatchTargets()");
return null; return null;
} }
@ -2991,16 +2943,6 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
return null; return null;
} }
public ASTNode getBreakFor(String label) {
Assertions.UNREACHABLE("RootContext.getBreakFor()");
return null;
}
public ASTNode getContinueFor(String label) {
Assertions.UNREACHABLE("RootContext.getContinueFor()");
return null;
}
public boolean needLValue() { public boolean needLValue() {
Assertions.UNREACHABLE("Rootcontext.needLValue()"); Assertions.UNREACHABLE("Rootcontext.needLValue()");
return false; return false;

View File

@ -115,8 +115,6 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator {
public void loadAllSources(Set<ModuleEntry> modules) { public void loadAllSources(Set<ModuleEntry> modules) {
// TODO: we might need one AST (-> "Object" class) for all files. // TODO: we might need one AST (-> "Object" class) for all files.
// TODO: group by project and send 'em in // TODO: group by project and send 'em in
JDTJava2CAstTranslator jdt2cast = makeCAstTranslator();
final Java2IRTranslator java2ir = makeIRTranslator(jdt2cast);
System.out.println(modules); System.out.println(modules);
@ -143,7 +141,9 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator {
public void acceptAST(ICompilationUnit source, CompilationUnit ast) { public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
try { try {
java2ir.translate(proj.getValue().get(source), ast, source.getUnderlyingResource().getLocation().toOSString()); JDTJava2CAstTranslator jdt2cast = makeCAstTranslator(ast, source.getUnderlyingResource().getLocation().toOSString());
final Java2IRTranslator java2ir = makeIRTranslator();
java2ir.translate(proj.getValue().get(source), jdt2cast.translateToCAst());
} catch (JavaModelException e) { } catch (JavaModelException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -165,12 +165,12 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator {
} }
} }
protected Java2IRTranslator makeIRTranslator(JDTJava2CAstTranslator jdt2cast) { protected Java2IRTranslator makeIRTranslator() {
return new Java2IRTranslator(jdt2cast, sourceLoader); return new Java2IRTranslator(sourceLoader);
} }
protected JDTJava2CAstTranslator makeCAstTranslator() { protected JDTJava2CAstTranslator makeCAstTranslator(CompilationUnit cu, String fullPath) {
return new JDTJava2CAstTranslator(sourceLoader); return new JDTJava2CAstTranslator(sourceLoader, cu, fullPath, false);
} }
} }

View File

@ -51,16 +51,18 @@ public class IRGoal extends SourceGoal_c /* PORT1.7 removed 'implements EndGoal'
ExtensionInfo extInfo= job.extensionInfo(); ExtensionInfo extInfo= job.extensionInfo();
fTranslator= new Java2IRTranslator( fTranslator= new Java2IRTranslator(
fSourceLoader,
((IRTranslatorExtension)extInfo).getCAstRewriterFactory());
ModuleSource src = (ModuleSource) job.source();
fTranslator.translate(
src.getModule(),
new PolyglotJava2CAstTranslator( new PolyglotJava2CAstTranslator(
job.ast(),
fSourceLoader.getReference(), fSourceLoader.getReference(),
extInfo.nodeFactory(), extInfo.nodeFactory(),
extInfo.typeSystem(), extInfo.typeSystem(),
new PolyglotIdentityMapper(fSourceLoader.getReference()), new PolyglotIdentityMapper(fSourceLoader.getReference()),
((IRTranslatorExtension)extInfo).getReplicateForDoLoops()), ((IRTranslatorExtension)extInfo).getReplicateForDoLoops()).translateToCAst());
fSourceLoader,
((IRTranslatorExtension)extInfo).getCAstRewriterFactory());
ModuleSource src = (ModuleSource) job.source();
fTranslator.translate(src.getModule(),job.ast(), src.name());
return true; return true;
} }

View File

@ -20,6 +20,7 @@ import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -34,6 +35,7 @@ import polyglot.ast.ArrayTypeNode;
import polyglot.ast.Assert; import polyglot.ast.Assert;
import polyglot.ast.Assign; import polyglot.ast.Assign;
import polyglot.ast.Binary; import polyglot.ast.Binary;
import polyglot.ast.Binary.Operator;
import polyglot.ast.Block; import polyglot.ast.Block;
import polyglot.ast.BooleanLit; import polyglot.ast.BooleanLit;
import polyglot.ast.Branch; import polyglot.ast.Branch;
@ -49,6 +51,7 @@ import polyglot.ast.ClassLit;
import polyglot.ast.ClassMember; import polyglot.ast.ClassMember;
import polyglot.ast.Conditional; import polyglot.ast.Conditional;
import polyglot.ast.ConstructorCall; import polyglot.ast.ConstructorCall;
import polyglot.ast.ConstructorCall.Kind;
import polyglot.ast.ConstructorDecl; import polyglot.ast.ConstructorDecl;
import polyglot.ast.Do; import polyglot.ast.Do;
import polyglot.ast.Empty; import polyglot.ast.Empty;
@ -94,8 +97,6 @@ import polyglot.ast.TopLevelDecl;
import polyglot.ast.Try; import polyglot.ast.Try;
import polyglot.ast.Unary; import polyglot.ast.Unary;
import polyglot.ast.While; import polyglot.ast.While;
import polyglot.ast.Binary.Operator;
import polyglot.ast.ConstructorCall.Kind;
import polyglot.types.ArrayType; import polyglot.types.ArrayType;
import polyglot.types.ClassType; import polyglot.types.ClassType;
import polyglot.types.CodeInstance; import polyglot.types.CodeInstance;
@ -117,9 +118,11 @@ import polyglot.types.Types;
import polyglot.util.Position; import polyglot.util.Position;
import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol; import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.DoLoopTranslator;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.WalkContext;
import com.ibm.wala.cast.java.loader.Util; import com.ibm.wala.cast.java.loader.Util;
import com.ibm.wala.cast.java.translator.JavaProcedureEntity; import com.ibm.wala.cast.java.translator.JavaProcedureEntity;
import com.ibm.wala.cast.java.translator.TranslatorToCAst;
import com.ibm.wala.cast.java.types.JavaType; import com.ibm.wala.cast.java.types.JavaType;
import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap; import com.ibm.wala.cast.tree.CAstControlFlowMap;
@ -132,12 +135,10 @@ import com.ibm.wala.cast.tree.CAstSymbol;
import com.ibm.wala.cast.tree.CAstType; import com.ibm.wala.cast.tree.CAstType;
import com.ibm.wala.cast.tree.CAstTypeDictionary; import com.ibm.wala.cast.tree.CAstTypeDictionary;
import com.ibm.wala.cast.tree.impl.AbstractSourcePosition; import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
import com.ibm.wala.cast.tree.impl.CAstCloner;
import com.ibm.wala.cast.tree.impl.CAstControlFlowRecorder; import com.ibm.wala.cast.tree.impl.CAstControlFlowRecorder;
import com.ibm.wala.cast.tree.impl.CAstImpl; import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.cast.tree.impl.CAstNodeTypeMapRecorder; import com.ibm.wala.cast.tree.impl.CAstNodeTypeMapRecorder;
import com.ibm.wala.cast.tree.impl.CAstOperator; import com.ibm.wala.cast.tree.impl.CAstOperator;
import com.ibm.wala.cast.tree.impl.CAstRewriter;
import com.ibm.wala.cast.tree.impl.CAstSourcePositionRecorder; import com.ibm.wala.cast.tree.impl.CAstSourcePositionRecorder;
import com.ibm.wala.cast.tree.impl.CAstSymbolImpl; import com.ibm.wala.cast.tree.impl.CAstSymbolImpl;
import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.CallSiteReference;
@ -155,8 +156,7 @@ import com.ibm.wala.util.collections.IteratorPlusOne;
import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.debug.Assertions;
@SuppressWarnings("unchecked") public class PolyglotJava2CAstTranslator {
public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
protected final CAst fFactory = new CAstImpl(); protected final CAst fFactory = new CAstImpl();
protected final NodeFactory fNodeFactory; protected final NodeFactory fNodeFactory;
@ -179,10 +179,12 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
protected PolyglotIdentityMapper fIdentityMapper; protected PolyglotIdentityMapper fIdentityMapper;
protected boolean replicateForDoLoops = false; protected final DoLoopTranslator doLoopTranslator;
protected final boolean DEBUG = true; protected final boolean DEBUG = true;
private final Node ast;
final protected TranslatingVisitor getTranslator() { final protected TranslatingVisitor getTranslator() {
if (fTranslator == null) if (fTranslator == null)
fTranslator = createTranslator(); fTranslator = createTranslator();
@ -1133,42 +1135,17 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
String loopLabel = (String) wc.getLabelMap().get(d); String loopLabel = (String) wc.getLabelMap().get(d);
CAstNode continueNode = walkNodes(continueTarget, wc); CAstNode continueNode = walkNodes(continueTarget, wc);
CAstNode breakBody = walkNodes(breakTarget, wc); CAstNode breakNode = walkNodes(breakTarget, wc);
WalkContext lc = new LoopContext(wc, loopLabel, breakTarget, continueTarget);
CAstNode loopBody = walkNodes(d.body(), lc);
if (replicateForDoLoops) { WalkContext lc = new LoopContext(wc, loopLabel, breakTarget, continueTarget);
CAstRewriter.Rewrite x = (new CAstCloner(fFactory, false)).copy(loopBody, wc.cfg(), wc.pos(), wc.getNodeTypeMap(), null); CAstNode loopExpr = walkNodes(d.cond(), wc);
CAstNode otherBody = x.newRoot(); CAstNode loopBody = walkNodes(d.body(), lc);
wc.cfg().addAll(x.newCfg());
wc.pos().addAll(x.newPos());
wc.getNodeTypeMap().addAll(x.newTypes());
return makeNode(wc, fFactory, d, CAstNode.BLOCK_STMT, return doLoopTranslator.translateDoLoop(loopExpr, loopBody, continueNode, breakNode, wc);
loopBody,
makeNode(wc, fFactory, d, CAstNode.LOOP,
walkNodes(d.cond(), wc),
makeNode(wc, fFactory, d, CAstNode.BLOCK_STMT, otherBody, continueNode)),
breakBody);
} else {
Node header = fNodeFactory.Empty(Position.COMPILER_GENERATED);
CAstNode loopGoto = makeNode(wc, fFactory, d, CAstNode.IFGOTO, walkNodes(d.cond(), wc));
wc.cfg().map(loopGoto, loopGoto);
wc.cfg().add(loopGoto, header, Boolean.TRUE);
return makeNode(wc, fFactory, d, CAstNode.BLOCK_STMT,
walkNodes(header, wc),
makeNode(wc, fFactory, d, CAstNode.BLOCK_STMT, loopBody, continueNode),
loopGoto,
breakBody);
}
} }
public CAstNode visit(For f, WalkContext wc) { public CAstNode visit(For f, WalkContext wc) {
Node breakTarget = makeBreakTarget(f); Node breakTarget = makeBreakTarget(f);
Node continueTarget = makeContinueTarget(f); Node continueTarget = makeContinueTarget(f);
@ -1529,12 +1506,8 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
protected abstract static class CodeBodyEntity implements CAstEntity { protected abstract static class CodeBodyEntity implements CAstEntity {
private final Map<CAstNode, Collection<CAstEntity>> fEntities; private final Map<CAstNode, Collection<CAstEntity>> fEntities;
public CodeBodyEntity(Map<CAstNode, CAstEntity> entities) { public CodeBodyEntity(Map<CAstNode, Collection<CAstEntity>> entities) {
fEntities = new LinkedHashMap<CAstNode, Collection<CAstEntity>>(); fEntities = new LinkedHashMap<CAstNode, Collection<CAstEntity>>(entities);
for (Iterator<CAstNode> keys = entities.keySet().iterator(); keys.hasNext();) {
CAstNode key = keys.next();
fEntities.put(key, Collections.singleton(entities.get(key)));
}
} }
public Map<CAstNode, Collection<CAstEntity>> getAllScopedEntities() { public Map<CAstNode, Collection<CAstEntity>> getAllScopedEntities() {
@ -1674,7 +1647,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
private final String[] argumentNames; private final String[] argumentNames;
public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, Type declaringType, String[] argumentNames, public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, Type declaringType, String[] argumentNames,
Map<CAstNode, CAstEntity> entities, MethodContext mc) { Map<CAstNode, Collection<CAstEntity>> entities, MethodContext mc) {
super(entities); super(entities);
fPdast = pdast; fPdast = pdast;
fSystem = system; fSystem = system;
@ -1685,7 +1658,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, String[] argumentNames, public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, String[] argumentNames,
Map<CAstNode, CAstEntity> entities, MethodContext mc) { Map<CAstNode, Collection<CAstEntity>> entities, MethodContext mc) {
//PORT1.7 used to be this(pdast, system, pd, ((MemberInstance) pd).container(), argumentNames, entities, mc); //PORT1.7 used to be this(pdast, system, pd, ((MemberInstance) pd).container(), argumentNames, entities, mc);
this(pdast, system, pd, ((MemberDef) pd.def()).container().get(), argumentNames, entities, mc); this(pdast, system, pd, ((MemberDef) pd.def()).container().get(), argumentNames, entities, mc);
} }
@ -1916,21 +1889,9 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
} }
public interface WalkContext { public interface WalkContext extends TranslatorToCAst.WalkContext<WalkContext, Node> {
void addScopedEntity(CAstNode node, CAstEntity e);
CAstControlFlowRecorder cfg();
CAstSourcePositionRecorder pos();
CAstNodeTypeMapRecorder getNodeTypeMap();
Collection<Pair<Type, Object>> getCatchTargets(Type label); Collection<Pair<Type, Object>> getCatchTargets(Type label);
Node getContinueFor(String label);
Node getBreakFor(String label);
Node getFinally(); Node getFinally();
CodeInstance getEnclosingMethod(); CodeInstance getEnclosingMethod();
@ -1948,49 +1909,15 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
boolean needLVal(); boolean needLVal();
} }
protected static class DelegatingContext implements WalkContext { protected static class DelegatingContext extends TranslatorToCAst.DelegatingContext<WalkContext, Node> implements WalkContext {
private final WalkContext parent;
public WalkContext getParent() {
return parent;
}
protected DelegatingContext(WalkContext parent) { protected DelegatingContext(WalkContext parent) {
this.parent = parent; super(parent);
}
public void addScopedEntity(CAstNode node, CAstEntity e) {
parent.addScopedEntity(node, e);
}
// public Map/*<CAstNode,CAstEntity>*/ getScopedEntities() {
// return parent.getScopedEntities();
// }
public CAstControlFlowRecorder cfg() {
return parent.cfg();
}
public CAstSourcePositionRecorder pos() {
return parent.pos();
}
public CAstNodeTypeMapRecorder getNodeTypeMap() {
return parent.getNodeTypeMap();
} }
public Collection<Pair<Type, Object>> getCatchTargets(Type label) { public Collection<Pair<Type, Object>> getCatchTargets(Type label) {
return parent.getCatchTargets(label); return parent.getCatchTargets(label);
} }
public Node getContinueFor(String label) {
return parent.getContinueFor(label);
}
public Node getBreakFor(String label) {
return parent.getBreakFor(label);
}
public Node getFinally() { public Node getFinally() {
return parent.getFinally(); return parent.getFinally();
} }
@ -2121,9 +2048,9 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
private final Map<Node, String> labelMap = HashMapFactory.make(2); private final Map<Node, String> labelMap = HashMapFactory.make(2);
private final Map<CAstNode, CAstEntity> fEntities; private final Map<CAstNode, Collection<CAstEntity>> fEntities;
public CodeBodyContext(WalkContext parent, Map<CAstNode, CAstEntity> entities) { public CodeBodyContext(WalkContext parent, Map<CAstNode, Collection<CAstEntity>> entities) {
super(parent); super(parent);
fEntities = entities; fEntities = entities;
} }
@ -2141,10 +2068,11 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
public void addScopedEntity(CAstNode node, CAstEntity entity) { public void addScopedEntity(CAstNode node, CAstEntity entity) {
fEntities.put(node, entity); if (! fEntities.containsKey(node)) { fEntities.put(node, new HashSet<CAstEntity>(1)); }
fEntities.get(node).add(entity);
} }
public Map/* <CAstNode,CAstEntity> */<CAstNode, CAstEntity> getScopedEntities() { public Map<CAstNode, Collection<CAstEntity>> getScopedEntities() {
return fEntities; return fEntities;
} }
@ -2160,7 +2088,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
public class MethodContext extends CodeBodyContext { public class MethodContext extends CodeBodyContext {
final CodeInstance fPI; final CodeInstance fPI;
public MethodContext(CodeInstance pi, Map<CAstNode, CAstEntity> entities, WalkContext parent) { public MethodContext(CodeInstance pi, Map<CAstNode, Collection<CAstEntity>> entities, WalkContext parent) {
super(parent, entities); super(parent, entities);
fPI = pi; fPI = pi;
} }
@ -2188,8 +2116,8 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
this.tryNode = tryNode; this.tryNode = tryNode;
this.context = context; this.context = context;
for (Iterator catchIter = tryNode.catchBlocks().iterator(); catchIter.hasNext();) { for (Iterator<Catch> catchIter = tryNode.catchBlocks().iterator(); catchIter.hasNext();) {
Catch c = (Catch) catchIter.next(); Catch c = catchIter.next();
Pair<Type,Object> p = Pair.make(c.catchType(), (Object)c); Pair<Type,Object> p = Pair.make(c.catchType(), (Object)c);
fCatchNodes.add(p); fCatchNodes.add(p);
@ -2217,7 +2145,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
continue; continue;
} }
} }
catchNodes.addAll(getParent().getCatchTargets(label)); catchNodes.addAll(parent.getCatchTargets(label));
return catchNodes; return catchNodes;
} }
@ -2230,53 +2158,23 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
} }
protected static class RootContext implements WalkContext { protected static class RootContext extends TranslatorToCAst.RootContext<WalkContext, Node> implements WalkContext {
final CAstTypeDictionary fTypeDict; final CAstTypeDictionary fTypeDict;
public RootContext(CAstTypeDictionary typeDict) { public RootContext(CAstTypeDictionary typeDict) {
fTypeDict = typeDict; fTypeDict = typeDict;
} }
public void addScopedEntity(CAstNode node, CAstEntity e) {
Assertions.UNREACHABLE("Attempt to call addScopedEntity() on a RootContext.");
}
public CAstControlFlowRecorder cfg() {
Assertions.UNREACHABLE("RootContext.cfg()");
return null;
}
public Collection<Pair<Type, Object>> getCatchTargets(Type label) { public Collection<Pair<Type, Object>> getCatchTargets(Type label) {
Assertions.UNREACHABLE("RootContext.getCatchTargets()"); Assertions.UNREACHABLE("RootContext.getCatchTargets()");
return null; return null;
} }
public CAstNodeTypeMapRecorder getNodeTypeMap() {
Assertions.UNREACHABLE("RootContext.getNodeTypeMap()");
return null;
}
public Node getFinally() { public Node getFinally() {
Assertions.UNREACHABLE("RootContext.getFinally()"); Assertions.UNREACHABLE("RootContext.getFinally()");
return null; return null;
} }
public CAstSourcePositionRecorder pos() {
// No AST, so no AST map
Assertions.UNREACHABLE("RootContext.pos()");
return null;
}
public Node getContinueFor(String label) {
Assertions.UNREACHABLE("RootContext.getContinueFor()");
return null;
}
public Node getBreakFor(String label) {
Assertions.UNREACHABLE("RootContext.getBreakFor()");
return null;
}
public CodeInstance getEnclosingMethod() { public CodeInstance getEnclosingMethod() {
Assertions.UNREACHABLE("RootContext.getEnclosingMethod()"); Assertions.UNREACHABLE("RootContext.getEnclosingMethod()");
return null; return null;
@ -2360,12 +2258,13 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
} }
public PolyglotJava2CAstTranslator(ClassLoaderReference clr, NodeFactory nf, TypeSystem ts, PolyglotIdentityMapper identityMapper, boolean replicateForDoLoops) { public PolyglotJava2CAstTranslator(Node ast, ClassLoaderReference clr, NodeFactory nf, TypeSystem ts, PolyglotIdentityMapper identityMapper, boolean replicateForDoLoops) {
this.ast = ast;
fClassLoaderRef = clr; fClassLoaderRef = clr;
fTypeSystem = ts; fTypeSystem = ts;
fNodeFactory = nf; fNodeFactory = nf;
fIdentityMapper = identityMapper; fIdentityMapper = identityMapper;
this.replicateForDoLoops = replicateForDoLoops; doLoopTranslator = new DoLoopTranslator(replicateForDoLoops, fFactory);
fNPEType = fTypeSystem.NullPointerException(); fNPEType = fTypeSystem.NullPointerException();
fCCEType = fTypeSystem.ClassCastException(); fCCEType = fTypeSystem.ClassCastException();
fREType = fTypeSystem.RuntimeException(); fREType = fTypeSystem.RuntimeException();
@ -2530,8 +2429,8 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
return cn; return cn;
} }
public CAstEntity translate(Object ast, String fileName) { public CAstEntity translateToCAst() {
return walkEntity((Node) ast, new RootContext(getTypeDict())); return walkEntity(ast, new RootContext(getTypeDict()));
} }
/** /**
@ -2623,7 +2522,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
InitializerDef initDef = fTypeSystem.initializerDef(n.position(), Types.ref(classType), Flags.STATIC); InitializerDef initDef = fTypeSystem.initializerDef(n.position(), Types.ref(classType), Flags.STATIC);
InitializerInstance initInstance = fTypeSystem.createInitializerInstance(n.position(), Types.ref(initDef)); InitializerInstance initInstance = fTypeSystem.createInitializerInstance(n.position(), Types.ref(initDef));
Map<CAstNode, CAstEntity> childEntities = HashMapFactory.make(); Map<CAstNode, Collection<CAstEntity>> childEntities = HashMapFactory.make();
final MethodContext mc = new MethodContext(initInstance, childEntities, classContext); final MethodContext mc = new MethodContext(initInstance, childEntities, classContext);
List inits = classContext.getStaticInitializers(); List inits = classContext.getStaticInitializers();
@ -2644,7 +2543,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
for (Iterator iter = superConstructors.iterator(); iter.hasNext();) { for (Iterator iter = superConstructors.iterator(); iter.hasNext();) {
ConstructorInstance superCtor = (ConstructorInstance) iter.next(); ConstructorInstance superCtor = (ConstructorInstance) iter.next();
Map<CAstNode, CAstEntity> childEntities = HashMapFactory.make(); Map<CAstNode, Collection<CAstEntity>> childEntities = HashMapFactory.make();
final MethodContext mc = new MethodContext(superCtor, childEntities, classContext); final MethodContext mc = new MethodContext(superCtor, childEntities, classContext);
String[] fakeArguments = new String[superCtor.formalTypes().size() + 1]; String[] fakeArguments = new String[superCtor.formalTypes().size() + 1];
@ -2713,7 +2612,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
return new ClassEntity(classContext, memberEntities, anonType, anonTypeName, n.position()); return new ClassEntity(classContext, memberEntities, anonType, anonTypeName, n.position());
} else if (rootNode instanceof ProcedureDecl) { } else if (rootNode instanceof ProcedureDecl) {
final ProcedureDecl pd = (ProcedureDecl) rootNode; final ProcedureDecl pd = (ProcedureDecl) rootNode;
final Map<CAstNode, CAstEntity> memberEntities = new LinkedHashMap<CAstNode, CAstEntity>(); final Map<CAstNode, Collection<CAstEntity>> memberEntities = HashMapFactory.make();
final MethodContext mc = new MethodContext(pd.procedureInstance().asInstance(), memberEntities, context); final MethodContext mc = new MethodContext(pd.procedureInstance().asInstance(), memberEntities, context);
CAstNode pdAST = null; CAstNode pdAST = null;

View File

@ -186,7 +186,7 @@ public class SynchronizedBlockDuplicator extends
return null; return null;
} }
protected CAstNode copyNodes(CAstNode n, RewriteContext<UnwindKey> c, Map<Pair<CAstNode, UnwindKey>, CAstNode> nodeMap) { protected CAstNode copyNodes(CAstNode n, final CAstControlFlowMap cfg, RewriteContext<UnwindKey> c, Map<Pair<CAstNode, UnwindKey>, CAstNode> nodeMap) {
String varName; String varName;
// don't copy operators or constants (presumably since they are immutable?) // don't copy operators or constants (presumably since they are immutable?)
if (n instanceof CAstOperator) { if (n instanceof CAstOperator) {
@ -204,15 +204,15 @@ public class SynchronizedBlockDuplicator extends
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(varName))); Ast.makeNode(CAstNode.VAR, Ast.makeConstant(varName)));
// the new if conditional // the new if conditional
return Ast.makeNode(CAstNode.IF_STMT, test, copyNodes(n, new SyncContext(true, n, c), nodeMap), return Ast.makeNode(CAstNode.IF_STMT, test, copyNodes(n, cfg, new SyncContext(true, n, c), nodeMap),
copyNodes(n, new SyncContext(false, n, c), nodeMap)); copyNodes(n, cfg, new SyncContext(false, n, c), nodeMap));
} else { } else {
// invoke copyNodes() on the children with context c, ensuring, e.g., that // invoke copyNodes() on the children with context c, ensuring, e.g., that
// the body of a synchronized block gets cloned // the body of a synchronized block gets cloned
CAstNode[] newChildren = new CAstNode[n.getChildCount()]; CAstNode[] newChildren = new CAstNode[n.getChildCount()];
for (int i = 0; i < newChildren.length; i++) for (int i = 0; i < newChildren.length; i++)
newChildren[i] = copyNodes(n.getChild(i), c, nodeMap); newChildren[i] = copyNodes(n.getChild(i), cfg, c, nodeMap);
CAstNode newN = Ast.makeNode(n.getKind(), newChildren); CAstNode newN = Ast.makeNode(n.getKind(), newChildren);

View File

@ -15,6 +15,7 @@ package com.ibm.wala.cast.java.translator;
import java.io.PrintWriter; import java.io.PrintWriter;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl; import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
@ -29,34 +30,29 @@ public class Java2IRTranslator {
protected final JavaSourceLoaderImpl fLoader; protected final JavaSourceLoaderImpl fLoader;
protected final TranslatorToCAst fSourceTranslator;
CAstRewriterFactory castRewriterFactory = null; CAstRewriterFactory castRewriterFactory = null;
public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader) { public Java2IRTranslator(JavaSourceLoaderImpl srcLoader) {
this(sourceTranslator, srcLoader, false); this(srcLoader, false);
} }
public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader, boolean debug) { public Java2IRTranslator(JavaSourceLoaderImpl srcLoader, boolean debug) {
this(sourceTranslator, srcLoader, null, debug); this(srcLoader, null, debug);
} }
public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader, public Java2IRTranslator(JavaSourceLoaderImpl srcLoader,
CAstRewriterFactory castRewriterFactory) { CAstRewriterFactory castRewriterFactory) {
this(sourceTranslator, srcLoader, castRewriterFactory, false); this(srcLoader, castRewriterFactory, false);
} }
public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader, public Java2IRTranslator(JavaSourceLoaderImpl srcLoader,
CAstRewriterFactory castRewriterFactory, boolean debug) { CAstRewriterFactory castRewriterFactory, boolean debug) {
DEBUG = debug; DEBUG = debug;
fLoader = srcLoader; fLoader = srcLoader;
fSourceTranslator = sourceTranslator;
this.castRewriterFactory = castRewriterFactory; this.castRewriterFactory = castRewriterFactory;
} }
public void translate(ModuleEntry module, Object ast, String N) { public void translate(ModuleEntry module, CAstEntity ce) {
CAstEntity ce = fSourceTranslator.translate(ast, N);
if (DEBUG) { if (DEBUG) {
PrintWriter printWriter = new PrintWriter(System.out); PrintWriter printWriter = new PrintWriter(System.out);
CAstPrinter.printTo(ce, printWriter); CAstPrinter.printTo(ce, printWriter);

View File

@ -304,26 +304,24 @@ public class JavaCAst2IRTranslator extends AstTranslator {
return ((JavaSourceLoaderImpl) loader).defineType(type, type.getType().getName(), parentType) != null; return ((JavaSourceLoaderImpl) loader).defineType(type, type.getType().getName(), parentType) != null;
} }
protected void leaveThis(CAstNode n, Context c, CAstVisitor visitor) { protected void leaveThis(CAstNode n, WalkContext c, CAstVisitor<WalkContext> visitor) {
if (n.getChildCount() == 0) { if (n.getChildCount() == 0) {
super.leaveThis(n, c, visitor); super.leaveThis(n, c, visitor);
} else { } else {
WalkContext wc = (WalkContext) c; int result = c.currentScope().allocateTempValue();
int result = wc.currentScope().allocateTempValue(); c.setValue(n, result);
setValue(n, result); c.cfg().addInstruction(new EnclosingObjectReference(result, (TypeReference) n.getChild(0).getValue()));
wc.cfg().addInstruction(new EnclosingObjectReference(result, (TypeReference) n.getChild(0).getValue()));
} }
} }
protected boolean visitCast(CAstNode n, Context c, CAstVisitor visitor) { protected boolean visitCast(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
WalkContext context = (WalkContext)c;
int result = context.currentScope().allocateTempValue(); int result = context.currentScope().allocateTempValue();
setValue(n, result); context.setValue(n, result);
return false; return false;
} }
protected void leaveCast(CAstNode n, Context c, CAstVisitor visitor) {
WalkContext context = (WalkContext)c; protected void leaveCast(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
int result = getValue(n); int result = context.getValue(n);
CAstType toType = (CAstType) n.getChild(0).getValue(); CAstType toType = (CAstType) n.getChild(0).getValue();
TypeReference toRef = makeType(toType); TypeReference toRef = makeType(toType);
@ -334,7 +332,7 @@ public class JavaCAst2IRTranslator extends AstTranslator {
context.cfg().addInstruction( context.cfg().addInstruction(
insts.ConversionInstruction( insts.ConversionInstruction(
result, result,
getValue(n.getChild(1)), context.getValue(n.getChild(1)),
fromRef, fromRef,
toRef, toRef,
false)); false));
@ -343,43 +341,42 @@ public class JavaCAst2IRTranslator extends AstTranslator {
context.cfg().addInstruction( context.cfg().addInstruction(
insts.CheckCastInstruction( insts.CheckCastInstruction(
result, result,
getValue(n.getChild(1)), context.getValue(n.getChild(1)),
toRef, toRef,
true)); true));
processExceptions(n, context); processExceptions(n, context);
} }
} }
protected boolean visitInstanceOf(CAstNode n, Context c, CAstVisitor visitor) {
WalkContext context = (WalkContext)c; protected boolean visitInstanceOf(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
int result = context.currentScope().allocateTempValue(); int result = context.currentScope().allocateTempValue();
setValue(n, result); context.setValue(n, result);
return false; return false;
} }
protected void leaveInstanceOf(CAstNode n, Context c, CAstVisitor visitor) {
WalkContext context = (WalkContext)c; protected void leaveInstanceOf(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
int result = getValue(n); int result = context.getValue(n);
CAstType type = (CAstType) n.getChild(0).getValue(); CAstType type = (CAstType) n.getChild(0).getValue();
TypeReference ref = makeType( type ); TypeReference ref = makeType( type );
context.cfg().addInstruction( context.cfg().addInstruction(
insts.InstanceofInstruction( insts.InstanceofInstruction(
result, result,
getValue(n.getChild(1)), context.getValue(n.getChild(1)),
ref)); ref));
} }
protected boolean doVisit(CAstNode n, Context context, CAstVisitor visitor) { protected boolean doVisit(CAstNode n, WalkContext wc, CAstVisitor<WalkContext> visitor) {
WalkContext wc = (WalkContext) context;
if (n.getKind() == CAstNode.MONITOR_ENTER) { if (n.getKind() == CAstNode.MONITOR_ENTER) {
visitor.visit(n.getChild(0), wc, visitor); visitor.visit(n.getChild(0), wc, visitor);
wc.cfg().addInstruction(insts.MonitorInstruction(getValue(n.getChild(0)), true)); wc.cfg().addInstruction(insts.MonitorInstruction(wc.getValue(n.getChild(0)), true));
processExceptions(n, wc); processExceptions(n, wc);
return true; return true;
} else if (n.getKind() == CAstNode.MONITOR_EXIT) { } else if (n.getKind() == CAstNode.MONITOR_EXIT) {
visitor.visit(n.getChild(0), wc, visitor); visitor.visit(n.getChild(0), wc, visitor);
wc.cfg().addInstruction(insts.MonitorInstruction(getValue(n.getChild(0)), false)); wc.cfg().addInstruction(insts.MonitorInstruction(wc.getValue(n.getChild(0)), false));
processExceptions(n, wc); processExceptions(n, wc);
return true; return true;
} else { } else {

View File

@ -1,19 +0,0 @@
/******************************************************************************
* 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.java.translator;
import com.ibm.wala.cast.tree.CAstEntity;
public interface TranslatorToCAst {
public CAstEntity translate(Object astRoot, String unitName);
}

View File

@ -0,0 +1,15 @@
package com.ibm.wala.cast.js.test;
import org.junit.Before;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
public class TestArgumentSensitivityRhino extends TestArgumentSensitivity {
@Before
public void setUp() {
com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory());
}
}

View File

@ -15,10 +15,10 @@ import java.io.IOException;
import com.ibm.wala.cast.js.ipa.callgraph.correlations.CorrelationFinder; import com.ibm.wala.cast.js.ipa.callgraph.correlations.CorrelationFinder;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory; import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.cast.js.translator.RhinoToAstTranslator;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.impl.CAstImpl; import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.classLoader.SourceModule; import com.ibm.wala.classLoader.SourceModule;
import org.mozilla.javascript.RhinoToAstTranslator;
public class TestCorrelatedPairExtractionRhino extends TestCorrelatedPairExtraction { public class TestCorrelatedPairExtractionRhino extends TestCorrelatedPairExtraction {
protected CorrelationFinder makeCorrelationFinder() { protected CorrelationFinder makeCorrelationFinder() {
@ -26,9 +26,8 @@ public class TestCorrelatedPairExtractionRhino extends TestCorrelatedPairExtract
} }
protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException { protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException {
RhinoToAstTranslator.resetGensymCounters(); RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName(), false);
RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName()); CAstEntity entity = translator.translateToCAst();
CAstEntity entity = translator.translate();
return entity; return entity;
} }
} }

View File

@ -13,17 +13,16 @@ package com.ibm.wala.cast.js.test;
import java.io.IOException; import java.io.IOException;
import org.mozilla.javascript.RhinoToAstTranslator;
import com.ibm.wala.cast.js.translator.RhinoToAstTranslator;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.impl.CAstImpl; import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.classLoader.SourceModule; import com.ibm.wala.classLoader.SourceModule;
public class TestForInBodyExtractionRhino extends TestForInBodyExtraction { public class TestForInBodyExtractionRhino extends TestForInBodyExtraction {
protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException { protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException {
RhinoToAstTranslator.resetGensymCounters(); RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName(), false);
RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName()); CAstEntity entity = translator.translateToCAst();
CAstEntity entity = translator.translate();
return entity; return entity;
} }
} }

View File

@ -0,0 +1,18 @@
package com.ibm.wala.cast.js.test;
import org.junit.Before;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
public class TestJQueryExamplesRhino extends TestJQueryExamples {
public static void main(String[] args) {
justThisTest(TestJQueryExamplesRhino.class);
}
@Before
public void setUp() {
com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory());
}
}

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Set; import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.html.DefaultSourceExtractor; import com.ibm.wala.cast.js.html.DefaultSourceExtractor;
import com.ibm.wala.cast.js.html.DomLessSourceExtractor; import com.ibm.wala.cast.js.html.DomLessSourceExtractor;
import com.ibm.wala.cast.js.html.IdentityUrlResolver; import com.ibm.wala.cast.js.html.IdentityUrlResolver;
@ -40,8 +41,8 @@ public class JsViewerDriver extends Util {
SourceModule[] sources = getSources(domless, url); SourceModule[] sources = getSources(domless, url);
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, false, true); JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, false, false, AstIRFactory.makeDefaultFactory());
builder.setBaseURL(url); builder.setBaseURL(url);
CallGraph cg = builder.makeCallGraph(builder.getOptions()); CallGraph cg = builder.makeCallGraph(builder.getOptions());
PointerAnalysis pa = builder.getPointerAnalysis(); PointerAnalysis pa = builder.getPointerAnalysis();

View File

@ -14,7 +14,6 @@ import java.io.IOException;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.mozilla.javascript.RhinoToAstTranslator;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst; import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.js.translator.PropertyReadExpander.ExpanderKey; import com.ibm.wala.cast.js.translator.PropertyReadExpander.ExpanderKey;
@ -31,9 +30,11 @@ import com.ibm.wala.classLoader.SourceModule;
public class CAstRhinoTranslator implements TranslatorToCAst { public class CAstRhinoTranslator implements TranslatorToCAst {
private final List<CAstRewriterFactory> rewriters = new LinkedList<CAstRewriterFactory>(); private final List<CAstRewriterFactory> rewriters = new LinkedList<CAstRewriterFactory>();
private final SourceModule M; private final SourceModule M;
private final boolean replicateForDoLoops;
public CAstRhinoTranslator(SourceModule M) {
public CAstRhinoTranslator(SourceModule M, boolean replicateForDoLoops) {
this.M = M; this.M = M;
this.replicateForDoLoops = replicateForDoLoops;
this.addRewriter(new CAstRewriterFactory<PropertyReadExpander.RewriteContext, ExpanderKey>() { this.addRewriter(new CAstRewriterFactory<PropertyReadExpander.RewriteContext, ExpanderKey>() {
public CAstRewriter<PropertyReadExpander.RewriteContext, ExpanderKey> createCAstRewriter(CAst ast) { public CAstRewriter<PropertyReadExpander.RewriteContext, ExpanderKey> createCAstRewriter(CAst ast) {
return new PropertyReadExpander(ast); return new PropertyReadExpander(ast);
@ -57,9 +58,10 @@ public class CAstRhinoTranslator implements TranslatorToCAst {
} }
CAstImpl Ast = new CAstImpl(); CAstImpl Ast = new CAstImpl();
CAstEntity entity = new RhinoToAstTranslator(Ast, M, N).translate(); CAstEntity entity = new RhinoToAstTranslator(Ast, M, N, replicateForDoLoops).translateToCAst();
for(CAstRewriterFactory rwf : rewriters) for(CAstRewriterFactory rwf : rewriters)
entity = rwf.createCAstRewriter(Ast).rewrite(entity); entity = rwf.createCAstRewriter(Ast).rewrite(entity);
return entity; return entity;
} }
} }

View File

@ -7,7 +7,7 @@ import com.ibm.wala.classLoader.SourceModule;
public class CAstRhinoTranslatorFactory implements JavaScriptTranslatorFactory { public class CAstRhinoTranslatorFactory implements JavaScriptTranslatorFactory {
public TranslatorToCAst make(CAst ast, SourceModule M) { public TranslatorToCAst make(CAst ast, SourceModule M) {
return new CAstRhinoTranslator(M); return new CAstRhinoTranslator(M, false);
} }
} }

View File

@ -0,0 +1,303 @@
package com.ibm.wala.cast.js.translator;
import org.mozilla.javascript.ast.ArrayComprehension;
import org.mozilla.javascript.ast.ArrayComprehensionLoop;
import org.mozilla.javascript.ast.ArrayLiteral;
import org.mozilla.javascript.ast.Assignment;
import org.mozilla.javascript.ast.AstNode;
import org.mozilla.javascript.ast.AstRoot;
import org.mozilla.javascript.ast.Block;
import org.mozilla.javascript.ast.BreakStatement;
import org.mozilla.javascript.ast.CatchClause;
import org.mozilla.javascript.ast.Comment;
import org.mozilla.javascript.ast.ConditionalExpression;
import org.mozilla.javascript.ast.ContinueStatement;
import org.mozilla.javascript.ast.DoLoop;
import org.mozilla.javascript.ast.ElementGet;
import org.mozilla.javascript.ast.EmptyExpression;
import org.mozilla.javascript.ast.ErrorNode;
import org.mozilla.javascript.ast.ExpressionStatement;
import org.mozilla.javascript.ast.ForInLoop;
import org.mozilla.javascript.ast.ForLoop;
import org.mozilla.javascript.ast.FunctionCall;
import org.mozilla.javascript.ast.FunctionNode;
import org.mozilla.javascript.ast.IfStatement;
import org.mozilla.javascript.ast.InfixExpression;
import org.mozilla.javascript.ast.Jump;
import org.mozilla.javascript.ast.KeywordLiteral;
import org.mozilla.javascript.ast.Label;
import org.mozilla.javascript.ast.LabeledStatement;
import org.mozilla.javascript.ast.LetNode;
import org.mozilla.javascript.ast.Name;
import org.mozilla.javascript.ast.NewExpression;
import org.mozilla.javascript.ast.NumberLiteral;
import org.mozilla.javascript.ast.ObjectLiteral;
import org.mozilla.javascript.ast.ObjectProperty;
import org.mozilla.javascript.ast.ParenthesizedExpression;
import org.mozilla.javascript.ast.PropertyGet;
import org.mozilla.javascript.ast.RegExpLiteral;
import org.mozilla.javascript.ast.ReturnStatement;
import org.mozilla.javascript.ast.Scope;
import org.mozilla.javascript.ast.ScriptNode;
import org.mozilla.javascript.ast.StringLiteral;
import org.mozilla.javascript.ast.SwitchCase;
import org.mozilla.javascript.ast.SwitchStatement;
import org.mozilla.javascript.ast.Symbol;
import org.mozilla.javascript.ast.ThrowStatement;
import org.mozilla.javascript.ast.TryStatement;
import org.mozilla.javascript.ast.UnaryExpression;
import org.mozilla.javascript.ast.VariableDeclaration;
import org.mozilla.javascript.ast.VariableInitializer;
import org.mozilla.javascript.ast.WhileLoop;
import org.mozilla.javascript.ast.WithStatement;
import org.mozilla.javascript.ast.XmlDotQuery;
import org.mozilla.javascript.ast.XmlElemRef;
import org.mozilla.javascript.ast.XmlExpression;
import org.mozilla.javascript.ast.XmlFragment;
import org.mozilla.javascript.ast.XmlLiteral;
import org.mozilla.javascript.ast.XmlMemberGet;
import org.mozilla.javascript.ast.XmlPropRef;
import org.mozilla.javascript.ast.XmlRef;
import org.mozilla.javascript.ast.XmlString;
import org.mozilla.javascript.ast.Yield;
public abstract class TypedNodeVisitor<R,A> {
public R visit(AstNode node, A arg) {
if (node instanceof ArrayComprehension) {
return visitArrayComprehension((ArrayComprehension) node, arg);
} else if (node instanceof WhileLoop) {
return visitWhileLoop((WhileLoop) node, arg);
} else if (node instanceof ArrayComprehensionLoop) {
return visitArrayComprehensionLoop((ArrayComprehensionLoop) node, arg);
} else if (node instanceof ArrayLiteral) {
return visitArrayLiteral((ArrayLiteral) node, arg);
} else if (node instanceof Assignment) {
return visitAssignment((Assignment) node, arg);
} else if (node instanceof AstRoot) {
return visitAstRoot((AstRoot) node, arg);
} else if (node instanceof Block) {
return visitBlock((Block) node, arg);
} else if (node instanceof BreakStatement) {
return visitBreakStatement((BreakStatement) node, arg);
} else if (node instanceof CatchClause) {
return visitCatchClause((CatchClause) node, arg);
} else if (node instanceof Comment) {
return visitComment((Comment) node, arg);
} else if (node instanceof ConditionalExpression) {
return visitConditionalExpression((ConditionalExpression) node, arg);
} else if (node instanceof ContinueStatement) {
return visitContinueStatement((ContinueStatement) node, arg);
} else if (node instanceof DoLoop) {
return visitDoLoop((DoLoop) node, arg);
} else if (node instanceof ElementGet) {
return visitElementGet((ElementGet) node, arg);
} else if (node instanceof EmptyExpression) {
return visitEmptyExpression((EmptyExpression) node, arg);
} else if (node instanceof ErrorNode) {
return visitErrorNode((ErrorNode) node, arg);
} else if (node instanceof ExpressionStatement) {
return visitExpressionStatement((ExpressionStatement) node, arg);
} else if (node instanceof ForInLoop) {
return visitForInLoop((ForInLoop) node, arg);
} else if (node instanceof ForLoop) {
return visitForLoop((ForLoop) node, arg);
} else if (node instanceof NewExpression) {
return visitNewExpression((NewExpression) node, arg);
} else if (node instanceof FunctionCall) {
return visitFunctionCall((FunctionCall) node, arg);
} else if (node instanceof FunctionNode) {
return visitFunctionNode((FunctionNode) node, arg);
} else if (node instanceof IfStatement) {
return visitIfStatement((IfStatement) node, arg);
} else if (node instanceof KeywordLiteral) {
return visitKeywordLiteral((KeywordLiteral) node, arg);
} else if (node instanceof Label) {
return visitLabel((Label) node, arg);
} else if (node instanceof LabeledStatement) {
return visitLabeledStatement((LabeledStatement) node, arg);
} else if (node instanceof LetNode) {
return visitLetNode((LetNode) node, arg);
} else if (node instanceof Name) {
return visitName((Name) node, arg);
} else if (node instanceof NumberLiteral) {
return visitNumberLiteral((NumberLiteral) node, arg);
} else if (node instanceof ObjectLiteral) {
return visitObjectLiteral((ObjectLiteral) node, arg);
} else if (node instanceof ObjectProperty) {
return visitObjectProperty((ObjectProperty) node, arg);
} else if (node instanceof ParenthesizedExpression) {
return visitParenthesizedExpression((ParenthesizedExpression) node, arg);
} else if (node instanceof PropertyGet) {
return visitPropertyGet((PropertyGet) node, arg);
} else if (node instanceof RegExpLiteral) {
return visitRegExpLiteral((RegExpLiteral) node, arg);
} else if (node instanceof ReturnStatement) {
return visitReturnStatement((ReturnStatement) node, arg);
} else if (node instanceof Scope) {
return visitScope((Scope) node, arg);
} else if (node instanceof ScriptNode) {
return visitScriptNode((ScriptNode) node, arg);
} else if (node instanceof StringLiteral) {
return visitStringLiteral((StringLiteral) node, arg);
} else if (node instanceof SwitchCase) {
return visitSwitchCase((SwitchCase) node, arg);
} else if (node instanceof SwitchStatement) {
return visitSwitchStatement((SwitchStatement) node, arg);
} else if (node instanceof ThrowStatement) {
return visitThrowStatement((ThrowStatement) node, arg);
} else if (node instanceof TryStatement) {
return visitTryStatement((TryStatement) node, arg);
} else if (node instanceof UnaryExpression) {
return visitUnaryExpression((UnaryExpression) node, arg);
} else if (node instanceof VariableDeclaration) {
return visitVariableDeclaration((VariableDeclaration) node, arg);
} else if (node instanceof VariableInitializer) {
return visitVariableInitializer((VariableInitializer) node, arg);
} else if (node instanceof WithStatement) {
return visitWithStatement((WithStatement) node, arg);
} else if (node instanceof XmlDotQuery) {
return visitXmlDotQuery((XmlDotQuery) node, arg);
} else if (node instanceof XmlElemRef) {
return visitXmlElemRef((XmlElemRef) node, arg);
} else if (node instanceof XmlExpression) {
return visitXmlExpression((XmlExpression) node, arg);
} else if (node instanceof XmlLiteral) {
return visitXmlLiteral((XmlLiteral) node, arg);
} else if (node instanceof XmlMemberGet) {
return visitXmlMemberGet((XmlMemberGet) node, arg);
} else if (node instanceof XmlPropRef) {
return visitXmlPropRef((XmlPropRef) node, arg);
} else if (node instanceof XmlString) {
return visitXmlString((XmlString) node, arg);
} else if (node instanceof Yield) {
return visitYield((Yield) node, arg);
} else if (node instanceof InfixExpression) {
return visitInfixExpression((InfixExpression) node, arg);
} else if (node instanceof Jump) {
return visitJump((Jump) node, arg);
} else {
throw new Error("unexpected node type " + node.getClass().getName());
}
}
public abstract R visitArrayComprehension(ArrayComprehension node, A arg) ;
public abstract R visitArrayComprehensionLoop(ArrayComprehensionLoop node, A arg) ;
public abstract R visitArrayLiteral(ArrayLiteral node, A arg) ;
public abstract R visitAssignment(Assignment node, A arg) ;
public abstract R visitAstRoot(AstRoot node, A arg) ;
public abstract R visitBlock(Block node, A arg) ;
public abstract R visitBreakStatement(BreakStatement node, A arg) ;
public abstract R visitCatchClause(CatchClause node, A arg) ;
public abstract R visitComment(Comment node, A arg) ;
public abstract R visitConditionalExpression(ConditionalExpression node, A arg) ;
public abstract R visitContinueStatement(ContinueStatement node, A arg) ;
public abstract R visitDoLoop(DoLoop node, A arg) ;
public abstract R visitElementGet(ElementGet node, A arg) ;
public abstract R visitEmptyExpression(EmptyExpression node, A arg) ;
public abstract R visitErrorNode(ErrorNode node, A arg) ;
public abstract R visitExpressionStatement(ExpressionStatement node, A arg) ;
public abstract R visitForInLoop(ForInLoop node, A arg) ;
public abstract R visitForLoop(ForLoop node, A arg) ;
public abstract R visitFunctionCall(FunctionCall node, A arg) ;
public abstract R visitFunctionNode(FunctionNode node, A arg) ;
public abstract R visitIfStatement(IfStatement node, A arg) ;
public abstract R visitInfixExpression(InfixExpression node, A arg) ;
public abstract R visitJump(Jump node, A arg) ;
public abstract R visitKeywordLiteral(KeywordLiteral node, A arg) ;
public abstract R visitLabel(Label node, A arg) ;
public abstract R visitLabeledStatement(LabeledStatement node, A arg) ;
public abstract R visitLetNode(LetNode node, A arg) ;
public abstract R visitName(Name node, A arg) ;
public abstract R visitNewExpression(NewExpression node, A arg) ;
public abstract R visitNumberLiteral(NumberLiteral node, A arg) ;
public abstract R visitObjectLiteral(ObjectLiteral node, A arg) ;
public abstract R visitObjectProperty(ObjectProperty node, A arg) ;
public abstract R visitParenthesizedExpression(ParenthesizedExpression node, A arg) ;
public abstract R visitPropertyGet(PropertyGet node, A arg) ;
public abstract R visitRegExpLiteral(RegExpLiteral node, A arg) ;
public abstract R visitReturnStatement(ReturnStatement node, A arg) ;
public abstract R visitScope(Scope node, A arg) ;
public abstract R visitScriptNode(ScriptNode node, A arg) ;
public abstract R visitStringLiteral(StringLiteral node, A arg) ;
public abstract R visitSwitchCase(SwitchCase node, A arg) ;
public abstract R visitSwitchStatement(SwitchStatement node, A arg) ;
public abstract R visitSymbol(Symbol node, A arg) ;
public abstract R visitThrowStatement(ThrowStatement node, A arg) ;
public abstract R visitTryStatement(TryStatement node, A arg) ;
public abstract R visitUnaryExpression(UnaryExpression node, A arg) ;
public abstract R visitVariableDeclaration(VariableDeclaration node, A arg) ;
public abstract R visitVariableInitializer(VariableInitializer node, A arg) ;
public abstract R visitWhileLoop(WhileLoop node, A arg) ;
public abstract R visitWithStatement(WithStatement node, A arg) ;
public abstract R visitXmlDotQuery(XmlDotQuery node, A arg) ;
public abstract R visitXmlElemRef(XmlElemRef node, A arg) ;
public abstract R visitXmlExpression(XmlExpression node, A arg) ;
public abstract R visitXmlFragment(XmlFragment node, A arg) ;
public abstract R visitXmlLiteral(XmlLiteral node, A arg) ;
public abstract R visitXmlMemberGet(XmlMemberGet node, A arg) ;
public abstract R visitXmlPropRef(XmlPropRef node, A arg) ;
public abstract R visitXmlRef(XmlRef node, A arg) ;
public abstract R visitXmlString(XmlString node, A arg) ;
public abstract R visitYield(Yield node, A arg) ;
}

View File

@ -0,0 +1,24 @@
function a() {
if (arguments.length >= 1) {
arguments[0]();
if (arguments.length >= 2) {
arguments[1]();
}
}
}
function x() {
print("x");
}
function y() {
print("y");
}
function z() {
print("z");
}
a(x);
a(y, z);

View File

@ -1,8 +1,11 @@
function() { (function(x) {
switch(0) { switch(x) {
case Ext.Date: case Ext.Date:
return 1;
break;
} }
} return -1;
})(0);

View File

@ -0,0 +1,53 @@
package com.ibm.wala.cast.js.test;
import java.io.IOException;
import org.junit.Test;
import com.ibm.wala.cast.js.ipa.callgraph.ArgumentSpecialization;
import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.ipa.callgraph.JSZeroOrOneXCFABuilder;
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.CancelException;
public abstract class TestArgumentSensitivity extends TestJSCallGraphShape {
protected static final Object[][] assertionsForArgs = new Object[][] {
new Object[] { ROOT, new String[] { "tests/args.js" } },
new Object[] {
"tests/args.js",
new String[] { "tests/args.js/a" } },
new Object[] { "tests/args.js/a", new String[] { "tests/args.js/x"} },
new Object[] { "tests/args.js/a", new String[] { "tests/args.js/y", "tests/args.js/z" } } };
@Test public void testArgs() throws IOException, IllegalArgumentException, CancelException, ClassHierarchyException {
JavaScriptLoaderFactory loaders = Util.makeLoaders();
AnalysisScope scope = Util.makeScriptScope("tests", "args.js", loaders);
IClassHierarchy cha = Util.makeHierarchy(scope, loaders);
com.ibm.wala.cast.js.util.Util.checkForFrontEndErrors(cha);
Iterable<Entrypoint> roots = Util.makeScriptRoots(cha);
JSAnalysisOptions options = Util.makeOptions(scope, cha, roots);
AnalysisCache cache = Util.makeCache(new ArgumentSpecialization.ArgumentCountIRFactory(options.getSSAOptions()));
JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, false);
builder.setContextSelector(new ArgumentSpecialization.ArgumentCountContextSelector(builder.getContextSelector()));
builder.setContextInterpreter(new ArgumentSpecialization.ArgumentSpecializationContextIntepreter(options, cache));
CallGraph CG = builder.makeCallGraph(options);
Util.AVOID_DUMP = false;
Util.dumpCG(builder.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForArgs);
}
}

View File

@ -0,0 +1,32 @@
package com.ibm.wala.cast.js.test;
import java.io.IOException;
import java.net.URL;
import org.junit.Before;
import org.junit.Test;
import com.ibm.wala.cast.js.html.JSSourceExtractor;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.util.CancelException;
public class TestJQueryExamples extends TestJSCallGraphShape {
public static void main(String[] args) {
justThisTest(TestJQueryExamples.class);
}
@Before
public void config() {
JSSourceExtractor.USE_TEMP_NAME = false;
JSSourceExtractor.DELETE_UPON_EXIT = false;
}
@Test public void testEx1() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/jquery/ex1.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG);
}
}

View File

@ -42,6 +42,18 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
justThisTest(TestSimpleCallGraphShape.class); justThisTest(TestSimpleCallGraphShape.class);
} }
protected static final Object[][] assertionsForArgs = new Object[][] {
new Object[] { ROOT, new String[] { "tests/args.js" } },
new Object[] {
"tests/args.js",
new String[] { "tests/args.js/a" } },
new Object[] { "tests/args.js/a", new String[] { "tests/args.js/x", "tests/args.js/y" } } };
@Test public void testArgs() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "args.js");
verifyGraphAssertions(CG, assertionsForArgs);
}
protected static final Object[][] assertionsForSimple = new Object[][] { protected static final Object[][] assertionsForSimple = new Object[][] {
new Object[] { ROOT, new String[] { "tests/simple.js" } }, new Object[] { ROOT, new String[] { "tests/simple.js" } },
new Object[] { new Object[] {

View File

@ -139,6 +139,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testCrawlPage12() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawlPage12() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl/page12.html"); URL url = getClass().getClassLoader().getResource("pages/crawl/page12.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = Util.makeHTMLCG(url);
System.err.println(CG);
verifyGraphAssertions(CG, assertionsForPage12); verifyGraphAssertions(CG, assertionsForPage12);
} }
@ -230,7 +231,9 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testCrawlPage17() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawlPage17() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl/page17.html"); URL url = getClass().getClassLoader().getResource("pages/crawl/page17.html");
CallGraph CG = Util.makeHTMLCG(url); JSCFABuilder builder = Util.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForPage17); verifyGraphAssertions(CG, assertionsForPage17);
} }

View File

@ -18,6 +18,7 @@ import java.util.Set;
import junit.framework.Assert; import junit.framework.Assert;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.html.MappedSourceModule; import com.ibm.wala.cast.js.html.MappedSourceModule;
import com.ibm.wala.cast.js.html.WebPageLoaderFactory; import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
import com.ibm.wala.cast.js.html.WebUtil; import com.ibm.wala.cast.js.html.WebUtil;
@ -36,6 +37,7 @@ import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys; import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
import com.ibm.wala.ipa.cha.ClassHierarchyException; import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.IRFactory;
import com.ibm.wala.util.CancelException; import com.ibm.wala.util.CancelException;
/** /**
@ -43,9 +45,15 @@ import com.ibm.wala.util.CancelException;
*/ */
public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
public static JSCFABuilder makeScriptCGBuilder(String dir, String name, boolean useOneCFA) throws IOException { public static JSCFABuilder makeScriptCGBuilder(String dir, String name, boolean useOneCFA, IRFactory irFactory) throws IOException {
JavaScriptLoaderFactory loaders = Util.makeLoaders(); JavaScriptLoaderFactory loaders = Util.makeLoaders();
AnalysisScope scope = makeScriptScope(dir, name, loaders);
return makeCG(loaders, scope, useOneCFA, true, irFactory);
}
static AnalysisScope makeScriptScope(String dir, String name, JavaScriptLoaderFactory loaders) throws IOException {
URL script = Util.class.getClassLoader().getResource(dir + File.separator + name); URL script = Util.class.getClassLoader().getResource(dir + File.separator + name);
if (script == null) { if (script == null) {
script = Util.class.getClassLoader().getResource(dir + "/" + name); script = Util.class.getClassLoader().getResource(dir + "/" + name);
@ -58,29 +66,36 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
} else { } else {
scope = makeScope(new SourceFileModule[] { makeSourceModule(script, dir, name) }, loaders, JavaScriptLoader.JS); scope = makeScope(new SourceFileModule[] { makeSourceModule(script, dir, name) }, loaders, JavaScriptLoader.JS);
} }
return scope;
return makeCG(loaders, scope, useOneCFA, true);
} }
public static JSCFABuilder makeScriptCGBuilder(String dir, String name) throws IOException { public static JSCFABuilder makeScriptCGBuilder(String dir, String name) throws IOException {
return makeScriptCGBuilder(dir, name, false); return makeScriptCGBuilder(dir, name, false, AstIRFactory.makeDefaultFactory());
} }
public static CallGraph makeScriptCG(String dir, String name) throws IOException, IllegalArgumentException, CancelException { public static CallGraph makeScriptCG(String dir, String name) throws IOException, IllegalArgumentException, CancelException {
return makeScriptCG(dir, name, false); return makeScriptCG(dir, name, AstIRFactory.makeDefaultFactory());
} }
public static CallGraph makeScriptCG(String dir, String name, boolean useOneCFA) throws IOException, IllegalArgumentException, public static CallGraph makeScriptCG(String dir, String name, boolean useOneCFA) throws IOException, IllegalArgumentException, CancelException {
return makeScriptCG(dir, name, useOneCFA, AstIRFactory.makeDefaultFactory());
}
public static CallGraph makeScriptCG(String dir, String name, IRFactory irFactory) throws IOException, IllegalArgumentException, CancelException {
return makeScriptCG(dir, name, false, irFactory);
}
public static CallGraph makeScriptCG(String dir, String name, boolean useOneCFA, IRFactory irFactory) throws IOException, IllegalArgumentException,
CancelException { CancelException {
PropagationCallGraphBuilder b = makeScriptCGBuilder(dir, name, useOneCFA); PropagationCallGraphBuilder b = makeScriptCGBuilder(dir, name, useOneCFA, irFactory);
CallGraph CG = b.makeCallGraph(b.getOptions()); CallGraph CG = b.makeCallGraph(b.getOptions());
dumpCG(b.getPointerAnalysis(), CG); dumpCG(b.getPointerAnalysis(), CG);
return CG; return CG;
} }
public static CallGraph makeScriptCG(SourceModule[] scripts, boolean useOneCFA) throws IOException, IllegalArgumentException, public static CallGraph makeScriptCG(SourceModule[] scripts, boolean useOneCFA, IRFactory irFactory) throws IOException, IllegalArgumentException,
CancelException { CancelException {
PropagationCallGraphBuilder b = makeCGBuilder(makeLoaders(), scripts, useOneCFA, true); PropagationCallGraphBuilder b = makeCGBuilder(makeLoaders(), scripts, useOneCFA, true, irFactory);
CallGraph CG = b.makeCallGraph(b.getOptions()); CallGraph CG = b.makeCallGraph(b.getOptions());
dumpCG(b.getPointerAnalysis(), CG); dumpCG(b.getPointerAnalysis(), CG);
return CG; return CG;
@ -92,7 +107,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
public static JSCFABuilder makeHTMLCGBuilder(URL url, boolean handleCallApply) throws IOException { public static JSCFABuilder makeHTMLCGBuilder(URL url, boolean handleCallApply) throws IOException {
JavaScriptLoader.addBootstrapFile(WebUtil.preamble); JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
Set<MappedSourceModule> script = WebUtil.extractScriptFromHTML(url); Set<MappedSourceModule> script = WebUtil.extractScriptFromHTML(url);
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory, preprocessor), script.toArray(new SourceModule[script.size()]), false, handleCallApply); JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), script.toArray(new SourceModule[script.size()]), false, handleCallApply, AstIRFactory.makeDefaultFactory());
builder.setBaseURL(url); builder.setBaseURL(url);
return builder; return builder;
} }
@ -100,7 +115,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
public static CallGraph makeHTMLCG(URL url) throws IOException, IllegalArgumentException, CancelException { public static CallGraph makeHTMLCG(URL url) throws IOException, IllegalArgumentException, CancelException {
PropagationCallGraphBuilder b = makeHTMLCGBuilder(url); PropagationCallGraphBuilder b = makeHTMLCGBuilder(url);
CallGraph CG = b.makeCallGraph(b.getOptions()); CallGraph CG = b.makeCallGraph(b.getOptions());
//dumpCG(b.getPointerAnalysis(), CG); dumpCG(b.getPointerAnalysis(), CG);
return CG; return CG;
} }
@ -111,19 +126,19 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
return CG; return CG;
} }
public static JSCFABuilder makeCGBuilder(JavaScriptLoaderFactory loaders, SourceModule[] scripts, boolean useOneCFA, boolean handleCallApply) throws IOException { public static JSCFABuilder makeCGBuilder(JavaScriptLoaderFactory loaders, SourceModule[] scripts, boolean useOneCFA, boolean handleCallApply, IRFactory irFactory) throws IOException {
AnalysisScope scope = makeScope(scripts, loaders, JavaScriptLoader.JS); AnalysisScope scope = makeScope(scripts, loaders, JavaScriptLoader.JS);
return makeCG(loaders, scope, useOneCFA, handleCallApply); return makeCG(loaders, scope, useOneCFA, handleCallApply, irFactory);
} }
protected static JSCFABuilder makeCG(JavaScriptLoaderFactory loaders, AnalysisScope scope, boolean useOneCFA, boolean handleCallApply) throws IOException { protected static JSCFABuilder makeCG(JavaScriptLoaderFactory loaders, AnalysisScope scope, boolean useOneCFA, boolean handleCallApply, IRFactory irFactory) throws IOException {
try { try {
IClassHierarchy cha = makeHierarchy(scope, loaders); IClassHierarchy cha = makeHierarchy(scope, loaders);
com.ibm.wala.cast.js.util.Util.checkForFrontEndErrors(cha); com.ibm.wala.cast.js.util.Util.checkForFrontEndErrors(cha);
Iterable<Entrypoint> roots = makeScriptRoots(cha); Iterable<Entrypoint> roots = makeScriptRoots(cha);
JSAnalysisOptions options = makeOptions(scope, cha, roots); JSAnalysisOptions options = makeOptions(scope, cha, roots);
options.setHandleCallApply(handleCallApply); options.setHandleCallApply(handleCallApply);
AnalysisCache cache = makeCache(); AnalysisCache cache = makeCache(irFactory);
JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, useOneCFA); JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, useOneCFA);

View File

@ -0,0 +1,353 @@
package com.ibm.wala.cast.js.ipa.callgraph;
import java.util.Map;
import com.ibm.wala.cast.ipa.callgraph.AstContextInsensitiveSSAContextInterpreter;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.translator.JSAstTranslator;
import com.ibm.wala.cast.js.translator.JSConstantFoldingRewriter;
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
import com.ibm.wala.cast.loader.AstMethod.Retranslatable;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.impl.CAstBasicRewriter;
import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.cfg.AbstractCFG;
import com.ibm.wala.cfg.ControlFlowGraph;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextItem;
import com.ibm.wala.ipa.callgraph.ContextItem.Value;
import com.ibm.wala.ipa.callgraph.ContextKey;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ssa.DefUse;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAOptions;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.intset.IntSet;
public class ArgumentSpecialization {
public static class ArgumentSpecializationContextIntepreter extends AstContextInsensitiveSSAContextInterpreter {
public ArgumentSpecializationContextIntepreter(AnalysisOptions options, AnalysisCache cache) {
super(options, cache);
}
@Override
public IR getIR(CGNode node) {
if (node.getMethod() instanceof Retranslatable) {
return getAnalysisCache().getSSACache().findOrCreateIR(node.getMethod(), node.getContext(), options.getSSAOptions());
} else {
return super.getIR(node);
}
}
public DefUse getDU(CGNode node) {
if (node.getMethod() instanceof Retranslatable) {
return getAnalysisCache().getSSACache().findOrCreateDU(node.getMethod(), node.getContext(), options.getSSAOptions());
} else {
return super.getDU(node);
}
}
}
public static class ArgumentCountContext implements Context {
private final Context base;
private final int argumentCount;
public static ContextKey ARGUMENT_COUNT = new ContextKey() {
public String toString() {
return "argument count key";
}
};
public int hashCode() {
return base.hashCode() + (argumentCount * 4073);
}
public boolean equals(Object o) {
return
o.getClass() == this.getClass() &&
base.equals(((ArgumentCountContext)o).base) &&
argumentCount == ((ArgumentCountContext)o).argumentCount;
}
public ArgumentCountContext(int argumentCount, Context base) {
this.argumentCount = argumentCount;
this.base = base;
}
public ContextItem get(ContextKey name) {
return (name == ARGUMENT_COUNT)? ContextItem.Value.make(argumentCount): base.get(name);
}
public String toString() {
return base.toString() + "(nargs:" + argumentCount + ")";
}
}
public static class ArgumentCountContextSelector implements ContextSelector, ContextKey {
private final ContextSelector base;
public ArgumentCountContextSelector(ContextSelector base) {
this.base = base;
}
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) {
Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters);
if (caller.getMethod() instanceof Retranslatable) {
int v = -1;
for (SSAAbstractInvokeInstruction x : caller.getIR().getCalls(site)) {
if (v == -1) {
v = x.getNumberOfParameters();
} else {
if (v != x.getNumberOfParameters()) {
return baseContext;
}
}
}
return new ArgumentCountContext(v, baseContext);
} else {
return baseContext;
}
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
return base.getRelevantParameters(caller, site);
}
}
public static class ArgumentCountIRFactory extends AstIRFactory.AstDefaultIRFactory {
private final SSAOptions defaultOptions;
public ArgumentCountIRFactory(SSAOptions defaultOptions) {
this.defaultOptions = defaultOptions;
}
@Override
public boolean contextIsIrrelevant(IMethod method) {
return method instanceof Retranslatable? false: super.contextIsIrrelevant(method);
}
@Override
public IR makeIR(final IMethod method, Context context, SSAOptions options) {
if (method instanceof Retranslatable) {
@SuppressWarnings("unchecked")
final Value<Integer> v = (Value<Integer>) context.get(ArgumentCountContext.ARGUMENT_COUNT);
final Retranslatable m = (Retranslatable)method;
if (v != null) {
final JavaScriptLoader myloader = (JavaScriptLoader) method.getDeclaringClass().getClassLoader();
class FixedArgumentsRewriter extends CAstBasicRewriter {
private final CAstEntity e = m.getEntity();
public FixedArgumentsRewriter(CAst Ast) {
super(Ast, false);
}
private boolean isNamedVar(CAstNode n, String name) {
if (n.getKind() == CAstNode.VAR) {
String nm = (String) n.getChild(0).getValue();
return nm.equals(name);
}
return false;
}
private Object getIndexFromArgumentRef(CAstNode n) {
if (n.getKind() == CAstNode.OBJECT_REF || n.getKind() == CAstNode.ARRAY_REF) {
if (isNamedVar(n.getChild(0), "arguments")) {
return n.getChild(1).getValue();
}
}
return null;
}
private Object getIndexFromBaseVar(CAstNode n) {
if (n.getKind() == CAstNode.BLOCK_EXPR) {
if (n.getChildCount() == 2) {
CAstNode c1 = n.getChild(0);
if (c1.getKind() == CAstNode.ASSIGN) {
if (isNamedVar(c1.getChild(0), "base")) {
if (isNamedVar(c1.getChild(1), "arguments")) {
CAstNode c2 = n.getChild(1);
if (c2.getKind() == CAstNode.OBJECT_REF || c2.getKind() == CAstNode.ARRAY_REF) {
if (isNamedVar(c2.getChild(0), "base")) {
return c2.getChild(1).getValue();
}
}
}
}
}
}
}
return null;
}
private Object getStaticArgumentIndex(CAstNode n) {
Object x = getIndexFromArgumentRef(n);
if (x != null) {
return x;
} else {
return getIndexFromBaseVar(n);
}
}
private CAstNode handleArgumentRef(CAstNode n) {
Object x = getStaticArgumentIndex(n);
if (x != null) {
if (x instanceof Number && ((Number)x).intValue() < v.getValue()-2) {
int arg = ((Number)x).intValue() + 3;
if (arg < e.getArgumentCount()) {
return Ast.makeNode(CAstNode.VAR, Ast.makeConstant(e.getArgumentNames()[arg]));
} else {
return Ast.makeNode(CAstNode.VAR, Ast.makeConstant("$arg" + arg));
}
} else if (x instanceof String && "length".equals(x)) {
return Ast.makeConstant(v.getValue());
}
}
return null;
}
@Override
protected CAstNode copyNodes(CAstNode root,
CAstControlFlowMap cfg,
NonCopyingContext context,
Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap)
{
CAstNode result = null;
if (root.getKind() == CAstNode.ARRAY_REF
|| root.getKind() == CAstNode.OBJECT_REF
|| root.getKind() == CAstNode.BLOCK_EXPR)
{
result = handleArgumentRef(root);
} else if (root.getKind() == CAstNode.CONSTANT) {
result = Ast.makeConstant(root.getValue());
} else if (root.getKind() == CAstNode.OPERATOR) {
result = root;
}
if (result == null) {
CAstNode children[] = new CAstNode[root.getChildCount()];
for (int i = 0; i < children.length; i++) {
children[i] = copyNodes(root.getChild(i), cfg, context, nodeMap);
}
for(Object label: cfg.getTargetLabels(root)) {
if (label instanceof CAstNode) {
copyNodes((CAstNode)label, cfg, context, nodeMap);
}
}
CAstNode copy = Ast.makeNode(root.getKind(), children);
result = copy;
}
nodeMap.put(Pair.make(root, context.key()), result);
return result;
}
}
final FixedArgumentsRewriter args = new FixedArgumentsRewriter(new CAstImpl());
final JSConstantFoldingRewriter fold = new JSConstantFoldingRewriter(new CAstImpl());
class ArgumentativeTranslator extends JSAstTranslator {
public ArgumentativeTranslator(JavaScriptLoader loader) {
super(loader);
}
private CAstEntity codeBodyEntity;
private IMethod specializedCode;
@Override
protected int getArgumentCount(CAstEntity f) {
return Math.max(super.getArgumentCount(f), v.getValue());
}
@Override
protected String[] getArgumentNames(CAstEntity f) {
if (super.getArgumentCount(f) >= v.getValue()) {
return super.getArgumentNames(f);
} else {
String[] argNames = new String[ v.getValue() ];
System.arraycopy(super.getArgumentNames(f), 0, argNames, 0, super.getArgumentCount(f));
for(int i = super.getArgumentCount(f); i < argNames.length; i++) {
argNames[i] = "$arg" + (i+1);
}
return argNames;
}
}
@Override
protected String composeEntityName(WalkContext parent, CAstEntity f) {
if (f == codeBodyEntity) {
return super.composeEntityName(parent, f) + "_" + v.getValue().intValue();
} else {
return super.composeEntityName(parent, f);
}
}
@Override
protected void defineFunction(CAstEntity N, WalkContext definingContext, AbstractCFG cfg, SymbolTable symtab,
boolean hasCatchBlock, TypeReference[][] caughtTypes, boolean hasMonitorOp, AstLexicalInformation LI,
DebuggingInformation debugInfo) {
if (N == codeBodyEntity) {
specializedCode = myloader.makeCodeBodyCode(cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, LI, debugInfo, method.getDeclaringClass());
} else {
super.defineFunction(N, definingContext, cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, LI, debugInfo);
}
}
@Override
public void translate(CAstEntity N, WalkContext context) {
if (N == m.getEntity()) {
codeBodyEntity = fold.rewrite(args.rewrite(N));
super.translate(codeBodyEntity, context);
} else {
super.translate(N, context);
}
}
}
ArgumentativeTranslator a = new ArgumentativeTranslator(myloader);
m.retranslate(a);
return super.makeIR(a.specializedCode, context, options);
}
}
return super.makeIR(method, context, options);
}
@Override
public ControlFlowGraph makeCFG(IMethod method, Context context) {
return makeIR(method, context, defaultOptions).getControlFlowGraph();
}
}
}

View File

@ -16,7 +16,6 @@ public class GlobalObjectKey implements InstanceKey {
this.concreteType = concreteType; this.concreteType = concreteType;
} }
@Override
public IClass getConcreteType() { public IClass getConcreteType() {
return concreteType; return concreteType;
} }

View File

@ -686,15 +686,17 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
system.newConstraint(F, constParams[i][j]); system.newConstraint(F, constParams[i][j]);
} }
if (av != -1 && i > num_pseudoargs) if (av != -1 && i > num_pseudoargs) {
targetVisitor.newFieldWrite(target, av, fn, constParams[i]); targetVisitor.newFieldWrite(target, av, fn, constParams[i]);
}
} else { } else {
PointerKey A = getPointerKeyForLocal(caller, instruction.getUse(i)); PointerKey A = getPointerKeyForLocal(caller, instruction.getUse(i));
system.newConstraint(F, (F instanceof FilteredPointerKey) ? filterOperator : assignOperator, A); system.newConstraint(F, (F instanceof FilteredPointerKey) ? filterOperator : assignOperator, A);
if (av != -1 && i > num_pseudoargs) if (av != -1 && i > num_pseudoargs) {
targetVisitor.newFieldWrite(target, av, fn, F); targetVisitor.newFieldWrite(target, av, fn, F);
}
} }
} }

View File

@ -91,7 +91,6 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
this.isNonNullArray = new BooleanContextItem(isNonNullArray); this.isNonNullArray = new BooleanContextItem(isNonNullArray);
} }
@Override
public ContextItem get(ContextKey name) { public ContextItem get(ContextKey name) {
if (APPLY_NON_NULL_ARGS.equals(name)) { if (APPLY_NON_NULL_ARGS.equals(name)) {
return isNonNullArray; return isNonNullArray;

View File

@ -62,7 +62,6 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele
* .wala.ipa.callgraph.CGNode, com.ibm.wala.classLoader.CallSiteReference, * .wala.ipa.callgraph.CGNode, com.ibm.wala.classLoader.CallSiteReference,
* com.ibm.wala.classLoader.IClass) * com.ibm.wala.classLoader.IClass)
*/ */
@Override
public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) {
IMethod method = receiver.getMethod(AstMethodReference.fnSelector); IMethod method = receiver.getMethod(AstMethodReference.fnSelector);
if (method != null) { if (method != null) {

View File

@ -50,7 +50,6 @@ public class ObjectSensitivityContextSelector implements ContextSelector {
return false; return false;
} }
@Override
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] arguments) { public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] arguments) {
Context baseContext = base.getCalleeTarget(caller, site, callee, arguments); Context baseContext = base.getCalleeTarget(caller, site, callee, arguments);
if(returnsThis(callee)) { if(returnsThis(callee)) {
@ -61,7 +60,6 @@ public class ObjectSensitivityContextSelector implements ContextSelector {
return baseContext; return baseContext;
} }
@Override
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
if (caller.getIR().getCalls(site)[0].getNumberOfUses() > 1) { if (caller.getIR().getCalls(site)[0].getNumberOfUses() > 1) {
return IntSetUtil.make(new int[]{1}).union(base.getRelevantParameters(caller, site)); return IntSetUtil.make(new int[]{1}).union(base.getRelevantParameters(caller, site));
@ -83,7 +81,6 @@ class ArgumentInstanceContext implements Context {
this.instanceKey = instanceKey; this.instanceKey = instanceKey;
} }
@Override
public ContextItem get(ContextKey name) { public ContextItem get(ContextKey name) {
/*if(name == ContextKey.RECEIVER && index == 1) /*if(name == ContextKey.RECEIVER && index == 1)
return instanceKey;*/ return instanceKey;*/

View File

@ -163,16 +163,15 @@ public class Util extends com.ibm.wala.cast.ipa.callgraph.Util {
} }
@Override @Override
protected void leaveFunctionStmt(CAstNode n, Context c, CAstVisitor visitor) { protected void leaveFunctionStmt(CAstNode n, WalkContext c, CAstVisitor<WalkContext> visitor) {
WalkContext context = (WalkContext) c;
CAstEntity fn = (CAstEntity) n.getChild(0).getValue(); CAstEntity fn = (CAstEntity) n.getChild(0).getValue();
Scope cs = context.currentScope(); Scope cs = c.currentScope();
if (!cs.contains(fn.getName()) if (!cs.contains(fn.getName())
|| cs.lookup(fn.getName()).getDefiningScope().getEntity().getKind() == CAstEntity.SCRIPT_ENTITY) { || cs.lookup(fn.getName()).getDefiningScope().getEntity().getKind() == CAstEntity.SCRIPT_ENTITY) {
int result = processFunctionExpr(n, c); int result = processFunctionExpr(n, c);
assignValue(n, context, cs.lookup(fn.getName()), fn.getName(), result); assignValue(n, c, cs.lookup(fn.getName()), fn.getName(), result);
} else { } else {
super.leaveFunctionStmt(n, context, visitor); super.leaveFunctionStmt(n, c, visitor);
} }
} }
}; };

View File

@ -216,7 +216,6 @@ public class CorrelationFinder {
Collections.sort(correlations, new Comparator<Pair<Position, String>>() { Collections.sort(correlations, new Comparator<Pair<Position, String>>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override
public int compare(Pair<Position, String> o1, Pair<Position, String> o2) { public int compare(Pair<Position, String> o1, Pair<Position, String> o2) {
return o1.fst.compareTo(o2.fst); return o1.fst.compareTo(o2.fst);
} }

View File

@ -196,50 +196,50 @@ public class ClosureExtractor extends CAstRewriterExt {
} }
@Override @Override
protected CAstNode copyNodes(CAstNode root, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) { protected CAstNode copyNodes(CAstNode root, CAstControlFlowMap cfg, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) {
switch(root.getKind()) { switch(root.getKind()) {
case OPERATOR: case OPERATOR:
return root; return root;
case CONSTANT: case CONSTANT:
return copyConstant(root, context, nodeMap); return copyConstant(root, cfg, context, nodeMap);
case BLOCK_STMT: case BLOCK_STMT:
return copyBlock(root, context, nodeMap); return copyBlock(root, cfg, context, nodeMap);
case RETURN: case RETURN:
return copyReturn(root, context, nodeMap); return copyReturn(root, cfg, context, nodeMap);
case VAR: case VAR:
return copyVar(root, context, nodeMap); return copyVar(root, cfg, context, nodeMap);
case GOTO: case GOTO:
return copyGoto(root, context, nodeMap); return copyGoto(root, cfg, context, nodeMap);
default: default:
return copyNode(root, context, nodeMap); return copyNode(root, cfg, context, nodeMap);
} }
} }
/* Constants are not affected by the rewriting, they are just copied. */ /* Constants are not affected by the rewriting, they are just copied. */
private CAstNode copyConstant(CAstNode root, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) { private CAstNode copyConstant(CAstNode root, CAstControlFlowMap cfg, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) {
CAstNode newNode = Ast.makeConstant(root.getValue()); CAstNode newNode = Ast.makeConstant(root.getValue());
nodeMap.put(Pair.make(root, context.key()), newNode); nodeMap.put(Pair.make(root, context.key()), newNode);
return newNode; return newNode;
} }
/* Ask the policy whether it wants anything extracted from this block; otherwise the node is simply copied. */ /* Ask the policy whether it wants anything extracted from this block; otherwise the node is simply copied. */
private CAstNode copyBlock(CAstNode root, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) { private CAstNode copyBlock(CAstNode root, CAstControlFlowMap cfg, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) {
List<ExtractionRegion> regions = policies.getFirst().extract(root); List<ExtractionRegion> regions = policies.getFirst().extract(root);
if(regions == null) { if(regions == null) {
return copyNode(root, context, nodeMap); return copyNode(root, cfg, context, nodeMap);
} else { } else {
ArrayList<CAstNode> copied_children = new ArrayList<CAstNode>(); ArrayList<CAstNode> copied_children = new ArrayList<CAstNode>();
int next_child = 0; int next_child = 0;
// code in between regions is handled by invoking copyNodes, the regions themselves by extractRegion // code in between regions is handled by invoking copyNodes, the regions themselves by extractRegion
for(ExtractionRegion region : regions) { for(ExtractionRegion region : regions) {
for(;next_child<region.getStart();++next_child) for(;next_child<region.getStart();++next_child)
copied_children.add(copyNodes(root.getChild(next_child), new ChildPos(root, next_child, context), nodeMap)); copied_children.add(copyNodes(root.getChild(next_child), cfg, new ChildPos(root, next_child, context), nodeMap));
for(CAstNode stmt : extractRegion(root, new ExtractionPos(root, region, context), nodeMap)) for(CAstNode stmt : extractRegion(root, cfg, new ExtractionPos(root, region, context), nodeMap))
copied_children.add(stmt); copied_children.add(stmt);
next_child = region.getEnd(); next_child = region.getEnd();
} }
for(;next_child<root.getChildCount();++next_child) for(;next_child<root.getChildCount();++next_child)
copied_children.add(copyNodes(root.getChild(next_child), new ChildPos(root, next_child, context), nodeMap)); copied_children.add(copyNodes(root.getChild(next_child), cfg, new ChildPos(root, next_child, context), nodeMap));
CAstNode newNode = Ast.makeNode(BLOCK_STMT, copied_children.toArray(new CAstNode[0])); CAstNode newNode = Ast.makeNode(BLOCK_STMT, copied_children.toArray(new CAstNode[0]));
nodeMap.put(Pair.make(root, context.key()), newNode); nodeMap.put(Pair.make(root, context.key()), newNode);
return newNode; return newNode;
@ -250,7 +250,7 @@ public class ClosureExtractor extends CAstRewriterExt {
* Normal variables are just copied, but 'this' references need to be rewritten if we are inside an extracted * Normal variables are just copied, but 'this' references need to be rewritten if we are inside an extracted
* function body. * function body.
*/ */
private CAstNode copyVar(CAstNode root, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) { private CAstNode copyVar(CAstNode root, CAstControlFlowMap cfg, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) {
/* /*
* If this node is a "this" reference, the outermost enclosing extracted function needs to pass in * If this node is a "this" reference, the outermost enclosing extracted function needs to pass in
* the value of "this" as a parameter. * the value of "this" as a parameter.
@ -268,10 +268,10 @@ public class ClosureExtractor extends CAstRewriterExt {
nodeMap.put(Pair.make(root, context.key()), newNode); nodeMap.put(Pair.make(root, context.key()), newNode);
return newNode; return newNode;
} else { } else {
return copyNode(root, context, nodeMap); return copyNode(root, cfg, context, nodeMap);
} }
} else { } else {
return copyNode(root, context, nodeMap); return copyNode(root, cfg, context, nodeMap);
} }
} }
@ -279,7 +279,7 @@ public class ClosureExtractor extends CAstRewriterExt {
* 'break' and 'continue' statements are both encoded as GOTO. If they refer to a target outside the innermost * 'break' and 'continue' statements are both encoded as GOTO. If they refer to a target outside the innermost
* enclosing extracted function body, they are rewritten into a 'return' statement. * enclosing extracted function body, they are rewritten into a 'return' statement.
*/ */
private CAstNode copyGoto(CAstNode root, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) { private CAstNode copyGoto(CAstNode root, CAstControlFlowMap cfg, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) {
CAstNode target = getCurrentEntity().getControlFlow().getTarget(root, null); CAstNode target = getCurrentEntity().getControlFlow().getTarget(root, null);
ExtractionPos epos = ExtractionPos.getEnclosingExtractionPos(context); ExtractionPos epos = ExtractionPos.getEnclosingExtractionPos(context);
if(epos != null && !NodePos.inSubtree(target, epos.getParent())) { if(epos != null && !NodePos.inSubtree(target, epos.getParent())) {
@ -301,18 +301,18 @@ public class ClosureExtractor extends CAstRewriterExt {
nodeMap.put(Pair.make(root, context.key()), newNode); nodeMap.put(Pair.make(root, context.key()), newNode);
return newNode; return newNode;
} else { } else {
return copyNode(root, context, nodeMap); return copyNode(root, cfg, context, nodeMap);
} }
} }
/* 'return' statements inside an extracted function body need to be encoded in a similar fashion. */ /* 'return' statements inside an extracted function body need to be encoded in a similar fashion. */
private CAstNode copyReturn(CAstNode root, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) { private CAstNode copyReturn(CAstNode root, CAstControlFlowMap cfg, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) {
ExtractionPos epos = ExtractionPos.getEnclosingExtractionPos(context); ExtractionPos epos = ExtractionPos.getEnclosingExtractionPos(context);
// if an extracted function body may terminate normally, we need to append a default RETURN node // if an extracted function body may terminate normally, we need to append a default RETURN node
// which should not be rewritten; this node is marked as 'synthetic' // which should not be rewritten; this node is marked as 'synthetic'
if(epos == null || isSynthetic(root)) if(epos == null || isSynthetic(root))
return copyNode(root, context, nodeMap); return copyNode(root, cfg, context, nodeMap);
// add a return to every enclosing extracted function body // add a return to every enclosing extracted function body
do { do {
@ -323,7 +323,7 @@ public class ClosureExtractor extends CAstRewriterExt {
// emit appropriate 'return' statement // emit appropriate 'return' statement
if(root.getChildCount() > 0) { if(root.getChildCount() > 0) {
// return { type: 'return', value: <retval> } // return { type: 'return', value: <retval> }
CAstNode retval = copyNodes(root.getChild(0), new ChildPos(root, 0, context), nodeMap); CAstNode retval = copyNodes(root.getChild(0), cfg, new ChildPos(root, 0, context), nodeMap);
CAstNode newNode = CAstNode newNode =
Ast.makeNode(RETURN, Ast.makeNode(RETURN,
Ast.makeNode(OBJECT_LITERAL, Ast.makeNode(OBJECT_LITERAL,
@ -352,10 +352,10 @@ public class ClosureExtractor extends CAstRewriterExt {
} }
/* Recursively copy child nodes. */ /* Recursively copy child nodes. */
private CAstNode copyNode(CAstNode node, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) { private CAstNode copyNode(CAstNode node, CAstControlFlowMap cfg, NodePos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) {
CAstNode children[] = new CAstNode[node.getChildCount()]; CAstNode children[] = new CAstNode[node.getChildCount()];
for (int i = 0; i < children.length; i++) { for (int i = 0; i < children.length; i++) {
children[i] = copyNodes(node.getChild(i), new ChildPos(node, i, context), nodeMap); children[i] = copyNodes(node.getChild(i), cfg, new ChildPos(node, i, context), nodeMap);
} }
CAstNode newNode = Ast.makeNode(node.getKind(), children); CAstNode newNode = Ast.makeNode(node.getKind(), children);
nodeMap.put(Pair.make(node, context.key()), newNode); nodeMap.put(Pair.make(node, context.key()), newNode);
@ -363,7 +363,7 @@ public class ClosureExtractor extends CAstRewriterExt {
// if this node has a control flow successor beyond the innermost enclosing extracted function loop, we need to reroute // if this node has a control flow successor beyond the innermost enclosing extracted function loop, we need to reroute
ExtractionPos epos = ExtractionPos.getEnclosingExtractionPos(context); ExtractionPos epos = ExtractionPos.getEnclosingExtractionPos(context);
if(!isFlowDeleted(newNode, getCurrentEntity()) && epos != null) { if(!isFlowDeleted(newNode, getCurrentEntity()) && epos != null) {
CAstControlFlowMap cfg = getCurrentEntity().getControlFlow(); // CAstControlFlowMap cfg = getCurrentEntity().getControlFlow();
Collection<Object> labels = cfg.getTargetLabels(node); Collection<Object> labels = cfg.getTargetLabels(node);
boolean invalidateCFlow = false; boolean invalidateCFlow = false;
for(Object label : labels) { for(Object label : labels) {
@ -388,7 +388,7 @@ public class ClosureExtractor extends CAstRewriterExt {
} }
private int anonymous_counter = 0; private int anonymous_counter = 0;
private List<CAstNode> extractRegion(CAstNode root, ExtractionPos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) { private List<CAstNode> extractRegion(CAstNode root, CAstControlFlowMap cfg, ExtractionPos context, Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) {
CAstEntity entity = getCurrentEntity(); CAstEntity entity = getCurrentEntity();
// whether we are extracting a single statement that is itself a block // whether we are extracting a single statement that is itself a block
@ -434,7 +434,7 @@ public class ClosureExtractor extends CAstRewriterExt {
throw new UnimplementedError("Two-level extraction not fully implemented."); throw new UnimplementedError("Two-level extraction not fully implemented.");
int i; int i;
for(i=0;i<tler.getStartInner();++i) for(i=0;i<tler.getStartInner();++i)
prologue.add(copyNodes(start.getChild(i),context, nodeMap)); prologue.add(copyNodes(start.getChild(i), cfg, context, nodeMap));
for(;i<start.getChildCount();++i) for(;i<start.getChildCount();++i)
fun_body_stmts.add(start.getChild(i)); fun_body_stmts.add(start.getChild(i));
for(i=context.getStart()+1;i<context.getEnd();++i) for(i=context.getStart()+1;i<context.getEnd();++i)
@ -459,7 +459,7 @@ public class ClosureExtractor extends CAstRewriterExt {
* Now we rewrite the body and construct a Rewrite object. * Now we rewrite the body and construct a Rewrite object.
*/ */
final Map<Pair<CAstNode, NoKey>, CAstNode> nodes = HashMapFactory.make(); final Map<Pair<CAstNode, NoKey>, CAstNode> nodes = HashMapFactory.make();
final CAstNode newRoot = copyNodes(fun_body, context, nodes); final CAstNode newRoot = copyNodes(fun_body, cfg, context, nodes);
final CAstSourcePositionMap theSource = copySource(nodes, entity.getSourceMap()); final CAstSourcePositionMap theSource = copySource(nodes, entity.getSourceMap());
final CAstControlFlowMap theCfg = copyFlow(nodes, entity.getControlFlow(), theSource); final CAstControlFlowMap theCfg = copyFlow(nodes, entity.getControlFlow(), theSource);
final CAstNodeTypeMap theTypes = copyTypes(nodes, entity.getNodeTypeMap()); final CAstNodeTypeMap theTypes = copyTypes(nodes, entity.getNodeTypeMap());
@ -468,11 +468,11 @@ public class ClosureExtractor extends CAstRewriterExt {
theChildren.putAll(copyChildren(root.getChild(i), nodes, entity.getAllScopedEntities())); theChildren.putAll(copyChildren(root.getChild(i), nodes, entity.getAllScopedEntities()));
Rewrite rw = new Rewrite() { Rewrite rw = new Rewrite() {
@Override public CAstNode newRoot() { return newRoot; } public CAstNode newRoot() { return newRoot; }
@Override public CAstControlFlowMap newCfg() { return theCfg; } public CAstControlFlowMap newCfg() { return theCfg; }
@Override public CAstSourcePositionMap newPos() { return theSource; } public CAstSourcePositionMap newPos() { return theSource; }
@Override public CAstNodeTypeMap newTypes() { return theTypes; } public CAstNodeTypeMap newTypes() { return theTypes; }
@Override public Map<CAstNode, Collection<CAstEntity>> newChildren() { return theChildren; } public Map<CAstNode, Collection<CAstEntity>> newChildren() { return theChildren; }
}; };
new_entity.setRewrite(rw); new_entity.setRewrite(rw);
@ -724,4 +724,5 @@ public class ClosureExtractor extends CAstRewriterExt {
synthetic.add(node); synthetic.add(node);
return node; return node;
} }
} }

View File

@ -37,7 +37,6 @@ public class CorrelatedPairExtractorFactory implements CAstRewriterFactory<NodeP
this.summaries = summaries; this.summaries = summaries;
} }
@Override
public CAstRewriter<NodePos, NoKey> createCAstRewriter(CAst ast) { public CAstRewriter<NodePos, NoKey> createCAstRewriter(CAst ast) {
ExtractionPolicyFactory policyFactory = new ExtractionPolicyFactory() { ExtractionPolicyFactory policyFactory = new ExtractionPolicyFactory() {
@Override @Override

View File

@ -61,33 +61,27 @@ class ExtractedFunction implements CAstEntity {
this.types = r.newTypes(); this.types = r.newTypes();
} }
@Override
public int getKind() { public int getKind() {
return CAstEntity.FUNCTION_ENTITY; return CAstEntity.FUNCTION_ENTITY;
} }
@Override
public String getName() { public String getName() {
return name; return name;
} }
@Override
public String getSignature() { public String getSignature() {
return null; return null;
} }
@Override
public String[] getArgumentNames() { public String[] getArgumentNames() {
computeParms(); computeParms();
return parms; return parms;
} }
@Override
public CAstNode[] getArgumentDefaults() { public CAstNode[] getArgumentDefaults() {
return new CAstNode[0]; return new CAstNode[0];
} }
@Override
public int getArgumentCount() { public int getArgumentCount() {
computeParms(); computeParms();
return parms.length; return parms.length;
@ -105,7 +99,6 @@ class ExtractedFunction implements CAstEntity {
} }
} }
@Override
public Map<CAstNode, Collection<CAstEntity>> getAllScopedEntities() { public Map<CAstNode, Collection<CAstEntity>> getAllScopedEntities() {
if(scopedEntities == null) { if(scopedEntities == null) {
scopedEntities = HashMapFactory.make(); scopedEntities = HashMapFactory.make();
@ -132,7 +125,6 @@ class ExtractedFunction implements CAstEntity {
return scopedEntities; return scopedEntities;
} }
@Override
public Iterator<CAstEntity> getScopedEntities(CAstNode construct) { public Iterator<CAstEntity> getScopedEntities(CAstNode construct) {
if(getAllScopedEntities().containsKey(construct)) { if(getAllScopedEntities().containsKey(construct)) {
return getAllScopedEntities().get(construct).iterator(); return getAllScopedEntities().get(construct).iterator();
@ -141,37 +133,30 @@ class ExtractedFunction implements CAstEntity {
} }
} }
@Override
public CAstNode getAST() { public CAstNode getAST() {
return root; return root;
} }
@Override
public CAstControlFlowMap getControlFlow() { public CAstControlFlowMap getControlFlow() {
return cfg; return cfg;
} }
@Override
public CAstSourcePositionMap getSourceMap() { public CAstSourcePositionMap getSourceMap() {
return posmap; return posmap;
} }
@Override
public Position getPosition() { public Position getPosition() {
return getSourceMap().getPosition(root); return getSourceMap().getPosition(root);
} }
@Override
public CAstNodeTypeMap getNodeTypeMap() { public CAstNodeTypeMap getNodeTypeMap() {
return types; return types;
} }
@Override
public Collection<CAstQualifier> getQualifiers() { public Collection<CAstQualifier> getQualifiers() {
return null; return null;
} }
@Override
public CAstType getType() { public CAstType getType() {
return null; return null;
} }

View File

@ -26,7 +26,6 @@ import com.ibm.wala.cast.tree.impl.CAstBasicRewriter.NoKey;
public abstract class NodePos implements CAstRewriter.RewriteContext<CAstBasicRewriter.NoKey> { public abstract class NodePos implements CAstRewriter.RewriteContext<CAstBasicRewriter.NoKey> {
public abstract <A> A accept(PosSwitch<A> ps); public abstract <A> A accept(PosSwitch<A> ps);
@Override
public NoKey key() { public NoKey key() {
return null; return null;
} }

View File

@ -33,6 +33,7 @@ import com.ibm.wala.cast.ir.ssa.EachElementGetInstruction;
import com.ibm.wala.cast.ir.ssa.EachElementHasNextInstruction; import com.ibm.wala.cast.ir.ssa.EachElementHasNextInstruction;
import com.ibm.wala.cast.ir.translator.AstTranslator; import com.ibm.wala.cast.ir.translator.AstTranslator;
import com.ibm.wala.cast.ir.translator.AstTranslator.AstLexicalInformation; import com.ibm.wala.cast.ir.translator.AstTranslator.AstLexicalInformation;
import com.ibm.wala.cast.ir.translator.AstTranslator.WalkContext;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst; import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.ir.translator.TranslatorToIR; import com.ibm.wala.cast.ir.translator.TranslatorToIR;
import com.ibm.wala.cast.js.analysis.typeInference.JSPrimitiveType; import com.ibm.wala.cast.js.analysis.typeInference.JSPrimitiveType;
@ -52,6 +53,7 @@ import com.ibm.wala.cast.loader.AstDynamicPropertyClass;
import com.ibm.wala.cast.loader.AstFunctionClass; import com.ibm.wala.cast.loader.AstFunctionClass;
import com.ibm.wala.cast.loader.AstMethod; import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation; import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
import com.ibm.wala.cast.loader.AstMethod.Retranslatable;
import com.ibm.wala.cast.loader.CAstAbstractModuleLoader; import com.ibm.wala.cast.loader.CAstAbstractModuleLoader;
import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
@ -641,19 +643,25 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
} }
class JavaScriptCodeBody extends AstFunctionClass { class JavaScriptCodeBody extends AstFunctionClass {
private final WalkContext translationContext;
private final CAstEntity entity;
public JavaScriptCodeBody(TypeReference codeName, TypeReference parent, IClassLoader loader, public JavaScriptCodeBody(TypeReference codeName, TypeReference parent, IClassLoader loader,
CAstSourcePositionMap.Position sourcePosition) { CAstSourcePositionMap.Position sourcePosition, CAstEntity entity, WalkContext context) {
super(codeName, parent, loader, sourcePosition); super(codeName, parent, loader, sourcePosition);
types.put(codeName.getName(), this); types.put(codeName.getName(), this);
this.translationContext = context;
this.entity = entity;
} }
public IClassHierarchy getClassHierarchy() { public IClassHierarchy getClassHierarchy() {
return cha; return cha;
} }
private IMethod setCodeBody(IMethod codeBody) { private IMethod setCodeBody(JavaScriptMethodObject codeBody) {
this.functionBody = codeBody; this.functionBody = codeBody;
codeBody.entity = entity;
codeBody.translationContext = translationContext;
return codeBody; return codeBody;
} }
} }
@ -666,12 +674,27 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
functionQualifiers.add(CAstQualifier.FINAL); functionQualifiers.add(CAstQualifier.FINAL);
} }
public class JavaScriptMethodObject extends AstMethod { public class JavaScriptMethodObject extends AstMethod implements Retranslatable {
private WalkContext translationContext;
private CAstEntity entity;
JavaScriptMethodObject(JavaScriptCodeBody cls, AbstractCFG cfg, SymbolTable symtab, boolean hasCatchBlock, JavaScriptMethodObject(IClass cls, AbstractCFG cfg, SymbolTable symtab, boolean hasCatchBlock,
TypeReference[][] caughtTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo) { TypeReference[][] caughtTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo) {
super(cls, functionQualifiers, cfg, symtab, AstMethodReference.fnReference(cls.getReference()), hasCatchBlock, caughtTypes, super(cls, functionQualifiers, cfg, symtab, AstMethodReference.fnReference(cls.getReference()), hasCatchBlock, caughtTypes,
hasMonitorOp, lexicalInfo, debugInfo); hasMonitorOp, lexicalInfo, debugInfo);
// force creation of these constants by calling the getter methods
symtab.getNullConstant();
}
public CAstEntity getEntity() {
return entity;
}
public void retranslate(AstTranslator xlator) {
xlator.translate(entity, translationContext);
} }
public IClassHierarchy getClassHierarchy() { public IClassHierarchy getClassHierarchy() {
@ -745,25 +768,31 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
} }
} }
public IClass defineCodeBodyType(String name, TypeReference P, CAstSourcePositionMap.Position sourcePosition) { public IClass makeCodeBodyType(String name, TypeReference P, CAstSourcePositionMap.Position sourcePosition, CAstEntity entity, WalkContext context) {
return new JavaScriptCodeBody(TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName(name)), P, this, return new JavaScriptCodeBody(TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName(name)), P, this,
sourcePosition); sourcePosition, entity, context);
} }
public IClass defineFunctionType(String name, CAstSourcePositionMap.Position pos) { public IClass defineFunctionType(String name, CAstSourcePositionMap.Position pos, CAstEntity entity, WalkContext context) {
return defineCodeBodyType(name, JavaScriptTypes.Function, pos); return makeCodeBodyType(name, JavaScriptTypes.Function, pos, entity, context);
} }
public IClass defineScriptType(String name, CAstSourcePositionMap.Position pos) { public IClass defineScriptType(String name, CAstSourcePositionMap.Position pos, CAstEntity entity, WalkContext context) {
return defineCodeBodyType(name, JavaScriptTypes.Script, pos); return makeCodeBodyType(name, JavaScriptTypes.Script, pos, entity, context);
} }
public IMethod defineCodeBodyCode(String clsName, AbstractCFG cfg, SymbolTable symtab, boolean hasCatchBlock, public IMethod defineCodeBodyCode(String clsName, AbstractCFG cfg, SymbolTable symtab, boolean hasCatchBlock,
TypeReference[][] caughtTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo) { TypeReference[][] caughtTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo) {
JavaScriptCodeBody C = (JavaScriptCodeBody) lookupClass(clsName, cha); JavaScriptCodeBody C = (JavaScriptCodeBody) lookupClass(clsName, cha);
assert C != null : clsName; assert C != null : clsName;
return C.setCodeBody(new JavaScriptMethodObject(C, cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, lexicalInfo, return C.setCodeBody(makeCodeBodyCode(cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, lexicalInfo, debugInfo, C));
debugInfo)); }
public JavaScriptMethodObject makeCodeBodyCode(AbstractCFG cfg, SymbolTable symtab, boolean hasCatchBlock,
TypeReference[][] caughtTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo,
IClass C) {
return new JavaScriptMethodObject(C, cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, lexicalInfo,
debugInfo);
} }
final JavaScriptRootClass ROOT = new JavaScriptRootClass(this, null); final JavaScriptRootClass ROOT = new JavaScriptRootClass(this, null);

View File

@ -125,9 +125,9 @@ public class JSAstTranslator extends AstTranslator {
protected void declareFunction(CAstEntity N, WalkContext context) { protected void declareFunction(CAstEntity N, WalkContext context) {
String fnName = composeEntityName(context, N); String fnName = composeEntityName(context, N);
if (N.getKind() == CAstEntity.SCRIPT_ENTITY) { if (N.getKind() == CAstEntity.SCRIPT_ENTITY) {
((JavaScriptLoader) loader).defineScriptType("L" + fnName, N.getPosition()); ((JavaScriptLoader) loader).defineScriptType("L" + fnName, N.getPosition(), N, context);
} else if (N.getKind() == CAstEntity.FUNCTION_ENTITY) { } else if (N.getKind() == CAstEntity.FUNCTION_ENTITY) {
((JavaScriptLoader) loader).defineFunctionType("L" + fnName, N.getPosition()); ((JavaScriptLoader) loader).defineFunctionType("L" + fnName, N.getPosition(), N, context);
} else { } else {
Assertions.UNREACHABLE(); Assertions.UNREACHABLE();
} }
@ -142,9 +142,6 @@ public class JSAstTranslator extends AstTranslator {
if (DEBUG) if (DEBUG)
System.err.println(cfg); System.err.println(cfg);
// force creation of these constants by calling the getter methods
symtab.getNullConstant();
((JavaScriptLoader) loader).defineCodeBodyCode("L" + fnName, cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, LI, ((JavaScriptLoader) loader).defineCodeBodyCode("L" + fnName, cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, LI,
debugInfo); debugInfo);
@ -211,7 +208,7 @@ public class JSAstTranslator extends AstTranslator {
context.currentScope().getConstantValue(field); context.currentScope().getConstantValue(field);
context.cfg().addInstruction(((JSInstructionFactory) insts).GetInstruction(result, x, field)); context.cfg().addInstruction(((JSInstructionFactory) insts).GetInstruction(result, x, field));
} else { } else {
context.cfg().addInstruction(((JSInstructionFactory) insts).PropertyRead(result, x, getValue(elt))); context.cfg().addInstruction(((JSInstructionFactory) insts).PropertyRead(result, x, context.getValue(elt)));
} }
// generate code to handle read of non-existent property // generate code to handle read of non-existent property
@ -240,7 +237,7 @@ public class JSAstTranslator extends AstTranslator {
} }
context.cfg().addInstruction(put); context.cfg().addInstruction(put);
} else { } else {
context.cfg().addInstruction(((JSInstructionFactory) insts).PropertyWrite(receiver, getValue(elt), rval)); context.cfg().addInstruction(((JSInstructionFactory) insts).PropertyWrite(receiver, context.getValue(elt), rval));
} }
} }
@ -328,26 +325,26 @@ public class JSAstTranslator extends AstTranslator {
} else { } else {
context.cfg().addInstruction(((JSInstructionFactory) insts).IsDefinedInstruction(result, ref, getValue(f))); context.cfg().addInstruction(((JSInstructionFactory) insts).IsDefinedInstruction(result, ref, context.getValue(f)));
} }
} }
protected boolean visitInstanceOf(CAstNode n, Context c, CAstVisitor visitor) { protected boolean visitInstanceOf(CAstNode n, WalkContext c, CAstVisitor<WalkContext> visitor) {
WalkContext context = (WalkContext) c; WalkContext context = (WalkContext) c;
int result = context.currentScope().allocateTempValue(); int result = context.currentScope().allocateTempValue();
setValue(n, result); context.setValue(n, result);
return false; return false;
} }
protected void leaveInstanceOf(CAstNode n, Context c, CAstVisitor visitor) { protected void leaveInstanceOf(CAstNode n, WalkContext c, CAstVisitor<WalkContext> visitor) {
WalkContext context = (WalkContext) c; WalkContext context = (WalkContext) c;
int result = getValue(n); int result = context.getValue(n);
visit(n.getChild(0), context, visitor); visit(n.getChild(0), context, visitor);
int value = getValue(n.getChild(0)); int value = context.getValue(n.getChild(0));
visit(n.getChild(1), context, visitor); visit(n.getChild(1), context, visitor);
int type = getValue(n.getChild(1)); int type = context.getValue(n.getChild(1));
context.cfg().addInstruction(new JavaScriptInstanceOf(result, value, type)); context.cfg().addInstruction(new JavaScriptInstanceOf(result, value, type));
} }
@ -362,18 +359,18 @@ public class JSAstTranslator extends AstTranslator {
//context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(1, tempVal, "arguments")); //context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(1, tempVal, "arguments"));
} }
protected boolean doVisit(CAstNode n, Context cntxt, CAstVisitor visitor) { protected boolean doVisit(CAstNode n, WalkContext cntxt, CAstVisitor<WalkContext> visitor) {
WalkContext context = (WalkContext) cntxt; WalkContext context = (WalkContext) cntxt;
switch (n.getKind()) { switch (n.getKind()) {
case CAstNode.TYPE_OF: { case CAstNode.TYPE_OF: {
int result = context.currentScope().allocateTempValue(); int result = context.currentScope().allocateTempValue();
this.visit(n.getChild(0), context, this); this.visit(n.getChild(0), context, this);
int ref = getValue(n.getChild(0)); int ref = context.getValue(n.getChild(0));
context.cfg().addInstruction(((JSInstructionFactory) insts).TypeOfInstruction(result, ref)); context.cfg().addInstruction(((JSInstructionFactory) insts).TypeOfInstruction(result, ref));
setValue(n, result); context.setValue(n, result);
return true; return true;
} }
@ -381,7 +378,7 @@ public class JSAstTranslator extends AstTranslator {
case JavaScriptCAstNode.EXIT_WITH: { case JavaScriptCAstNode.EXIT_WITH: {
this.visit(n.getChild(0), context, this); this.visit(n.getChild(0), context, this);
int ref = getValue(n.getChild(0)); int ref = context.getValue(n.getChild(0));
context.cfg().addInstruction(((JSInstructionFactory) insts).WithRegion(ref, n.getKind() == JavaScriptCAstNode.ENTER_WITH)); context.cfg().addInstruction(((JSInstructionFactory) insts).WithRegion(ref, n.getKind() == JavaScriptCAstNode.ENTER_WITH));

View File

@ -0,0 +1,102 @@
package com.ibm.wala.cast.js.translator;
import com.ibm.wala.cast.ir.translator.ConstantFoldingRewriter;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.impl.CAstOperator;
public class JSConstantFoldingRewriter extends ConstantFoldingRewriter {
public JSConstantFoldingRewriter(CAst Ast) {
super(Ast);
}
@Override
protected Object eval(CAstOperator op, Object lhs, Object rhs) {
if (op == CAstOperator.OP_ADD) {
if (lhs instanceof String || rhs instanceof String) {
return "" + lhs + rhs;
} else if (lhs instanceof Number && rhs instanceof Number) {
return new Double(((Number)lhs).doubleValue() + ((Number)rhs).doubleValue());
}
} else if (op == CAstOperator.OP_BIT_AND) {
} else if (op == CAstOperator.OP_BIT_OR) {
} else if (op == CAstOperator.OP_BIT_XOR) {
} else if (op == CAstOperator.OP_BITNOT) {
} else if (op == CAstOperator.OP_CONCAT) {
if (lhs instanceof String || rhs instanceof String) {
return "" + lhs + rhs;
}
} else if (op == CAstOperator.OP_DIV) {
if (lhs instanceof Number && rhs instanceof Number) {
return new Double(((Number)lhs).doubleValue() / ((Number)rhs).doubleValue());
}
} else if (op == CAstOperator.OP_EQ) {
} else if (op == CAstOperator.OP_GE) {
if (lhs instanceof Number && rhs instanceof Number) {
return Boolean.valueOf(((Number)lhs).doubleValue() >= ((Number)rhs).doubleValue());
}
} else if (op == CAstOperator.OP_GT) {
if (lhs instanceof Number && rhs instanceof Number) {
return Boolean.valueOf(((Number)lhs).doubleValue() > ((Number)rhs).doubleValue());
}
} else if (op == CAstOperator.OP_LE) {
if (lhs instanceof Number && rhs instanceof Number) {
return Boolean.valueOf(((Number)lhs).doubleValue() <= ((Number)rhs).doubleValue());
}
} else if (op == CAstOperator.OP_LSH) {
} else if (op == CAstOperator.OP_LT) {
if (lhs instanceof Number && rhs instanceof Number) {
return Boolean.valueOf(((Number)lhs).doubleValue() < ((Number)rhs).doubleValue());
}
} else if (op == CAstOperator.OP_MOD) {
if (lhs instanceof Number && rhs instanceof Number) {
return new Double(((Number)lhs).doubleValue() % ((Number)rhs).doubleValue());
}
} else if (op == CAstOperator.OP_MUL) {
if (lhs instanceof Number && rhs instanceof Number) {
return new Double(((Number)lhs).doubleValue() * ((Number)rhs).doubleValue());
}
} else if (op == CAstOperator.OP_NE) {
} else if (op == CAstOperator.OP_NOT) {
} else if (op == CAstOperator.OP_REL_AND) {
} else if (op == CAstOperator.OP_REL_OR) {
} else if (op == CAstOperator.OP_REL_XOR) {
} else if (op == CAstOperator.OP_RSH) {
} else if (op == CAstOperator.OP_STRICT_EQ) {
} else if (op == CAstOperator.OP_STRICT_NE) {
} else if (op == CAstOperator.OP_SUB) {
if (lhs instanceof Number && rhs instanceof Number) {
return new Double(((Number)lhs).doubleValue() - ((Number)rhs).doubleValue());
}
} else if (op == CAstOperator.OP_URSH) {
}
// no constant value
return null;
}
}

View File

@ -0,0 +1,279 @@
package com.ibm.wala.cast.js.translator;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.impl.CAstControlFlowRecorder;
import com.ibm.wala.cast.tree.impl.CAstSourcePositionRecorder;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.debug.Assertions;
public interface JavaScriptTranslatorToCAst extends TranslatorToCAst {
interface WalkContext<C extends WalkContext<C, T>, T> extends TranslatorToCAst.WalkContext<C, T> {
String script();
T top();
/**
* Add a name declaration to this context. For variables or constants, n
* should be a {@link CAstNode#DECL_STMT}, and the initialization of the
* variable (if any) may occur in a separate assignment. For functions, n
* should be a {@link CAstNode#FUNCTION_STMT}, including the function body.
*/
void addNameDecl(CAstNode n);
Collection<CAstNode> getNameDecls();
CAstNode getCatchTarget();
CAstNode getBaseVarIfRelevant(T node);
boolean foundBase(T node);
void updateBase(T from, T to);
}
public static class RootContext<C extends WalkContext<C, T>, T> extends TranslatorToCAst.RootContext<C, T> implements WalkContext<C,T> {
public String script() { return null; }
public T top() {
Assertions.UNREACHABLE();
return null;
}
public void addNameDecl(CAstNode v) {
Assertions.UNREACHABLE();
}
public Collection<CAstNode> getNameDecls() {
Assertions.UNREACHABLE();
return null;
}
public CAstNode getCatchTarget() {
Assertions.UNREACHABLE();
return null;
}
public CAstNode getBaseVarIfRelevant(T node) { return null; }
public boolean foundBase(T node) { return false; }
public void updateBase(T from, T to) { }
}
class DelegatingContext<C extends WalkContext<C, T>, T> extends TranslatorToCAst.DelegatingContext<C, T> implements WalkContext<C,T> {
protected DelegatingContext(C parent) {
super(parent);
}
public String script() {
return parent.script();
}
public T top() {
return parent.top();
}
public void addNameDecl(CAstNode n) {
parent.addNameDecl(n);
}
public Collection<CAstNode> getNameDecls() {
return parent.getNameDecls();
}
public CAstNode getCatchTarget() {
return parent.getCatchTarget();
}
public CAstNode getBaseVarIfRelevant(T node) {
return parent.getBaseVarIfRelevant(node);
}
public boolean foundBase(T node) {
return parent.foundBase(node);
}
public void updateBase(T from, T to) {
parent.updateBase(from, to);
}
}
public static class FunctionContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> {
private final T topNode;
private final CAstSourcePositionRecorder pos = new CAstSourcePositionRecorder();
private final CAstControlFlowRecorder cfg = new CAstControlFlowRecorder(pos);
private final Map<CAstNode, Collection<CAstEntity>> scopedEntities = HashMapFactory.make();
private final Vector<CAstNode> initializers = new Vector<CAstNode>();
protected FunctionContext(C parent, T s) {
super(parent);
this.topNode = s;
}
@Override
public T top() { return topNode; }
@Override
public CAstNode getCatchTarget() { return CAstControlFlowMap.EXCEPTION_TO_EXIT; }
@Override
public void addScopedEntity(CAstNode construct, CAstEntity e) {
if (! scopedEntities.containsKey(construct)) {
scopedEntities.put(construct, new HashSet<CAstEntity>(1));
}
scopedEntities.get(construct).add(e);
}
@Override
public Map<CAstNode, Collection<CAstEntity>> getScopedEntities() {
return scopedEntities;
}
@Override
public void addNameDecl(CAstNode v) { initializers.add(v); }
@Override
public Collection<CAstNode> getNameDecls() { return initializers; }
@Override
public CAstControlFlowRecorder cfg() { return cfg; }
@Override
public CAstSourcePositionRecorder pos() { return pos; }
}
public static class ScriptContext<C extends WalkContext<C, T>, T> extends FunctionContext<C,T> {
private final String script;
ScriptContext(C parent, T s, String script) {
super(parent, s);
this.script = script;
}
public String script() { return script; }
}
public static class TryCatchContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> {
private final CAstNode catchNode;
protected TryCatchContext(C parent, CAstNode catchNode) {
super(parent);
this.catchNode = catchNode;
}
public CAstNode getCatchTarget() { return catchNode; }
}
class BreakContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> {
private final T breakTarget;
protected final String label;
protected BreakContext(C parent, T breakTarget, String label) {
super(parent);
this.breakTarget = breakTarget;
this.label = label;
}
@Override
public T getBreakFor(String l) {
return ((l == null)? label==null: label.equals(l))? breakTarget: super.getBreakFor(l);
}
}
public class LoopContext<C extends WalkContext<C, T>, T> extends BreakContext<C,T> {
private final T continueTo;
protected LoopContext(C parent, T breakTo, T continueTo, String label) {
super(parent, breakTo, label);
this.continueTo = continueTo;
}
@Override
public T getContinueFor(String l) {
return ((l == null)? label==null: label.equals(l))? continueTo: super.getContinueFor(l);
}
}
/**
* Used to determine the value to be passed as the 'this' argument for a
* function call. This is needed since in JavaScript, you can write a call
* e(...) where e is some arbitrary expression, and in the case where e is a
* property access like e'.f, we must discover that the value of expression e'
* is passed as the 'this' parameter.
*
* The general strategy is to store the value of the expression passed as the
* 'this' parameter in baseVar, and then to use baseVar as the actual argument
* sub-node for the CAst call node
*/
public class BaseCollectingContext<C extends WalkContext<C, T>, T> extends DelegatingContext<C,T> {
/**
* node for which we actually care about what the base pointer is. this
* helps to handle cases like x.y.f(), where we would like to store x.y in
* baseVar, but not x when we recurse.
*/
private final Set<T> baseFor = new HashSet<T>();
/**
* the variable to be used to store the value of the expression passed as
* the 'this' parameter
*/
private final CAstNode baseVar;
/**
* have we discovered a value to be passed as the 'this' parameter?
*/
private boolean foundBase = false;
protected BaseCollectingContext(C parent, T initialBaseFor, CAstNode baseVar) {
super(parent);
baseFor.add( initialBaseFor );
this.baseVar = baseVar;
}
/**
* if node is one that we care about, return baseVar, and as a side effect
* set foundBase to true. Otherwise, return <code>null</code>.
*/
@Override
public CAstNode getBaseVarIfRelevant(T node) {
if (baseFor.contains( node )) {
foundBase = true;
return baseVar;
} else {
return null;
}
}
@Override
public boolean foundBase(T node) {
return foundBase;
}
/**
* if we currently care about the base pointer of from, switch to searching
* for the base pointer of to. Used for cases like comma expressions: if we
* have (x,y.f)(), we want to assign y to baseVar
*/
@Override
public void updateBase(T from, T to) {
if (baseFor.contains(from)) baseFor.add(to);
}
}
}

View File

@ -4,6 +4,7 @@ import java.util.Map;
import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol; import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol;
import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstNode; import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.impl.CAstOperator; import com.ibm.wala.cast.tree.impl.CAstOperator;
import com.ibm.wala.cast.tree.impl.CAstRewriter; import com.ibm.wala.cast.tree.impl.CAstRewriter;
@ -207,15 +208,15 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
return result; return result;
} }
protected CAstNode copyNodes(CAstNode root, RewriteContext context, Map<Pair<CAstNode, ExpanderKey>, CAstNode> nodeMap) { protected CAstNode copyNodes(CAstNode root, final CAstControlFlowMap cfg, RewriteContext context, Map<Pair<CAstNode, ExpanderKey>, CAstNode> nodeMap) {
int kind = root.getKind(); int kind = root.getKind();
if (kind == CAstNode.OBJECT_REF && context.inRead()) { if (kind == CAstNode.OBJECT_REF && context.inRead()) {
// if we see a property access (OBJECT_REF) in a read context, transform // if we see a property access (OBJECT_REF) in a read context, transform
// to a loop traversing the prototype chain // to a loop traversing the prototype chain
CAstNode readLoop; CAstNode readLoop;
CAstNode receiver = copyNodes(root.getChild(0), READ, nodeMap); CAstNode receiver = copyNodes(root.getChild(0), cfg, READ, nodeMap);
CAstNode element = copyNodes(root.getChild(1), READ, nodeMap); CAstNode element = copyNodes(root.getChild(1), cfg, READ, nodeMap);
if (element.getKind() == CAstNode.CONSTANT && element.getValue() instanceof String) { if (element.getKind() == CAstNode.CONSTANT && element.getValue() instanceof String) {
readLoop = makeConstRead(root, receiver, element, context, nodeMap); readLoop = makeConstRead(root, receiver, element, context, nodeMap);
} else { } else {
@ -227,9 +228,9 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
// handle cases like x.f++, represented as ASSIGN_POST_OP(x.f,1,+) // handle cases like x.f++, represented as ASSIGN_POST_OP(x.f,1,+)
AssignPreOrPostOpContext ctxt = new AssignPreOrPostOpContext(); AssignPreOrPostOpContext ctxt = new AssignPreOrPostOpContext();
// generate loop for the first child (x.f for example), keeping the loop var and element var in ctxt // generate loop for the first child (x.f for example), keeping the loop var and element var in ctxt
CAstNode lval = copyNodes(root.getChild(0), ctxt, nodeMap); CAstNode lval = copyNodes(root.getChild(0), cfg, ctxt, nodeMap);
CAstNode rval = copyNodes(root.getChild(1), READ, nodeMap); CAstNode rval = copyNodes(root.getChild(1), cfg, READ, nodeMap);
CAstNode op = copyNodes(root.getChild(2), READ, nodeMap); CAstNode op = copyNodes(root.getChild(2), cfg, READ, nodeMap);
if (ctxt.receiverTemp != null) { // if we found a nested property access if (ctxt.receiverTemp != null) { // if we found a nested property access
String temp1 = TEMP_NAME + (readTempCounter++); String temp1 = TEMP_NAME + (readTempCounter++);
String temp2 = TEMP_NAME + (readTempCounter++); String temp2 = TEMP_NAME + (readTempCounter++);
@ -257,8 +258,8 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
} else if (kind == CAstNode.ASSIGN) { } else if (kind == CAstNode.ASSIGN) {
// use ASSIGN context for LHS so we don't translate property accesses there // use ASSIGN context for LHS so we don't translate property accesses there
CAstNode copy = Ast.makeNode(CAstNode.ASSIGN, copyNodes(root.getChild(0), ASSIGN, nodeMap), CAstNode copy = Ast.makeNode(CAstNode.ASSIGN, copyNodes(root.getChild(0), cfg, ASSIGN, nodeMap),
copyNodes(root.getChild(1), READ, nodeMap)); copyNodes(root.getChild(1), cfg, READ, nodeMap));
nodeMap.put(Pair.make(root, context.key()), copy); nodeMap.put(Pair.make(root, context.key()), copy);
return copy; return copy;
@ -266,9 +267,9 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
CAstNode children[] = new CAstNode[root.getChildCount()]; CAstNode children[] = new CAstNode[root.getChildCount()];
int last = (children.length - 1); int last = (children.length - 1);
for (int i = 0; i < last; i++) { for (int i = 0; i < last; i++) {
children[i] = copyNodes(root.getChild(i), READ, nodeMap); children[i] = copyNodes(root.getChild(i), cfg, READ, nodeMap);
} }
children[last] = copyNodes(root.getChild(last), context, nodeMap); children[last] = copyNodes(root.getChild(last), cfg, context, nodeMap);
CAstNode copy = Ast.makeNode(CAstNode.BLOCK_EXPR, children); CAstNode copy = Ast.makeNode(CAstNode.BLOCK_EXPR, children);
nodeMap.put(Pair.make(root, context.key()), copy); nodeMap.put(Pair.make(root, context.key()), copy);
@ -286,7 +287,12 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
} else { } else {
CAstNode children[] = new CAstNode[root.getChildCount()]; CAstNode children[] = new CAstNode[root.getChildCount()];
for (int i = 0; i < children.length; i++) { for (int i = 0; i < children.length; i++) {
children[i] = copyNodes(root.getChild(i), READ, nodeMap); children[i] = copyNodes(root.getChild(i), cfg, READ, nodeMap);
}
for(Object label: cfg.getTargetLabels(root)) {
if (label instanceof CAstNode) {
copyNodes((CAstNode)label, cfg, READ, nodeMap);
}
} }
CAstNode copy = Ast.makeNode(kind, children); CAstNode copy = Ast.makeNode(kind, children);
nodeMap.put(Pair.make(root, context.key()), copy); nodeMap.put(Pair.make(root, context.key()), copy);

View File

@ -1,35 +0,0 @@
/******************************************************************************
* 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.util.Iterator;
import java.util.List;
import com.ibm.wala.classLoader.ModuleEntry;
import com.ibm.wala.classLoader.SourceFileModule;
public abstract class TranslatorBase {
public abstract void translate(ModuleEntry M, String N) throws IOException;
public void translate(List modules) throws IOException {
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

@ -277,11 +277,8 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
protected static class AstConstraintVisitor extends ConstraintVisitor implements AstInstructionVisitor { protected static class AstConstraintVisitor extends ConstraintVisitor implements AstInstructionVisitor {
private final CallGraph cg; public AstConstraintVisitor(AstSSAPropagationCallGraphBuilder builder, CGNode node) {
public AstConstraintVisitor(AstSSAPropagationCallGraphBuilder builder, CGNode node) {
super(builder, node); super(builder, node);
this.cg = builder.callGraph;
} }
protected AstSSAPropagationCallGraphBuilder getBuilder() { protected AstSSAPropagationCallGraphBuilder getBuilder() {

View File

@ -61,7 +61,7 @@ public abstract class ScriptEntryPoints implements Iterable<Entrypoint> {
} }
int functionVn = getMethod().isStatic()? -1: makeArgument(m, 0); int functionVn = getMethod().isStatic()? -1: makeArgument(m, 0);
int paramVns[] = new int[Math.max(0, getNumberOfParameters() - 1)]; int paramVns[] = new int[Math.min(0, getNumberOfParameters() - 1)];
for (int j = 0; j < paramVns.length; j++) { for (int j = 0; j < paramVns.length; j++) {
paramVns[j] = makeArgument(m, j + 1); paramVns[j] = makeArgument(m, j + 1);
} }

View File

@ -17,7 +17,6 @@ import java.net.URL;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.loader.SingleClassLoaderFactory; import com.ibm.wala.cast.loader.SingleClassLoaderFactory;
import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.classLoader.Language; import com.ibm.wala.classLoader.Language;
@ -30,6 +29,7 @@ import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey; import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.IRFactory;
import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.debug.Assertions;
public class Util { public class Util {
@ -37,7 +37,7 @@ public class Util {
/** /**
* flag to prevent dumping of verbose call graph / pointer analysis output * flag to prevent dumping of verbose call graph / pointer analysis output
*/ */
private static final boolean AVOID_DUMP = true; public static boolean AVOID_DUMP = true;
public static SourceFileModule makeSourceModule(URL script, String dir, String name) { public static SourceFileModule makeSourceModule(URL script, String dir, String name) {
// DO NOT use File.separator here, since this name is matched against // DO NOT use File.separator here, since this name is matched against
@ -73,8 +73,8 @@ public class Util {
return result; return result;
} }
public static AnalysisCache makeCache() { public static AnalysisCache makeCache(IRFactory<IMethod> factory) {
return new AnalysisCache(AstIRFactory.makeDefaultFactory()); return new AnalysisCache(factory);
} }
public static String getShortName(CGNode nd) { public static String getShortName(CGNode nd) {

View File

@ -36,6 +36,34 @@ public class AstIRFactory implements IRFactory {
return ((AstMethod) method).getControlFlowGraph(); return ((AstMethod) method).getControlFlowGraph();
} }
public static class AstDefaultIRFactory extends DefaultIRFactory {
private final AstIRFactory astFactory;
public AstDefaultIRFactory() {
this(new AstIRFactory());
}
public AstDefaultIRFactory(AstIRFactory astFactory) {
this.astFactory = astFactory;
}
public IR makeIR(IMethod method, Context context, SSAOptions options) {
if (method instanceof AstMethod) {
return astFactory.makeIR(method, context, options);
} else {
return super.makeIR(method, context, options);
}
}
public ControlFlowGraph makeCFG(IMethod method, Context context) {
if (method instanceof AstMethod) {
return astFactory.makeCFG(method, context);
} else {
return super.makeCFG(method, context);
}
}
}
public class AstIR extends IR { public class AstIR extends IR {
private final LexicalInformation lexicalInfo; private final LexicalInformation lexicalInfo;
@ -101,7 +129,6 @@ public class AstIRFactory implements IRFactory {
public IR makeIR(final IMethod method, final Context context, final SSAOptions options) { public IR makeIR(final IMethod method, final Context context, final SSAOptions options) {
assert method instanceof AstMethod : method.toString(); assert method instanceof AstMethod : method.toString();
// Pair<IMethod,Context> key = Pair.make(method, context);
AbstractCFG oldCfg = ((AstMethod) method).cfg(); AbstractCFG oldCfg = ((AstMethod) method).cfg();
SSAInstruction[] oldInstrs = (SSAInstruction[]) oldCfg.getInstructions(); SSAInstruction[] oldInstrs = (SSAInstruction[]) oldCfg.getInstructions();
@ -115,25 +142,7 @@ public class AstIRFactory implements IRFactory {
} }
public static IRFactory<IMethod> makeDefaultFactory() { public static IRFactory<IMethod> makeDefaultFactory() {
return new DefaultIRFactory() { return new AstDefaultIRFactory();
private final AstIRFactory astFactory = new AstIRFactory();
public IR makeIR(IMethod method, Context context, SSAOptions options) {
if (method instanceof AstMethod) {
return astFactory.makeIR(method, context, options);
} else {
return super.makeIR(method, context, options);
}
}
public ControlFlowGraph makeCFG(IMethod method, Context context) {
if (method instanceof AstMethod) {
return astFactory.makeCFG(method, context);
} else {
return super.makeCFG(method, context);
}
}
};
} }
public boolean contextIsIrrelevant(IMethod method) { public boolean contextIsIrrelevant(IMethod method) {

View File

@ -0,0 +1,76 @@
package com.ibm.wala.cast.ir.translator;
import java.util.Map;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.impl.CAstBasicRewriter;
import com.ibm.wala.cast.tree.impl.CAstOperator;
import com.ibm.wala.util.collections.Pair;
public abstract class ConstantFoldingRewriter extends CAstBasicRewriter {
protected ConstantFoldingRewriter(CAst Ast) {
super(Ast, true);
}
protected abstract Object eval(CAstOperator op, Object lhs, Object rhs);
@Override
protected CAstNode copyNodes(CAstNode root,
CAstControlFlowMap cfg,
NonCopyingContext context,
Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap)
{
CAstNode result;
if (root.getKind() == CAstNode.BINARY_EXPR) {
CAstNode left = copyNodes(root.getChild(1), cfg, context, nodeMap);
CAstNode right = copyNodes(root.getChild(2), cfg, context, nodeMap);
Object v;
if (left.getKind() == CAstNode.CONSTANT && right.getKind() == CAstNode.CONSTANT && (v = eval((CAstOperator) root.getChild(0), left.getValue(), right.getValue())) != null) {
result = Ast.makeConstant(v);
} else {
result = Ast.makeNode(CAstNode.BINARY_EXPR, root.getChild(0), left, right);
}
} else if (root.getKind() == CAstNode.IF_EXPR || root.getKind() == CAstNode.IF_STMT) {
CAstNode expr = copyNodes(root.getChild(0), cfg, context, nodeMap);
if (expr.getKind() == CAstNode.CONSTANT && expr.getValue() == Boolean.TRUE) {
result = copyNodes(root.getChild(1), cfg, context, nodeMap);
} else if (expr.getKind() == CAstNode.CONSTANT && root.getChildCount() > 2 && expr.getValue() == Boolean.FALSE) {
result = copyNodes(root.getChild(2), cfg, context, nodeMap);
} else {
CAstNode then = copyNodes(root.getChild(1), cfg, context, nodeMap);
if (root.getChildCount() == 3) {
result = Ast.makeNode(root.getKind(), expr, then, copyNodes(root.getChild(2), cfg, context, nodeMap));
} else {
result = Ast.makeNode(root.getKind(), expr, then);
}
}
} else if (root.getKind() == CAstNode.CONSTANT) {
result = Ast.makeConstant(root.getValue());
} else if (root.getKind() == CAstNode.OPERATOR) {
result = root;
} else {
CAstNode children[] = new CAstNode[root.getChildCount()];
for (int i = 0; i < children.length; i++) {
children[i] = copyNodes(root.getChild(i), cfg, context, nodeMap);
}
for(Object label: cfg.getTargetLabels(root)) {
if (label instanceof CAstNode) {
copyNodes((CAstNode)label, cfg, context, nodeMap);
}
}
CAstNode copy = Ast.makeNode(root.getKind(), children);
result = copy;
}
nodeMap.put(Pair.make(root, context.key()), result);
return result;
}
}

View File

@ -1,15 +1,183 @@
package com.ibm.wala.cast.ir.translator; package com.ibm.wala.cast.ir.translator;
import java.io.IOException; import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.impl.CAstCloner;
import com.ibm.wala.cast.tree.impl.CAstControlFlowRecorder;
import com.ibm.wala.cast.tree.impl.CAstNodeTypeMapRecorder;
import com.ibm.wala.cast.tree.impl.CAstRewriter;
import com.ibm.wala.cast.tree.impl.CAstRewriter.CopyKey; import com.ibm.wala.cast.tree.impl.CAstRewriter.CopyKey;
import com.ibm.wala.cast.tree.impl.CAstRewriter.RewriteContext; import com.ibm.wala.cast.tree.impl.CAstRewriter.RewriteContext;
import com.ibm.wala.cast.tree.impl.CAstRewriterFactory; import com.ibm.wala.cast.tree.impl.CAstRewriterFactory;
import com.ibm.wala.cast.tree.impl.CAstSourcePositionRecorder;
public interface TranslatorToCAst { public interface TranslatorToCAst {
public <C extends RewriteContext<K>, K extends CopyKey<K>> void addRewriter(CAstRewriterFactory<C, K> factory, boolean prepend); public <C extends RewriteContext<K>, K extends CopyKey<K>> void addRewriter(CAstRewriterFactory<C, K> factory, boolean prepend);
public CAstEntity translateToCAst() throws IOException; public CAstEntity translateToCAst() throws IOException;
public interface WalkContext<C extends WalkContext<C, T>, T> {
/**
* get a mapping from CAstNodes to the scoped entities (e.g. functions or
* local classes) introduced by those nodes. Also maps <code>null</code> to
* those entities not corresponding to any node (e.g nested classes)
*/
Map<CAstNode, Collection<CAstEntity>> getScopedEntities();
/**
* associate a child entity with a given CAstNode, e.g. for a function declaration
*/
void addScopedEntity(CAstNode newNode, CAstEntity visit);
/**
* for recording control-flow relationships among the CAst nodes
*/
CAstControlFlowRecorder cfg();
/**
* for recording source positions
*/
CAstSourcePositionRecorder pos();
/**
* for recording types of nodes
*/
CAstNodeTypeMapRecorder getNodeTypeMap();
/**
* for a 'continue' style goto, return the control flow target
*/
T getContinueFor(String label);
/**
* for a 'break' style goto, return the control flow target
*/
T getBreakFor(String label);
}
public class RootContext <C extends WalkContext<C, T>, T> implements WalkContext<C, T> {
public Map<CAstNode, Collection<CAstEntity>> getScopedEntities() {
assert false;
return Collections.emptyMap();
}
public void addScopedEntity(CAstNode newNode, CAstEntity visit) {
assert false;
}
public CAstControlFlowRecorder cfg() {
assert false;
return null;
}
public CAstSourcePositionRecorder pos() {
assert false;
return null;
}
public CAstNodeTypeMapRecorder getNodeTypeMap() {
assert false;
return null;
}
public T getContinueFor(String label) {
assert false;
return null;
}
public T getBreakFor(String label) {
assert false;
return null;
}
}
public class DelegatingContext<C extends WalkContext<C, T>, T> implements WalkContext<C, T> {
protected final C parent;
protected DelegatingContext(C parent) {
this.parent = parent;
}
public CAstControlFlowRecorder cfg() {
return parent.cfg();
}
public CAstSourcePositionRecorder pos() {
return parent.pos();
}
public CAstNodeTypeMapRecorder getNodeTypeMap() {
return parent.getNodeTypeMap();
}
public T getContinueFor(String label) {
return parent.getContinueFor(label);
}
public T getBreakFor(String label) {
return parent.getBreakFor(label);
}
public void addScopedEntity(CAstNode newNode, CAstEntity visit) {
parent.addScopedEntity(newNode, visit);
}
public Map<CAstNode, Collection<CAstEntity>> getScopedEntities() {
return parent.getScopedEntities();
}
}
public static class DoLoopTranslator {
private final boolean replicateForDoLoops;
private final CAst Ast;
public DoLoopTranslator(boolean replicateForDoLoops, CAst ast) {
this.replicateForDoLoops = replicateForDoLoops;
Ast = ast;
}
public CAstNode translateDoLoop(CAstNode loopTest, CAstNode loopBody, CAstNode continueNode, CAstNode breakNode, WalkContext<?,?> wc) {
if (replicateForDoLoops) {
loopBody = Ast.makeNode(CAstNode.BLOCK_STMT, loopBody, continueNode);
CAstRewriter.Rewrite x = (new CAstCloner(Ast, false)).copy(loopBody, wc.cfg(), wc.pos(), wc.getNodeTypeMap(), null);
CAstNode otherBody = x.newRoot();
wc.cfg().addAll(x.newCfg());
wc.pos().addAll(x.newPos());
wc.getNodeTypeMap().addAll(x.newTypes());
return Ast.makeNode(CAstNode.BLOCK_STMT,
loopBody,
Ast.makeNode(CAstNode.LOOP, loopTest, otherBody),
breakNode);
} else {
CAstNode header = Ast.makeNode(CAstNode.EMPTY);
CAstNode loopGoto = Ast.makeNode(CAstNode.IFGOTO, loopTest);
wc.cfg().map(header, header);
wc.cfg().map(loopGoto, loopGoto);
wc.cfg().add(loopGoto, header, Boolean.TRUE);
return Ast.makeNode(CAstNode.BLOCK_STMT,
header,
Ast.makeNode(CAstNode.BLOCK_STMT, loopBody, continueNode),
loopGoto,
breakNode);
}
}
};
} }

View File

@ -10,7 +10,6 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.loader; package com.ibm.wala.cast.loader;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.Collection; import java.util.Collection;
@ -30,6 +29,7 @@ import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.strings.Atom; import com.ibm.wala.util.strings.Atom;
abstract public class AstFunctionClass implements IClass, ClassConstants { abstract public class AstFunctionClass implements IClass, ClassConstants {
private final IClassLoader loader; private final IClassLoader loader;
protected IMethod functionBody; protected IMethod functionBody;

View File

@ -12,7 +12,9 @@ package com.ibm.wala.cast.loader;
import java.util.Collection; import java.util.Collection;
import com.ibm.wala.cast.ir.translator.AstTranslator;
import com.ibm.wala.cast.ir.translator.AstTranslator.AstLexicalInformation; import com.ibm.wala.cast.ir.translator.AstTranslator.AstLexicalInformation;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstQualifier; import com.ibm.wala.cast.tree.CAstQualifier;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cfg.AbstractCFG; import com.ibm.wala.cfg.AbstractCFG;
@ -30,6 +32,11 @@ import com.ibm.wala.util.strings.Atom;
public abstract class AstMethod implements IMethod { public abstract class AstMethod implements IMethod {
public interface Retranslatable {
void retranslate(AstTranslator xlator);
CAstEntity getEntity();
}
public interface DebuggingInformation { public interface DebuggingInformation {
Position getCodeBodyPosition(); Position getCodeBodyPosition();

View File

@ -111,6 +111,8 @@ public interface CAstNode {
public static final int MONITOR_ENTER = 23; public static final int MONITOR_ENTER = 23;
public static final int MONITOR_EXIT = 24; public static final int MONITOR_EXIT = 24;
public static final int ECHO = 25; public static final int ECHO = 25;
public static final int YIELD_STMT = 26;
public static final int FORIN_LOOP = 27;
// expression kinds // expression kinds
public static final int FUNCTION_EXPR = 100; public static final int FUNCTION_EXPR = 100;

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstNode; import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.debug.Assertions;
@ -58,6 +59,6 @@ public abstract class CAstBasicRewriter
super(Ast, recursive, new NonCopyingContext()); super(Ast, recursive, new NonCopyingContext());
} }
protected abstract CAstNode copyNodes(CAstNode root, NonCopyingContext context, Map<Pair<CAstNode,NoKey>, CAstNode> nodeMap); protected abstract CAstNode copyNodes(CAstNode root, final CAstControlFlowMap cfg, NonCopyingContext context, Map<Pair<CAstNode,NoKey>, CAstNode> nodeMap);
} }

View File

@ -31,14 +31,14 @@ public class CAstCloner extends CAstBasicRewriter {
this(Ast, false); this(Ast, false);
} }
protected CAstNode copyNodes(CAstNode root, NonCopyingContext c, Map<Pair<CAstNode,NoKey>, CAstNode> nodeMap) { protected CAstNode copyNodes(CAstNode root, final CAstControlFlowMap cfg, NonCopyingContext c, Map<Pair<CAstNode,NoKey>, CAstNode> nodeMap) {
return copyNodesHackForEclipse(root, c, nodeMap); return copyNodesHackForEclipse(root, cfg, c, nodeMap);
} }
/** /**
* what is the hack here? --MS * what is the hack here? --MS
*/ */
protected CAstNode copyNodesHackForEclipse(CAstNode root, NonCopyingContext c, Map<Pair<CAstNode,NoKey>, CAstNode> nodeMap) { protected CAstNode copyNodesHackForEclipse(CAstNode root, final CAstControlFlowMap cfg, NonCopyingContext c, Map<Pair<CAstNode,NoKey>, CAstNode> nodeMap) {
if (root instanceof CAstOperator) { if (root instanceof CAstOperator) {
nodeMap.put(Pair.make(root, c.key()), root); nodeMap.put(Pair.make(root, c.key()), root);
return root; return root;
@ -51,7 +51,7 @@ public class CAstCloner extends CAstBasicRewriter {
CAstNode newChildren[] = new CAstNode[root.getChildCount()]; CAstNode newChildren[] = new CAstNode[root.getChildCount()];
for (int i = 0; i < root.getChildCount(); i++) { for (int i = 0; i < root.getChildCount(); i++) {
newChildren[i] = copyNodes(root.getChild(i), c, nodeMap); newChildren[i] = copyNodes(root.getChild(i), cfg, c, nodeMap);
} }
CAstNode copy = Ast.makeNode(root.getKind(), newChildren); CAstNode copy = Ast.makeNode(root.getKind(), newChildren);

View File

@ -140,6 +140,14 @@ public class CAstControlFlowRecorder implements CAstControlFlowMap {
assert from != null; assert from != null;
assert to != null; assert to != null;
if (CAstToNode.containsKey(to)) {
to = CAstToNode.get(to);
}
if (CAstToNode.containsKey(from)) {
from = CAstToNode.get(from);
}
table.put(new Key(label, from), to); table.put(new Key(label, from), to);
Set<Object> ls = labelMap.get(from); Set<Object> ls = labelMap.get(from);
@ -170,8 +178,12 @@ public class CAstControlFlowRecorder implements CAstControlFlowMap {
public void addAll(CAstControlFlowMap other) { public void addAll(CAstControlFlowMap other) {
for (CAstNode n : other.getMappedNodes()) { for (CAstNode n : other.getMappedNodes()) {
if (! CAstToNode.containsKey(n)) {
map(n, n);
}
for (Object l : other.getTargetLabels(n)) { for (Object l : other.getTargetLabels(n)) {
add(n, l, other.getTarget(n, l)); CAstNode to = other.getTarget(n, l);
add(n, to, l);
} }
} }
} }

View File

@ -119,7 +119,7 @@ public abstract class CAstRewriter<C extends CAstRewriter.RewriteContext<K>, K e
* how (original node, copy key) pairs are mapped to nodes in the rewritten * how (original node, copy key) pairs are mapped to nodes in the rewritten
* tree. * tree.
*/ */
protected abstract CAstNode copyNodes(CAstNode root, C context, Map<Pair<CAstNode, K>, CAstNode> nodeMap); protected abstract CAstNode copyNodes(CAstNode root, final CAstControlFlowMap cfg, C context, Map<Pair<CAstNode, K>, CAstNode> nodeMap);
/** /**
* in {@link #copyFlow(Map, CAstControlFlowMap, CAstSourcePositionMap)}, if * in {@link #copyFlow(Map, CAstControlFlowMap, CAstSourcePositionMap)}, if
@ -170,9 +170,9 @@ public abstract class CAstRewriter<C extends CAstRewriter.RewriteContext<K>, K e
if (oldSources.contains(oldSource)) { if (oldSources.contains(oldSource)) {
Iterator<Object> LS = orig.getTargetLabels(oldSource).iterator(); Iterator<Object> LS = orig.getTargetLabels(oldSource).iterator();
if (orig.getTarget(oldSource, null) != null) { //if (orig.getTarget(oldSource, null) != null) {
LS = IteratorPlusOne.make(LS, null); // LS = IteratorPlusOne.make(LS, null);
} //}
while (LS.hasNext()) { while (LS.hasNext()) {
Object origLabel = LS.next(); Object origLabel = LS.next();
@ -238,7 +238,9 @@ public abstract class CAstRewriter<C extends CAstRewriter.RewriteContext<K>, K e
allNewTargetNodes.removeAll(newMap.getMappedNodes()); allNewTargetNodes.removeAll(newMap.getMappedNodes());
for (CAstNode newTarget : allNewTargetNodes) { for (CAstNode newTarget : allNewTargetNodes) {
newMap.map(newTarget, newTarget); if (newTarget != CAstControlFlowMap.EXCEPTION_TO_EXIT) {
newMap.map(newTarget, newTarget);
}
} }
@ -341,7 +343,7 @@ public abstract class CAstRewriter<C extends CAstRewriter.RewriteContext<K>, K e
public Rewrite rewrite(final CAstNode root, final CAstControlFlowMap cfg, final CAstSourcePositionMap pos, final CAstNodeTypeMap types, public Rewrite rewrite(final CAstNode root, final CAstControlFlowMap cfg, final CAstSourcePositionMap pos, final CAstNodeTypeMap types,
final Map<CAstNode, Collection<CAstEntity>> children) { final Map<CAstNode, Collection<CAstEntity>> children) {
final Map<Pair<CAstNode, K>, CAstNode> nodes = HashMapFactory.make(); final Map<Pair<CAstNode, K>, CAstNode> nodes = HashMapFactory.make();
final CAstNode newRoot = copyNodes(root, rootContext, nodes); final CAstNode newRoot = copyNodes(root, cfg, rootContext, nodes);
return new Rewrite() { return new Rewrite() {
private CAstControlFlowMap theCfg = null; private CAstControlFlowMap theCfg = null;

View File

@ -53,12 +53,13 @@ public class CAstPrinter {
case CAstNode.LABEL_STMT: return "LABEL_STMT"; case CAstNode.LABEL_STMT: return "LABEL_STMT";
case CAstNode.IFGOTO: return "IFGOTO"; case CAstNode.IFGOTO: return "IFGOTO";
case CAstNode.EMPTY: return "EMPTY"; case CAstNode.EMPTY: return "EMPTY";
case CAstNode.RETURN_WITHOUT_BRANCH: return "RET_WO_BRANCH"; case CAstNode.YIELD_STMT: return "YIELD";
case CAstNode.CATCH: return "CATCH"; case CAstNode.CATCH: return "CATCH";
case CAstNode.UNWIND: return "UNWIND"; case CAstNode.UNWIND: return "UNWIND";
case CAstNode.MONITOR_ENTER: return "MONITOR_ENTER"; case CAstNode.MONITOR_ENTER: return "MONITOR_ENTER";
case CAstNode.MONITOR_EXIT: return "MONITOR_EXIT"; case CAstNode.MONITOR_EXIT: return "MONITOR_EXIT";
case CAstNode.ECHO: return "ECHO"; case CAstNode.ECHO: return "ECHO";
case CAstNode.FORIN_LOOP: return "FOR..IN";
// expression kinds // expression kinds
case CAstNode.FUNCTION_EXPR: return "FUNCTION_EXPR"; case CAstNode.FUNCTION_EXPR: return "FUNCTION_EXPR";
@ -85,8 +86,6 @@ public class CAstPrinter {
case CAstNode.ARRAY_REF: return "ARRAY_REF"; case CAstNode.ARRAY_REF: return "ARRAY_REF";
case CAstNode.ARRAY_LENGTH: return "ARRAY_LENGTH"; case CAstNode.ARRAY_LENGTH: return "ARRAY_LENGTH";
case CAstNode.TYPE_OF: return "TYPE_OF"; case CAstNode.TYPE_OF: return "TYPE_OF";
case CAstNode.EACH_ELEMENT_HAS_NEXT: return "EACH_ELEMENT_HAS_NEXT";
case CAstNode.EACH_ELEMENT_GET: return "EACH_ELEMENT_GET";
case CAstNode.LIST_EXPR: return "LIST_EXPR"; case CAstNode.LIST_EXPR: return "LIST_EXPR";
case CAstNode.EMPTY_LIST_EXPR: return "EMPTY_LIST_EXPR"; case CAstNode.EMPTY_LIST_EXPR: return "EMPTY_LIST_EXPR";
case CAstNode.IS_DEFINED_EXPR: return "IS_DEFINED_EXPR"; case CAstNode.IS_DEFINED_EXPR: return "IS_DEFINED_EXPR";

View File

@ -16,4 +16,20 @@ package com.ibm.wala.ipa.callgraph;
*/ */
public interface ContextItem { public interface ContextItem {
public class Value<T> implements ContextItem {
private final T v;
public Value(T v) {
this.v = v;
}
public T getValue() {
return v;
}
public static <T> Value make(T v) {
return new Value<T>(v);
}
}
} }