From 5a3470a67442a9d05953efa01087c8fe15654b3f Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Tue, 24 Jan 2012 16:28:57 +0000 Subject: [PATCH 001/145] remove debug print git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4424 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../callgraph/propagation/SSAPropagationCallGraphBuilder.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java index 12d6b19e7..117f4daa3 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java @@ -1781,9 +1781,6 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap } } }; - if (site.getDeclaredTarget().getName().toString().contains("numericToTextFormat")) { - System.err.println(site + "\n" + params + "\n" + targets); - } iterateCrossProduct(caller, site, params, f); return targets; } From 4c6d062dbb385a05887c5a9e37b30b3b285d77b6 Mon Sep 17 00:00:00 2001 From: dolby-oss Date: Fri, 27 Jan 2012 20:15:33 +0000 Subject: [PATCH 002/145] 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 --- .../jdt/JDTJava2CAstTranslator.java | 152 +- .../jdt/JDTSourceModuleTranslator.java | 14 +- .../cast/java/translator/polyglot/IRGoal.java | 12 +- .../polyglot/PolyglotJava2CAstTranslator.java | 185 +- .../ast/SynchronizedBlockDuplicator.java | 8 +- .../java/translator/Java2IRTranslator.java | 22 +- .../translator/JavaCAst2IRTranslator.java | 45 +- .../java/translator/TranslatorToCAst.java | 19 - .../js/test/TestArgumentSensitivityRhino.java | 15 + .../TestCorrelatedPairExtractionRhino.java | 7 +- .../js/test/TestForInBodyExtractionRhino.java | 7 +- .../cast/js/test/TestJQueryExamplesRhino.java | 18 + .../ibm/wala/cast/js/vis/JsViewerDriver.java | 5 +- .../js/translator/CAstRhinoTranslator.java | 10 +- .../CAstRhinoTranslatorFactory.java | 2 +- .../js/translator/RhinoToAstTranslator.java | 2203 +++++++++++++++++ .../cast/js/translator/TypedNodeVisitor.java | 303 +++ .../examples-src/tests/args.js | 24 + .../examples-src/tests/extjs_switch.js | 9 +- .../cast/js/test/TestArgumentSensitivity.java | 53 + .../wala/cast/js/test/TestJQueryExamples.java | 32 + .../js/test/TestSimpleCallGraphShape.java | 12 + .../js/test/TestSimplePageCallGraphShape.java | 5 +- .../com/ibm/wala/cast/js/test/Util.java | 45 +- .../ipa/callgraph/ArgumentSpecialization.java | 353 +++ .../js/ipa/callgraph/GlobalObjectKey.java | 1 - .../JSSSAPropagationCallGraphBuilder.java | 8 +- ...avaScriptFunctionApplyContextSelector.java | 1 - ...vaScriptFunctionDotCallTargetSelector.java | 1 - .../ObjectSensitivityContextSelector.java | 3 - .../ibm/wala/cast/js/ipa/callgraph/Util.java | 9 +- .../correlations/CorrelationFinder.java | 1 - .../extraction/ClosureExtractor.java | 65 +- .../CorrelatedPairExtractorFactory.java | 1 - .../extraction/ExtractedFunction.java | 15 - .../correlations/extraction/NodePos.java | 1 - .../wala/cast/js/loader/JavaScriptLoader.java | 57 +- .../cast/js/translator/JSAstTranslator.java | 33 +- .../translator/JSConstantFoldingRewriter.java | 102 + .../JavaScriptTranslatorToCAst.java | 279 +++ .../js/translator/PropertyReadExpander.java | 28 +- .../cast/js/translator/TranslatorBase.java | 35 - .../AstSSAPropagationCallGraphBuilder.java | 5 +- .../cast/ipa/callgraph/ScriptEntryPoints.java | 2 +- .../com/ibm/wala/cast/ipa/callgraph/Util.java | 8 +- .../ibm/wala/cast/ir/ssa/AstIRFactory.java | 49 +- .../cast/ir/translator/AstTranslator.java | 917 +++---- .../translator/ConstantFoldingRewriter.java | 76 + .../cast/ir/translator/TranslatorToCAst.java | 168 ++ .../wala/cast/loader/AstFunctionClass.java | 2 +- .../com/ibm/wala/cast/loader/AstMethod.java | 7 + .../java/com/ibm/wala/cast/tree/CAstNode.java | 2 + .../cast/tree/impl/CAstBasicRewriter.java | 3 +- .../ibm/wala/cast/tree/impl/CAstCloner.java | 8 +- .../tree/impl/CAstControlFlowRecorder.java | 14 +- .../ibm/wala/cast/tree/impl/CAstRewriter.java | 14 +- .../ibm/wala/cast/tree/visit/CAstVisitor.java | 383 +-- .../tree/visit/DelegatingCAstVisitor.java | 266 +- .../com/ibm/wala/cast/util/CAstPrinter.java | 5 +- .../ibm/wala/ipa/callgraph/ContextItem.java | 16 + 60 files changed, 4863 insertions(+), 1282 deletions(-) delete mode 100644 com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/TranslatorToCAst.java create mode 100644 com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestArgumentSensitivityRhino.java create mode 100644 com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestJQueryExamplesRhino.java create mode 100755 com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java create mode 100644 com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/TypedNodeVisitor.java create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/args.js create mode 100644 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestArgumentSensitivity.java create mode 100644 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestJQueryExamples.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ArgumentSpecialization.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JSConstantFoldingRewriter.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JavaScriptTranslatorToCAst.java delete mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/TranslatorBase.java create mode 100644 com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/ConstantFoldingRewriter.java diff --git a/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/translator/jdt/JDTJava2CAstTranslator.java b/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/translator/jdt/JDTJava2CAstTranslator.java index 901cac5d6..69f179ef8 100644 --- a/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/translator/jdt/JDTJava2CAstTranslator.java +++ b/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/translator/jdt/JDTJava2CAstTranslator.java @@ -128,10 +128,11 @@ import org.eclipse.jdt.core.dom.VariableDeclarationStatement; import org.eclipse.jdt.core.dom.WhileStatement; 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.Util; 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.CAstControlFlowMap; 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) @SuppressWarnings("unchecked") -public class JDTJava2CAstTranslator implements TranslatorToCAst { +public class JDTJava2CAstTranslator { protected final CAst fFactory = new CAstImpl(); // /////////////////////////////////////////// @@ -203,6 +204,8 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst { protected ITypeBinding OutOfMemoryError; + protected DoLoopTranslator doLoopTranslator; + private String fullPath; private CompilationUnit cu; @@ -211,20 +214,7 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst { // COMPILATION UNITS & TYPES // - public JDTJava2CAstTranslator(JavaSourceLoaderImpl sourceLoader) { - 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); - + public JDTJava2CAstTranslator(JavaSourceLoaderImpl sourceLoader, CompilationUnit astRoot, String fullPath, boolean replicateForDoLoops) { fDivByZeroExcType = FakeExceptionTypeBinding.arithmetic; fNullPointerExcType = FakeExceptionTypeBinding.nullPointer; fClassCastExcType = FakeExceptionTypeBinding.classCast; @@ -232,12 +222,27 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst { ExceptionInInitializerError = FakeExceptionTypeBinding.initException; 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"); assert fRuntimeExcType != null; + } + + public CAstEntity translateToCAst() { List declEntities = new ArrayList(); - for (Iterator iter = cu.types().iterator(); iter.hasNext();) { + for (Iterator iter = cu.types().iterator(); iter.hasNext();) { AbstractTypeDeclaration decl = (AbstractTypeDeclaration) iter.next(); // can be of type AnnotationTypeDeclaration, EnumDeclaration, TypeDeclaration declEntities.add(visit(decl, new RootContext())); @@ -2095,7 +2100,6 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst { // //////////////// 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) ASTNode stmt = n.getBody(); @@ -2108,10 +2112,12 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst { CAstNode result; 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); 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 { result = makeNode(context, fFactory, n, CAstNode.LABEL_STMT, fFactory.makeConstant(n.getLabel().getIdentifier()), visitNode(n .getBody(), context)); @@ -2163,7 +2169,10 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst { Statement body = n.getBody(); ASTNode breakTarget = makeBreakOrContinueTarget(n, "breakLabel" + n.getStartPosition()); + CAstNode breakNode = visitNode(breakTarget, context); + ASTNode continueTarget = makeBreakOrContinueTarget(n, "continueLabel" + n.getStartPosition()); + CAstNode continueNode = visitNode(continueTarget, context); String loopLabel = (String) context.getLabelMap().get(n); 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. */ 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))), - visitNode(breakTarget, context)); + context), makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, visitNode(body, lc), continueNode)), + breakNode); } private CAstNode getSwitchCaseConstant(SwitchCase n, WalkContext context) { @@ -2282,22 +2291,21 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst { } 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) - 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 loopTest = visitNode(n.getExpression(), context); - return makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, visitNode(header, context), makeNode(context, fFactory, n, - CAstNode.BLOCK_STMT, visitNode(n.getBody(), loopContext), continueNode), loopGoto, visitNode(breakTarget, context)); + WalkContext loopContext = new LoopContext(context, loopLabel, breakTarget, continueTarget); + 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 * mapping which each node registers */ - public static interface WalkContext { - // LEFTOUT: plenty of stuff - public CAstControlFlowRecorder cfg(); - - public void addScopedEntity(CAstNode newNode, CAstEntity visit); + public static interface WalkContext extends TranslatorToCAst.WalkContext { public Collection> getCatchTargets(ITypeBinding type); - public CAstSourcePositionRecorder pos(); - - public CAstNodeTypeMapRecorder getNodeTypeMap(); - public Map getLabelMap(); - public ASTNode getContinueFor(String label); - - public ASTNode getBreakFor(String label); - 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 * source pos. mapping per MethodContext, so loop contexts delegate it up. */ - public static class DelegatingContext implements WalkContext { - protected WalkContext parent; + public static class DelegatingContext extends TranslatorToCAst.DelegatingContext implements WalkContext { public DelegatingContext(WalkContext parent) { - this.parent = parent; - } - - public CAstControlFlowRecorder cfg() { - return parent.cfg(); - } - - public CAstSourcePositionRecorder pos() { - return parent.pos(); - } - - public CAstNodeTypeMapRecorder getNodeTypeMap() { - return parent.getNodeTypeMap(); + super(parent); } public Collection> getCatchTargets(ITypeBinding type) { return parent.getCatchTargets(type); } - public void addScopedEntity(CAstNode newNode, CAstEntity visit) { - parent.addScopedEntity(newNode, visit); - } - public Map getLabelMap() { return parent.getLabelMap(); } - public ASTNode getContinueFor(String label) { - return parent.getContinueFor(label); - } - - public ASTNode getBreakFor(String label) { - return parent.getBreakFor(label); - } - - public boolean needLValue() { + public boolean needLValue() { return parent.needLValue(); } } @@ -2961,27 +2932,8 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst { /* * Root context. Doesn't do anything. */ - public static class RootContext implements WalkContext { - public void addScopedEntity(CAstNode newNode, CAstEntity visit) { - 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> getCatchTargets(ITypeBinding type) { + public static class RootContext extends TranslatorToCAst.RootContext implements WalkContext { + public Collection> getCatchTargets(ITypeBinding type) { Assertions.UNREACHABLE("RootContext.getCatchTargets()"); return null; } @@ -2991,16 +2943,6 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst { 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() { Assertions.UNREACHABLE("Rootcontext.needLValue()"); return false; diff --git a/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/translator/jdt/JDTSourceModuleTranslator.java b/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/translator/jdt/JDTSourceModuleTranslator.java index 04bd8600f..1b4f1d3c9 100644 --- a/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/translator/jdt/JDTSourceModuleTranslator.java +++ b/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/translator/jdt/JDTSourceModuleTranslator.java @@ -115,8 +115,6 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator { public void loadAllSources(Set modules) { // TODO: we might need one AST (-> "Object" class) for all files. // TODO: group by project and send 'em in - JDTJava2CAstTranslator jdt2cast = makeCAstTranslator(); - final Java2IRTranslator java2ir = makeIRTranslator(jdt2cast); System.out.println(modules); @@ -143,7 +141,9 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator { public void acceptAST(ICompilationUnit source, CompilationUnit ast) { 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) { e.printStackTrace(); } @@ -165,12 +165,12 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator { } } - protected Java2IRTranslator makeIRTranslator(JDTJava2CAstTranslator jdt2cast) { - return new Java2IRTranslator(jdt2cast, sourceLoader); + protected Java2IRTranslator makeIRTranslator() { + return new Java2IRTranslator(sourceLoader); } - protected JDTJava2CAstTranslator makeCAstTranslator() { - return new JDTJava2CAstTranslator(sourceLoader); + protected JDTJava2CAstTranslator makeCAstTranslator(CompilationUnit cu, String fullPath) { + return new JDTJava2CAstTranslator(sourceLoader, cu, fullPath, false); } } diff --git a/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/IRGoal.java b/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/IRGoal.java index d104cb88b..e33f9951f 100644 --- a/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/IRGoal.java +++ b/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/IRGoal.java @@ -51,16 +51,18 @@ public class IRGoal extends SourceGoal_c /* PORT1.7 removed 'implements EndGoal' ExtensionInfo extInfo= job.extensionInfo(); fTranslator= new Java2IRTranslator( + fSourceLoader, + ((IRTranslatorExtension)extInfo).getCAstRewriterFactory()); + ModuleSource src = (ModuleSource) job.source(); + fTranslator.translate( + src.getModule(), new PolyglotJava2CAstTranslator( + job.ast(), fSourceLoader.getReference(), extInfo.nodeFactory(), extInfo.typeSystem(), new PolyglotIdentityMapper(fSourceLoader.getReference()), - ((IRTranslatorExtension)extInfo).getReplicateForDoLoops()), - fSourceLoader, - ((IRTranslatorExtension)extInfo).getCAstRewriterFactory()); - ModuleSource src = (ModuleSource) job.source(); - fTranslator.translate(src.getModule(),job.ast(), src.name()); + ((IRTranslatorExtension)extInfo).getReplicateForDoLoops()).translateToCAst()); return true; } diff --git a/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java b/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java index 337abf136..2fc41781a 100644 --- a/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java +++ b/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/PolyglotJava2CAstTranslator.java @@ -20,6 +20,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -34,6 +35,7 @@ import polyglot.ast.ArrayTypeNode; import polyglot.ast.Assert; import polyglot.ast.Assign; import polyglot.ast.Binary; +import polyglot.ast.Binary.Operator; import polyglot.ast.Block; import polyglot.ast.BooleanLit; import polyglot.ast.Branch; @@ -49,6 +51,7 @@ import polyglot.ast.ClassLit; import polyglot.ast.ClassMember; import polyglot.ast.Conditional; import polyglot.ast.ConstructorCall; +import polyglot.ast.ConstructorCall.Kind; import polyglot.ast.ConstructorDecl; import polyglot.ast.Do; import polyglot.ast.Empty; @@ -94,8 +97,6 @@ import polyglot.ast.TopLevelDecl; import polyglot.ast.Try; import polyglot.ast.Unary; import polyglot.ast.While; -import polyglot.ast.Binary.Operator; -import polyglot.ast.ConstructorCall.Kind; import polyglot.types.ArrayType; import polyglot.types.ClassType; import polyglot.types.CodeInstance; @@ -117,9 +118,11 @@ import polyglot.types.Types; import polyglot.util.Position; 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.translator.JavaProcedureEntity; -import com.ibm.wala.cast.java.translator.TranslatorToCAst; import com.ibm.wala.cast.java.types.JavaType; import com.ibm.wala.cast.tree.CAst; 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.CAstTypeDictionary; 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.CAstImpl; import com.ibm.wala.cast.tree.impl.CAstNodeTypeMapRecorder; 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.CAstSymbolImpl; 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.debug.Assertions; -@SuppressWarnings("unchecked") -public class PolyglotJava2CAstTranslator implements TranslatorToCAst { +public class PolyglotJava2CAstTranslator { protected final CAst fFactory = new CAstImpl(); protected final NodeFactory fNodeFactory; @@ -179,10 +179,12 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { protected PolyglotIdentityMapper fIdentityMapper; - protected boolean replicateForDoLoops = false; + protected final DoLoopTranslator doLoopTranslator; protected final boolean DEBUG = true; - + + private final Node ast; + final protected TranslatingVisitor getTranslator() { if (fTranslator == null) fTranslator = createTranslator(); @@ -1133,42 +1135,17 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { String loopLabel = (String) wc.getLabelMap().get(d); 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) { - CAstRewriter.Rewrite x = (new CAstCloner(fFactory, 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()); + WalkContext lc = new LoopContext(wc, loopLabel, breakTarget, continueTarget); + CAstNode loopExpr = walkNodes(d.cond(), wc); + CAstNode loopBody = walkNodes(d.body(), lc); - return makeNode(wc, fFactory, d, CAstNode.BLOCK_STMT, - 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); - } + return doLoopTranslator.translateDoLoop(loopExpr, loopBody, continueNode, breakNode, wc); } + public CAstNode visit(For f, WalkContext wc) { Node breakTarget = makeBreakTarget(f); Node continueTarget = makeContinueTarget(f); @@ -1529,12 +1506,8 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { protected abstract static class CodeBodyEntity implements CAstEntity { private final Map> fEntities; - public CodeBodyEntity(Map entities) { - fEntities = new LinkedHashMap>(); - for (Iterator keys = entities.keySet().iterator(); keys.hasNext();) { - CAstNode key = keys.next(); - fEntities.put(key, Collections.singleton(entities.get(key))); - } + public CodeBodyEntity(Map> entities) { + fEntities = new LinkedHashMap>(entities); } public Map> getAllScopedEntities() { @@ -1674,7 +1647,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { private final String[] argumentNames; public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, Type declaringType, String[] argumentNames, - Map entities, MethodContext mc) { + Map> entities, MethodContext mc) { super(entities); fPdast = pdast; fSystem = system; @@ -1685,7 +1658,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { } public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, String[] argumentNames, - Map entities, MethodContext mc) { + Map> entities, MethodContext 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); } @@ -1916,21 +1889,9 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { } } - public interface WalkContext { - void addScopedEntity(CAstNode node, CAstEntity e); - - CAstControlFlowRecorder cfg(); - - CAstSourcePositionRecorder pos(); - - CAstNodeTypeMapRecorder getNodeTypeMap(); - + public interface WalkContext extends TranslatorToCAst.WalkContext { Collection> getCatchTargets(Type label); - Node getContinueFor(String label); - - Node getBreakFor(String label); - Node getFinally(); CodeInstance getEnclosingMethod(); @@ -1948,49 +1909,15 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { boolean needLVal(); } - protected static class DelegatingContext implements WalkContext { - private final WalkContext parent; - - public WalkContext getParent() { - return parent; - } - + protected static class DelegatingContext extends TranslatorToCAst.DelegatingContext implements WalkContext { protected DelegatingContext(WalkContext parent) { - this.parent = parent; - } - - public void addScopedEntity(CAstNode node, CAstEntity e) { - parent.addScopedEntity(node, e); - } - - // public Map/**/ getScopedEntities() { - // return parent.getScopedEntities(); - // } - - public CAstControlFlowRecorder cfg() { - return parent.cfg(); - } - - public CAstSourcePositionRecorder pos() { - return parent.pos(); - } - - public CAstNodeTypeMapRecorder getNodeTypeMap() { - return parent.getNodeTypeMap(); + super(parent); } public Collection> getCatchTargets(Type 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() { return parent.getFinally(); } @@ -2121,9 +2048,9 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { private final Map labelMap = HashMapFactory.make(2); - private final Map fEntities; + private final Map> fEntities; - public CodeBodyContext(WalkContext parent, Map entities) { + public CodeBodyContext(WalkContext parent, Map> entities) { super(parent); fEntities = entities; } @@ -2141,10 +2068,11 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { } public void addScopedEntity(CAstNode node, CAstEntity entity) { - fEntities.put(node, entity); + if (! fEntities.containsKey(node)) { fEntities.put(node, new HashSet(1)); } + fEntities.get(node).add(entity); } - public Map/* */ getScopedEntities() { + public Map> getScopedEntities() { return fEntities; } @@ -2160,7 +2088,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { public class MethodContext extends CodeBodyContext { final CodeInstance fPI; - public MethodContext(CodeInstance pi, Map entities, WalkContext parent) { + public MethodContext(CodeInstance pi, Map> entities, WalkContext parent) { super(parent, entities); fPI = pi; } @@ -2188,8 +2116,8 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { this.tryNode = tryNode; this.context = context; - for (Iterator catchIter = tryNode.catchBlocks().iterator(); catchIter.hasNext();) { - Catch c = (Catch) catchIter.next(); + for (Iterator catchIter = tryNode.catchBlocks().iterator(); catchIter.hasNext();) { + Catch c = catchIter.next(); Pair p = Pair.make(c.catchType(), (Object)c); fCatchNodes.add(p); @@ -2217,7 +2145,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { continue; } } - catchNodes.addAll(getParent().getCatchTargets(label)); + catchNodes.addAll(parent.getCatchTargets(label)); return catchNodes; } @@ -2230,53 +2158,23 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { } } - protected static class RootContext implements WalkContext { + protected static class RootContext extends TranslatorToCAst.RootContext implements WalkContext { final CAstTypeDictionary fTypeDict; public RootContext(CAstTypeDictionary 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> getCatchTargets(Type label) { Assertions.UNREACHABLE("RootContext.getCatchTargets()"); return null; } - public CAstNodeTypeMapRecorder getNodeTypeMap() { - Assertions.UNREACHABLE("RootContext.getNodeTypeMap()"); - return null; - } - public Node getFinally() { Assertions.UNREACHABLE("RootContext.getFinally()"); 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() { Assertions.UNREACHABLE("RootContext.getEnclosingMethod()"); 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; fTypeSystem = ts; fNodeFactory = nf; fIdentityMapper = identityMapper; - this.replicateForDoLoops = replicateForDoLoops; + doLoopTranslator = new DoLoopTranslator(replicateForDoLoops, fFactory); fNPEType = fTypeSystem.NullPointerException(); fCCEType = fTypeSystem.ClassCastException(); fREType = fTypeSystem.RuntimeException(); @@ -2530,8 +2429,8 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { return cn; } - public CAstEntity translate(Object ast, String fileName) { - return walkEntity((Node) ast, new RootContext(getTypeDict())); + public CAstEntity translateToCAst() { + 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); InitializerInstance initInstance = fTypeSystem.createInitializerInstance(n.position(), Types.ref(initDef)); - Map childEntities = HashMapFactory.make(); + Map> childEntities = HashMapFactory.make(); final MethodContext mc = new MethodContext(initInstance, childEntities, classContext); List inits = classContext.getStaticInitializers(); @@ -2644,7 +2543,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst { for (Iterator iter = superConstructors.iterator(); iter.hasNext();) { ConstructorInstance superCtor = (ConstructorInstance) iter.next(); - Map childEntities = HashMapFactory.make(); + Map> childEntities = HashMapFactory.make(); final MethodContext mc = new MethodContext(superCtor, childEntities, classContext); 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()); } else if (rootNode instanceof ProcedureDecl) { final ProcedureDecl pd = (ProcedureDecl) rootNode; - final Map memberEntities = new LinkedHashMap(); + final Map> memberEntities = HashMapFactory.make(); final MethodContext mc = new MethodContext(pd.procedureInstance().asInstance(), memberEntities, context); CAstNode pdAST = null; diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/examples/ast/SynchronizedBlockDuplicator.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/examples/ast/SynchronizedBlockDuplicator.java index 06c07d8b2..27a628bc5 100644 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/examples/ast/SynchronizedBlockDuplicator.java +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/examples/ast/SynchronizedBlockDuplicator.java @@ -186,7 +186,7 @@ public class SynchronizedBlockDuplicator extends return null; } - protected CAstNode copyNodes(CAstNode n, RewriteContext c, Map, CAstNode> nodeMap) { + protected CAstNode copyNodes(CAstNode n, final CAstControlFlowMap cfg, RewriteContext c, Map, CAstNode> nodeMap) { String varName; // don't copy operators or constants (presumably since they are immutable?) if (n instanceof CAstOperator) { @@ -204,15 +204,15 @@ public class SynchronizedBlockDuplicator extends Ast.makeNode(CAstNode.VAR, Ast.makeConstant(varName))); // the new if conditional - return Ast.makeNode(CAstNode.IF_STMT, test, copyNodes(n, new SyncContext(true, n, c), nodeMap), - copyNodes(n, new SyncContext(false, n, c), nodeMap)); + return Ast.makeNode(CAstNode.IF_STMT, test, copyNodes(n, cfg, new SyncContext(true, n, c), nodeMap), + copyNodes(n, cfg, new SyncContext(false, n, c), nodeMap)); } else { // invoke copyNodes() on the children with context c, ensuring, e.g., that // the body of a synchronized block gets cloned CAstNode[] newChildren = new CAstNode[n.getChildCount()]; 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); diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/Java2IRTranslator.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/Java2IRTranslator.java index 3a60728ed..0dd6ae558 100644 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/Java2IRTranslator.java +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/Java2IRTranslator.java @@ -15,6 +15,7 @@ package com.ibm.wala.cast.java.translator; 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.tree.CAst; import com.ibm.wala.cast.tree.CAstEntity; @@ -29,34 +30,29 @@ public class Java2IRTranslator { protected final JavaSourceLoaderImpl fLoader; - protected final TranslatorToCAst fSourceTranslator; - CAstRewriterFactory castRewriterFactory = null; - public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader) { - this(sourceTranslator, srcLoader, false); + public Java2IRTranslator(JavaSourceLoaderImpl srcLoader) { + this(srcLoader, false); } - public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader, boolean debug) { - this(sourceTranslator, srcLoader, null, debug); + public Java2IRTranslator(JavaSourceLoaderImpl srcLoader, boolean debug) { + this(srcLoader, null, debug); } - public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader, + public Java2IRTranslator(JavaSourceLoaderImpl srcLoader, 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) { DEBUG = debug; fLoader = srcLoader; - fSourceTranslator = sourceTranslator; this.castRewriterFactory = castRewriterFactory; } - public void translate(ModuleEntry module, Object ast, String N) { - CAstEntity ce = fSourceTranslator.translate(ast, N); - + public void translate(ModuleEntry module, CAstEntity ce) { if (DEBUG) { PrintWriter printWriter = new PrintWriter(System.out); CAstPrinter.printTo(ce, printWriter); diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java index 223e3e96c..13008f65e 100644 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java @@ -304,26 +304,24 @@ public class JavaCAst2IRTranslator extends AstTranslator { 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 visitor) { if (n.getChildCount() == 0) { super.leaveThis(n, c, visitor); } else { - WalkContext wc = (WalkContext) c; - int result = wc.currentScope().allocateTempValue(); - setValue(n, result); - wc.cfg().addInstruction(new EnclosingObjectReference(result, (TypeReference) n.getChild(0).getValue())); + int result = c.currentScope().allocateTempValue(); + c.setValue(n, result); + c.cfg().addInstruction(new EnclosingObjectReference(result, (TypeReference) n.getChild(0).getValue())); } } - protected boolean visitCast(CAstNode n, Context c, CAstVisitor visitor) { - WalkContext context = (WalkContext)c; + protected boolean visitCast(CAstNode n, WalkContext context, CAstVisitor visitor) { int result = context.currentScope().allocateTempValue(); - setValue(n, result); + context.setValue(n, result); return false; } - protected void leaveCast(CAstNode n, Context c, CAstVisitor visitor) { - WalkContext context = (WalkContext)c; - int result = getValue(n); + + protected void leaveCast(CAstNode n, WalkContext context, CAstVisitor visitor) { + int result = context.getValue(n); CAstType toType = (CAstType) n.getChild(0).getValue(); TypeReference toRef = makeType(toType); @@ -334,7 +332,7 @@ public class JavaCAst2IRTranslator extends AstTranslator { context.cfg().addInstruction( insts.ConversionInstruction( result, - getValue(n.getChild(1)), + context.getValue(n.getChild(1)), fromRef, toRef, false)); @@ -343,43 +341,42 @@ public class JavaCAst2IRTranslator extends AstTranslator { context.cfg().addInstruction( insts.CheckCastInstruction( result, - getValue(n.getChild(1)), + context.getValue(n.getChild(1)), toRef, true)); processExceptions(n, context); } } - protected boolean visitInstanceOf(CAstNode n, Context c, CAstVisitor visitor) { - WalkContext context = (WalkContext)c; + + protected boolean visitInstanceOf(CAstNode n, WalkContext context, CAstVisitor visitor) { int result = context.currentScope().allocateTempValue(); - setValue(n, result); + context.setValue(n, result); return false; } - protected void leaveInstanceOf(CAstNode n, Context c, CAstVisitor visitor) { - WalkContext context = (WalkContext)c; - int result = getValue(n); + + protected void leaveInstanceOf(CAstNode n, WalkContext context, CAstVisitor visitor) { + int result = context.getValue(n); CAstType type = (CAstType) n.getChild(0).getValue(); TypeReference ref = makeType( type ); context.cfg().addInstruction( insts.InstanceofInstruction( result, - getValue(n.getChild(1)), + context.getValue(n.getChild(1)), ref)); } - protected boolean doVisit(CAstNode n, Context context, CAstVisitor visitor) { - WalkContext wc = (WalkContext) context; + protected boolean doVisit(CAstNode n, WalkContext wc, CAstVisitor visitor) { if (n.getKind() == CAstNode.MONITOR_ENTER) { 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); return true; } else if (n.getKind() == CAstNode.MONITOR_EXIT) { 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); return true; } else { diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/TranslatorToCAst.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/TranslatorToCAst.java deleted file mode 100644 index 5218c8e05..000000000 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/TranslatorToCAst.java +++ /dev/null @@ -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); - -} diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestArgumentSensitivityRhino.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestArgumentSensitivityRhino.java new file mode 100644 index 000000000..67988884b --- /dev/null +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestArgumentSensitivityRhino.java @@ -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()); + } + + +} diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestCorrelatedPairExtractionRhino.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestCorrelatedPairExtractionRhino.java index 9c79a5a7e..ba9575b6c 100644 --- a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestCorrelatedPairExtractionRhino.java +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestCorrelatedPairExtractionRhino.java @@ -15,10 +15,10 @@ import java.io.IOException; 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.RhinoToAstTranslator; import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.impl.CAstImpl; import com.ibm.wala.classLoader.SourceModule; -import org.mozilla.javascript.RhinoToAstTranslator; public class TestCorrelatedPairExtractionRhino extends TestCorrelatedPairExtraction { protected CorrelationFinder makeCorrelationFinder() { @@ -26,9 +26,8 @@ public class TestCorrelatedPairExtractionRhino extends TestCorrelatedPairExtract } protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException { - RhinoToAstTranslator.resetGensymCounters(); - RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName()); - CAstEntity entity = translator.translate(); + RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName(), false); + CAstEntity entity = translator.translateToCAst(); return entity; } } diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtractionRhino.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtractionRhino.java index 661221223..13a401e4b 100644 --- a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtractionRhino.java +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtractionRhino.java @@ -13,17 +13,16 @@ package com.ibm.wala.cast.js.test; 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.impl.CAstImpl; import com.ibm.wala.classLoader.SourceModule; public class TestForInBodyExtractionRhino extends TestForInBodyExtraction { protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException { - RhinoToAstTranslator.resetGensymCounters(); - RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName()); - CAstEntity entity = translator.translate(); + RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName(), false); + CAstEntity entity = translator.translateToCAst(); return entity; } } diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestJQueryExamplesRhino.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestJQueryExamplesRhino.java new file mode 100644 index 000000000..d8ee9a59c --- /dev/null +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestJQueryExamplesRhino.java @@ -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()); + } + +} diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/vis/JsViewerDriver.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/vis/JsViewerDriver.java index 64ecc1daa..ebe8ac3a1 100644 --- a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/vis/JsViewerDriver.java +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/vis/JsViewerDriver.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.net.URL; 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.DomLessSourceExtractor; import com.ibm.wala.cast.js.html.IdentityUrlResolver; @@ -40,8 +41,8 @@ public class JsViewerDriver extends Util { SourceModule[] sources = getSources(domless, url); - JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, false, true); - builder.setBaseURL(url); + JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, false, false, AstIRFactory.makeDefaultFactory()); + builder.setBaseURL(url); CallGraph cg = builder.makeCallGraph(builder.getOptions()); PointerAnalysis pa = builder.getPointerAnalysis(); diff --git a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslator.java b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslator.java index c919a4e7c..eb57e918e 100644 --- a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslator.java @@ -14,7 +14,6 @@ import java.io.IOException; import java.util.LinkedList; import java.util.List; -import org.mozilla.javascript.RhinoToAstTranslator; import com.ibm.wala.cast.ir.translator.TranslatorToCAst; import com.ibm.wala.cast.js.translator.PropertyReadExpander.ExpanderKey; @@ -31,9 +30,11 @@ import com.ibm.wala.classLoader.SourceModule; public class CAstRhinoTranslator implements TranslatorToCAst { private final List rewriters = new LinkedList(); private final SourceModule M; - - public CAstRhinoTranslator(SourceModule M) { + private final boolean replicateForDoLoops; + + public CAstRhinoTranslator(SourceModule M, boolean replicateForDoLoops) { this.M = M; + this.replicateForDoLoops = replicateForDoLoops; this.addRewriter(new CAstRewriterFactory() { public CAstRewriter createCAstRewriter(CAst ast) { return new PropertyReadExpander(ast); @@ -57,9 +58,10 @@ public class CAstRhinoTranslator implements TranslatorToCAst { } 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) entity = rwf.createCAstRewriter(Ast).rewrite(entity); return entity; } + } diff --git a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslatorFactory.java b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslatorFactory.java index aa2dba7b0..99e9f963a 100644 --- a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslatorFactory.java +++ b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslatorFactory.java @@ -7,7 +7,7 @@ import com.ibm.wala.classLoader.SourceModule; public class CAstRhinoTranslatorFactory implements JavaScriptTranslatorFactory { public TranslatorToCAst make(CAst ast, SourceModule M) { - return new CAstRhinoTranslator(M); + return new CAstRhinoTranslator(M, false); } } diff --git a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java new file mode 100755 index 000000000..db56b03dc --- /dev/null +++ b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java @@ -0,0 +1,2203 @@ +/****************************************************************************** + * 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.Reader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.mozilla.javascript.CompilerEnvirons; +import org.mozilla.javascript.Node; +import org.mozilla.javascript.Parser; +import org.mozilla.javascript.Token; +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; +import org.mozilla.javascript.tools.ToolErrorReporter; + +import com.ibm.wala.cast.ir.translator.TranslatorToCAst.DoLoopTranslator; +import com.ibm.wala.cast.js.html.MappedSourceModule; +import com.ibm.wala.cast.js.ipa.callgraph.JSSSAPropagationCallGraphBuilder; +import com.ibm.wala.cast.js.loader.JavaScriptLoader; +import com.ibm.wala.cast.js.translator.JavaScriptTranslatorToCAst; +import com.ibm.wala.cast.js.types.JavaScriptTypes; +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.CAstNodeTypeMap; +import com.ibm.wala.cast.tree.CAstQualifier; +import com.ibm.wala.cast.tree.CAstSourcePositionMap; +import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; +import com.ibm.wala.cast.tree.CAstType; +import com.ibm.wala.cast.tree.impl.CAstOperator; +import com.ibm.wala.cast.tree.impl.CAstSymbolImpl; +import com.ibm.wala.cast.tree.impl.LineNumberPosition; +import com.ibm.wala.classLoader.SourceModule; +import com.ibm.wala.util.collections.EmptyIterator; +import com.ibm.wala.util.collections.HashMapFactory; +import com.ibm.wala.util.debug.Assertions; + +public class RhinoToAstTranslator { + + /** + * a dummy name to use for standard function calls, only used to distinguish + * them from constructor calls + */ + public static final String STANDARD_CALL_FN_NAME = "do"; + + /** + * name used for constructor calls, used to distinguish them from standard + * function calls + */ + public static final String CTOR_CALL_FN_NAME = "ctor"; + + private final boolean DEBUG = true; + + /** + * shared interface for all objects storing contextual information during the + * Rhino AST traversal + * + */ + private interface WalkContext extends JavaScriptTranslatorToCAst.WalkContext { + + } + + /** + * default implementation of WalkContext; methods do nothing / return null + * + */ + private static class RootContext extends JavaScriptTranslatorToCAst.RootContext implements WalkContext { + + } + + /** + * context used for function / script declarations + */ + private static class FunctionContext extends JavaScriptTranslatorToCAst.FunctionContext implements WalkContext { + FunctionContext(WalkContext parent, Node s) { + super(parent, s); + } + + } + + /** + * context used for top-level script declarations + */ + private static class ScriptContext extends FunctionContext { + private final String script; + + ScriptContext(WalkContext parent, ScriptNode s, String script) { + super(parent, s); + this.script = script; + } + + @Override + public String script() { + return script; + } + } + + private static class BaseCollectingContext extends JavaScriptTranslatorToCAst.BaseCollectingContext implements WalkContext { + + BaseCollectingContext(WalkContext parent, Node initialBaseFor, + CAstNode baseVar) { + super(parent, initialBaseFor, baseVar); + } + + } + + private static class LoopContext extends JavaScriptTranslatorToCAst.LoopContext implements WalkContext { + + LoopContext(WalkContext parent, Node breakTo, Node continueTo, String label) { + super(parent, breakTo, continueTo, label); + } + + } + + private static class TryCatchContext extends JavaScriptTranslatorToCAst.TryCatchContext implements WalkContext { + + TryCatchContext(WalkContext parent, CAstNode catchNode) { + super(parent, catchNode); + } + + } + + private CAstNode translateOpcode(int nodeType) { + switch (nodeType) { + case Token.POS: + case Token.ADD: + case Token.ASSIGN_ADD: + return CAstOperator.OP_ADD; + case Token.DIV: + case Token.ASSIGN_DIV: + return CAstOperator.OP_DIV; + case Token.ASSIGN_LSH: + case Token.LSH: + return CAstOperator.OP_LSH; + case Token.MOD: + case Token.ASSIGN_MOD: + return CAstOperator.OP_MOD; + case Token.MUL: + case Token.ASSIGN_MUL: + return CAstOperator.OP_MUL; + case Token.RSH: + case Token.ASSIGN_RSH: + return CAstOperator.OP_RSH; + case Token.SUB: + case Token.NEG: + case Token.ASSIGN_SUB: + return CAstOperator.OP_SUB; + case Token.URSH: + case Token.ASSIGN_URSH: + return CAstOperator.OP_URSH; + case Token.BITAND: + case Token.ASSIGN_BITAND: + return CAstOperator.OP_BIT_AND; + case Token.BITOR: + case Token.ASSIGN_BITOR: + return CAstOperator.OP_BIT_OR; + case Token.BITXOR: + case Token.ASSIGN_BITXOR: + return CAstOperator.OP_BIT_XOR; + + case Token.EQ: + return CAstOperator.OP_EQ; + case Token.SHEQ: + return CAstOperator.OP_STRICT_EQ; + case Token.IFEQ: + return CAstOperator.OP_EQ; + case Token.GE: + return CAstOperator.OP_GE; + case Token.GT: + return CAstOperator.OP_GT; + case Token.LE: + return CAstOperator.OP_LE; + case Token.LT: + return CAstOperator.OP_LT; + case Token.NE: + return CAstOperator.OP_NE; + case Token.SHNE: + return CAstOperator.OP_STRICT_NE; + case Token.IFNE: + return CAstOperator.OP_NE; + + case Token.BITNOT: + return CAstOperator.OP_BITNOT; + case Token.NOT: + return CAstOperator.OP_NOT; + + default: + Assertions.UNREACHABLE(); + return null; + } + } + + private CAstNode makeBuiltinNew(String typeName) { + return Ast.makeNode(CAstNode.NEW, Ast.makeConstant(typeName)); + } + + private CAstNode handleNew(WalkContext context, String globalName, CAstNode arguments[]) { + return handleNew(context, readName(context, globalName), arguments); + } + + private CAstNode handleNew(WalkContext context, CAstNode value, CAstNode arguments[]) { + return makeCtorCall(value, arguments, context); + } + + private boolean isPrologueScript(WalkContext context) { + return JavaScriptLoader.bootstrapFileNames.contains(context.script()); + } + + private Node getCallTarget(FunctionCall n) { + return n.getTarget(); + } + /** + * is n a call to "primitive" within our synthetic modeling code? + */ + private boolean isPrimitiveCall(WalkContext context, FunctionCall n) { + return isPrologueScript(context) && n.getType() == Token.CALL && getCallTarget(n).getType() == Token.NAME + && getCallTarget(n).getString().equals("primitive"); + } + + private Node getNewTarget(NewExpression n) { + return n.getTarget(); + } + + private boolean isPrimitiveCreation(WalkContext context, NewExpression n) { + Node target = getNewTarget(n); + return isPrologueScript(context) && n.getType() == Token.NEW && target.getType() == Token.NAME + && target.getString().equals("Primitives"); + } + + private CAstNode makeCall(CAstNode fun, CAstNode thisptr, CAstNode args[], WalkContext context) { + return makeCall(fun, thisptr, args, context, STANDARD_CALL_FN_NAME); + } + + private CAstNode makeCtorCall(CAstNode thisptr, CAstNode args[], WalkContext context) { + return makeCall(thisptr, null, args, context, CTOR_CALL_FN_NAME); + } + + private CAstNode makeCall(CAstNode fun, CAstNode thisptr, CAstNode args[], WalkContext context, String callee) { + int children = (args == null)? 0 : args.length; + + // children of CAst CALL node are the expression that evaluates to the + // function, followed by a name (either STANDARD_CALL_FN_NAME or + // CTOR_CALL_FN_NAME), followed by the actual + // parameters + int nargs = (thisptr == null) ? children + 2 : children + 3; + int i = 0; + CAstNode arguments[] = new CAstNode[nargs]; + arguments[i++] = fun; + assert callee.equals(STANDARD_CALL_FN_NAME) || callee.equals(CTOR_CALL_FN_NAME); + arguments[i++] = Ast.makeConstant(callee); + if (thisptr != null) + arguments[i++] = thisptr; + if (args != null) { + for (CAstNode arg : args) { + arguments[i++] = arg; + } + } + + CAstNode call = Ast.makeNode(CAstNode.CALL, arguments); + + context.cfg().map(call, call); + if (context.getCatchTarget() != null) { + context.cfg().add(call, context.getCatchTarget(), null); + } + + return call; + } + + /** + * Used to represent a script or function in the CAst; see walkEntity(). + * + */ + private static class ScriptOrFnEntity implements CAstEntity { + private final String[] arguments; + + private final String name; + + private final int kind; + + private final Map> subs; + + private final CAstNode ast; + + private final CAstControlFlowMap map; + + private final CAstSourcePositionMap pos; + + private final Position entityPosition; + + private ScriptOrFnEntity(AstNode n, Map> subs, CAstNode ast, CAstControlFlowMap map, CAstSourcePositionMap pos, String name) { + this.name = name; + this.entityPosition = pos.getPosition(ast); + + if (n instanceof FunctionNode) { + FunctionNode f = (FunctionNode) n; + f.flattenSymbolTable(false); + int i = 0; + arguments = new String[f.getParamCount() + 2]; + arguments[i++] = name; + arguments[i++] = "this"; + for (int j = 0; j < f.getParamCount(); j++) { + arguments[i++] = f.getParamOrVarName(j); + } + } else { + arguments = new String[0]; + } + kind = (n instanceof FunctionNode) ? CAstEntity.FUNCTION_ENTITY : CAstEntity.SCRIPT_ENTITY; + this.subs = subs; + this.ast = ast; + this.map = map; + this.pos = pos; + } + + @Override + public String toString() { + return ""; + } + + public String getName() { + return name; + } + + public String getSignature() { + Assertions.UNREACHABLE(); + return null; + } + + public int getKind() { + return kind; + } + + public String[] getArgumentNames() { + return arguments; + } + + public CAstNode[] getArgumentDefaults() { + return new CAstNode[0]; + } + + public int getArgumentCount() { + return arguments.length; + } + + public Map> getAllScopedEntities() { + return Collections.unmodifiableMap(subs); + } + + public Iterator getScopedEntities(CAstNode construct) { + if (subs.containsKey(construct)) + return subs.get(construct).iterator(); + else + return EmptyIterator.instance(); + } + + public CAstNode getAST() { + return ast; + } + + public CAstControlFlowMap getControlFlow() { + return map; + } + + public CAstSourcePositionMap getSourceMap() { + return pos; + } + + public CAstSourcePositionMap.Position getPosition() { + return entityPosition; + } + + public CAstNodeTypeMap getNodeTypeMap() { + return null; + } + + public Collection getQualifiers() { + Assertions.UNREACHABLE("JuliansUnnamedCAstEntity$2.getQualifiers()"); + return null; + } + + public CAstType getType() { + Assertions.UNREACHABLE("JuliansUnnamedCAstEntity$2.getType()"); + return null; + } + } + + private CAstEntity walkEntity(final AstNode n, List body, String name, WalkContext child) { + CAstNode[] stmts = body.toArray(new CAstNode[body.size()]); + + // add variable / constant / function declarations, if any + if (!child.getNameDecls().isEmpty()) { + // new first statement will be a block declaring all names. + CAstNode[] newStmts = new CAstNode[stmts.length + 1]; + + newStmts[0] = Ast.makeNode(CAstNode.BLOCK_STMT, child.getNameDecls().toArray(new CAstNode[child.getNameDecls().size()])); + + System.arraycopy(stmts, 0, newStmts, 1, stmts.length); + + stmts = newStmts; + } + + final CAstNode ast = Ast.makeNode(CAstNode.BLOCK_STMT, stmts); + final CAstControlFlowMap map = child.cfg(); + final CAstSourcePositionMap pos = child.pos(); + + // not sure if we need this copy --MS + final Map> subs = HashMapFactory.make(child.getScopedEntities()); + + return new ScriptOrFnEntity(n, subs, ast, map, pos, name); + } + + private Position makePosition(AstNode n) { + URL url = sourceModule.getURL(); + int line = n.getLineno(); + if (sourceModule instanceof MappedSourceModule) { + return ((MappedSourceModule) sourceModule).getMapping().getAssociatedFileAndLine(line); + } else { + return new LineNumberPosition(url, url, line); + } + } + + private void pushSourcePosition(WalkContext context, CAstNode n, Position p) { + if (context.pos().getPosition(n) == null) { + context.pos().setPosition(n, p); + for(int i = 0; i < n.getChildCount(); i++) { + pushSourcePosition(context, n.getChild(i), p); + } + } + } + private CAstNode noteSourcePosition(WalkContext context, CAstNode n, AstNode p) { + if (p.getLineno() != -1 && context.pos().getPosition(n) == null) { + pushSourcePosition(context, n, makePosition(p)); + } + return n; + } + + private CAstNode readName(WalkContext context, String name) { + CAstNode cn = makeVarRef(name); + context.cfg().map(cn, cn); + CAstNode target = context.getCatchTarget(); + if (target != null) { + context.cfg().add(cn, target, JavaScriptTypes.ReferenceError); + } else { + context.cfg().add(cn, CAstControlFlowMap.EXCEPTION_TO_EXIT, JavaScriptTypes.ReferenceError); + } + return cn; + } + + private List