Skip to content

Commit

Permalink
Live variables analysis Es6 modified to work for let/const/block scop…
Browse files Browse the repository at this point in the history
…e. DataFlowAnalysisTests - added tests for compute variables in ES6 and ES5

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=159312277
  • Loading branch information
simran-arora authored and blickly committed Jun 19, 2017
1 parent 92e8188 commit f0cfbde
Show file tree
Hide file tree
Showing 4 changed files with 380 additions and 37 deletions.
39 changes: 26 additions & 13 deletions src/com/google/javascript/jscomp/DataFlowAnalysis.java
Expand Up @@ -32,6 +32,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import javax.annotation.Nullable;

/**
* A framework to help writing static program analysis. A subclass of
Expand Down Expand Up @@ -589,13 +590,15 @@ public void visit(NodeTraversal t, Node n, Node parent) {
}

/**
* ******************************************************************** Alternate implementation
* of compute escaped that accepts the child scope and the current jsScope to help us access both
* the function and function body scopes.
* Alternate implementation of compute escaped that accepts the child scope and the current
* jsScope to help us access both the function and function body scopes.
*
* @param jsScopeChild If jsScope is a function scope, jsScopeChild is the scope for the body of
* that function. If not, jsScopeChild is null.
*/
static void computeEscaped(
final Scope jsScope,
final Scope jsScopeChild,
@Nullable final Scope jsScopeChild,
final Set<Var> escaped,
AbstractCompiler compiler,
Es6SyntacticScopeCreator scopeCreator) {
Expand All @@ -605,16 +608,24 @@ static void computeEscaped(
@Override
public void visit(NodeTraversal t, Node n, Node parent) {

if (jsScope.getRootNode() == NodeUtil.getEnclosingFunction(n)
|| !n.isName()
|| parent.isFunction()) {
Node enclosingBlock = NodeUtil.getEnclosingScopeRoot(n);
if (jsScope.isFunctionScope()) {
enclosingBlock = NodeUtil.getEnclosingFunction(n);
}
if (jsScope.getRootNode() == enclosingBlock || !n.isName() || parent.isFunction()) {
return;
}

String name = n.getString();
Var var = t.getScope().getVar(name);
Node enclosing = NodeUtil.getEnclosingFunction(var.getNode());
if (var != null && enclosing == jsScope.getRootNode()) {
escaped.add(var);
if (var != null) {
Node enclosingScopeNode = NodeUtil.getEnclosingScopeRoot(var.getNode());
if (jsScope.isFunctionScope()) {
enclosingScopeNode = NodeUtil.getEnclosingFunction(var.getNode());
}
if (enclosingScopeNode == jsScope.getRootNode()) {
escaped.add(var);
}
}
}
};
Expand All @@ -628,9 +639,11 @@ public void visit(NodeTraversal t, Node n, Node parent) {
}
}

for (Var var : jsScopeChild.getVarIterable()) {
if (compiler.getCodingConvention().isExported(var.getName())) {
escaped.add(var);
if (jsScopeChild != null) {
for (Var var : jsScopeChild.getVarIterable()) {
if (compiler.getCodingConvention().isExported(var.getName())) {
escaped.add(var);
}
}
}
}
Expand Down
84 changes: 60 additions & 24 deletions src/com/google/javascript/jscomp/LiveVariablesAnalysisEs6.java
Expand Up @@ -26,6 +26,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
* Compute the "liveness" of all local variables. A variable is "live" at a point of a program if
Expand Down Expand Up @@ -135,8 +136,8 @@ public int hashCode() {
LiveVariablesAnalysisEs6(
ControlFlowGraph<Node> cfg,
Scope jsScope,
Scope jsScopeChild,
Compiler compiler,
@Nullable Scope jsScopeChild,
AbstractCompiler compiler,
Es6SyntacticScopeCreator scopeCreator) {
super(cfg, new LiveVariableJoinOp());
this.jsScope = jsScope;
Expand All @@ -154,14 +155,37 @@ public int hashCode() {
*/
private void addScopeVariables() {
int num = 0;
for (Var v : jsScope.getVarIterable()) {
scopeVariables.put(v.getName(), num);
num++;
}
if (jsScope.isFunctionScope()) {
for (Var v : jsScope.getVarIterable()) {
scopeVariables.put(v.getName(), num);
num++;
}

if (jsScopeChild != null) {
for (Var v : jsScopeChild.getVarIterable()) {
// add the hoisted variables from this child scope
if ((v.isLet() || v.isConst()) && !jsScope.isFunctionScope()) {
continue;
}
scopeVariables.put(v.getName(), num);
num++;
}
}
} else if (jsScope.isFunctionBlockScope()) {
for (Var v : jsScope.getParent().getVarIterable()) {
scopeVariables.put(v.getName(), num);
num++;
}

for (Var v : jsScopeChild.getVarIterable()) {
scopeVariables.put(v.getName(), num);
num++;
for (Var v : jsScope.getVarIterable()) {
scopeVariables.put(v.getName(), num);
num++;
}
} else {
for (Var v : jsScope.getVarIterable()) {
scopeVariables.put(v.getName(), num);
num++;
}
}
}

Expand Down Expand Up @@ -224,9 +248,9 @@ private void computeGenKill(Node n, BitSet gen, BitSet kill, boolean conditional

switch (n.getToken()) {
case SCRIPT:
case BLOCK:
case ROOT:
case FUNCTION:
case BLOCK:
return;

case WHILE:
Expand All @@ -236,12 +260,13 @@ private void computeGenKill(Node n, BitSet gen, BitSet kill, boolean conditional
computeGenKill(NodeUtil.getConditionExpression(n), gen, kill, conditional);
return;

case FOR_OF:
case FOR_IN:
{
// for(x in y) {...}
// for (x in y) {...}
Node lhs = n.getFirstChild();
if (lhs.isVar()) {
// for(var x in y) {...}
if (NodeUtil.isNameDeclaration(lhs)) {
// for (var x in y) {...}
lhs = lhs.getLastChild();
}

Expand All @@ -256,6 +281,8 @@ private void computeGenKill(Node n, BitSet gen, BitSet kill, boolean conditional
return;
}

case LET:
case CONST:
case VAR:
for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {
if (c.hasChildren()) {
Expand Down Expand Up @@ -320,13 +347,15 @@ private void addToSetIfLocal(Node node, BitSet set) {
if (!escaped.contains(var)) {
set.set(getVarIndex(var.getName()));
}
} else if (!jsScopeChild.isDeclaredSloppy(name, false)) {
return;
} else {
Var var = jsScopeChild.getVar(name);
} else if (jsScopeChild != null && jsScope.isFunctionScope()) {
if (!jsScopeChild.isDeclared(name, false)) {
return;
} else {
Var var = jsScopeChild.getVar(name);

if (!escaped.contains(var)) {
set.set(getVarIndex(var.getName()));
if (!escaped.contains(var)) {
set.set(getVarIndex(var.getName()));
}
}
}
}
Expand All @@ -336,16 +365,23 @@ private void addToSetIfLocal(Node node, BitSet set) {
* escaped set.
*/
void markAllParametersEscaped() {
Node lp = jsScope.getRootNode().getSecondChild();
for (Node arg = lp.getFirstChild(); arg != null; arg = arg.getNext()) {
escaped.add(jsScope.getVar(arg.getString()));
if (jsScope.isFunctionScope()) {
Node lp = jsScope.getRootNode().getSecondChild();
for (Node arg = lp.getFirstChild(); arg != null; arg = arg.getNext()) {
escaped.add(jsScope.getVar(arg.getString()));
}
}
}

private boolean isArgumentsName(Node n) {
boolean childDeclared;
if (jsScopeChild != null) {
childDeclared = jsScopeChild.isDeclared(ARGUMENT_ARRAY_ALIAS, false);
} else {
childDeclared = true;
}
return n.isName()
&& n.getString().equals(ARGUMENT_ARRAY_ALIAS)
&& (!jsScope.isDeclaredSloppy(ARGUMENT_ARRAY_ALIAS, false)
|| !jsScopeChild.isDeclaredSloppy(ARGUMENT_ARRAY_ALIAS, false));
&& (!jsScope.isDeclaredSloppy(ARGUMENT_ARRAY_ALIAS, false) || !childDeclared);
}
}

0 comments on commit f0cfbde

Please sign in to comment.