Skip to content

Commit

Permalink
Complete replacement of RUPP with RemoveUnusedCode.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=178636068
  • Loading branch information
brad4d committed Dec 11, 2017
1 parent 8ca4910 commit 34616d9
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 1,004 deletions.
2 changes: 1 addition & 1 deletion src/com/google/javascript/jscomp/CompilerOptions.java
Expand Up @@ -2286,7 +2286,7 @@ public void setExtractPrototypeMemberDeclarations(ExtractPrototypeMemberDeclarat
public void setRemoveUnusedPrototypeProperties(boolean enabled) {
this.removeUnusedPrototypeProperties = enabled;
// InlineSimpleMethods makes similar assumptions to
// RemoveUnusedPrototypeProperties, so they are enabled together.
// RemoveUnusedCode, so they are enabled together.
this.inlineGetters = enabled;
}

Expand Down
48 changes: 14 additions & 34 deletions src/com/google/javascript/jscomp/DefaultPassConfig.java
Expand Up @@ -820,8 +820,8 @@ protected List<PassFactory> getOptimizations() {

// After inlining some of the variable uses, some variables are unused.
// Re-run remove unused vars to clean it up.
if (options.removeUnusedVars || options.removeUnusedLocalVars) {
passes.add(getRemoveUnusedCodeOnce());
if (shouldRunRemoveUnusedCode()) {
passes.add(removeUnusedCodeOnce);
}
}

Expand Down Expand Up @@ -1007,10 +1007,6 @@ private List<PassFactory> getMainOptimizationLoop() {
passes.add(optimizeCalls);
}

if (options.removeUnusedVars || options.removeUnusedLocalVars) {
passes.add(getRemoveUnusedCode());
}

if (options.j2clPassMode.shouldAddJ2clPasses()) {
passes.add(j2clConstantHoisterPass);
passes.add(j2clClinitPass);
Expand Down Expand Up @@ -1041,8 +1037,8 @@ private List<PassFactory> getCodeRemovingPasses() {
passes.add(removeUnreachableCode);
}

if (options.removeUnusedPrototypeProperties) {
passes.add(removeUnusedPrototypeProperties);
if (shouldRunRemoveUnusedCode()) {
passes.add(removeUnusedCode);
}

if (options.removeUnusedClassProperties) {
Expand All @@ -1053,6 +1049,12 @@ private List<PassFactory> getCodeRemovingPasses() {
return passes;
}

private boolean shouldRunRemoveUnusedCode() {
return options.removeUnusedVars
|| options.removeUnusedLocalVars
|| options.removeUnusedPrototypeProperties;
}

private final HotSwapPassFactory checkSideEffects =
new HotSwapPassFactory("checkSideEffects") {
@Override
Expand Down Expand Up @@ -2710,23 +2712,6 @@ protected FeatureSet featureSet() {
}
};

/** Remove prototype properties that do not appear to be used. */
private final PassFactory removeUnusedPrototypeProperties =
new PassFactory(PassNames.REMOVE_UNUSED_PROTOTYPE_PROPERTIES, false) {
@Override
protected CompilerPass create(AbstractCompiler compiler) {
return new RemoveUnusedPrototypeProperties(
compiler,
options.removeUnusedPrototypePropertiesInExterns,
!options.removeUnusedVars);
}

@Override
protected FeatureSet featureSet() {
return ES8_MODULES;
}
};

/** Remove prototype properties that do not appear to be used. */
private final PassFactory removeUnusedClassProperties =
new PassFactory(PassNames.REMOVE_UNUSED_CLASS_PROPERTIES, false) {
Expand Down Expand Up @@ -2880,24 +2865,19 @@ protected FeatureSet featureSet() {
}
};

private PassFactory getRemoveUnusedCode() {
return getRemoveUnusedCode(false /* isOneTimePass */);
}

private PassFactory getRemoveUnusedCodeOnce() {
return getRemoveUnusedCode(true /* isOneTimePass */);
}
private PassFactory removeUnusedCodeOnce = getRemoveUnusedCode(true /* isOneTimePass */);
private PassFactory removeUnusedCode = getRemoveUnusedCode(false /* isOneTimePass */);

private PassFactory getRemoveUnusedCode(boolean isOneTimePass) {
/** Removes variables that are never used. */
return new PassFactory(PassNames.REMOVE_UNUSED_CODE, isOneTimePass) {
@Override
protected CompilerPass create(AbstractCompiler compiler) {
boolean removeOnlyLocals = options.removeUnusedLocalVars && !options.removeUnusedVars;
boolean preserveAnonymousFunctionNames =
options.anonymousFunctionNaming != AnonymousFunctionNamingPolicy.OFF;
return new RemoveUnusedCode.Builder(compiler)
.removeGlobals(!removeOnlyLocals)
.removeLocalVars(options.removeUnusedLocalVars)
.removeGlobals(options.removeUnusedVars)
.preserveFunctionExpressionNames(preserveAnonymousFunctionNames)
.removeUnusedPrototypeProperties(options.removeUnusedPrototypeProperties)
.allowRemovalOfExternProperties(options.removeUnusedPrototypePropertiesInExterns)
Expand Down
Expand Up @@ -32,7 +32,7 @@
* constructors or interfaces. Explicitly ignored is the possibility that
* these properties may be indirectly referenced using "for-in" or
* "Object.keys". This is the same assumption used with
* RemoveUnusedPrototypeProperties but is slightly wider in scope.
* RemoveUnusedCode but is slightly wider in scope.
*
* TODO(tomnguyen) Handle destructuring of objects/classes as cases where the field is used.
*
Expand Down
49 changes: 30 additions & 19 deletions src/com/google/javascript/jscomp/RemoveUnusedCode.java
Expand Up @@ -96,6 +96,7 @@ class RemoveUnusedCode implements CompilerPass {

private final CodingConvention codingConvention;

private final boolean removeLocalVars;
private final boolean removeGlobals;

private final boolean preserveFunctionExpressionNames;
Expand All @@ -118,7 +119,7 @@ class RemoveUnusedCode implements CompilerPass {
private final Multimap<String, Removable> removablesForPropertyNames = HashMultimap.create();

/** Single value to use for all vars for which we cannot remove anything at all. */
private final VarInfo canonicalTotallyUnremovableVarInfo;
private final VarInfo canonicalUnremovableVarInfo;

/**
* Keep track of scopes that we've traversed.
Expand All @@ -133,20 +134,22 @@ class RemoveUnusedCode implements CompilerPass {
RemoveUnusedCode(Builder builder) {
this.compiler = builder.compiler;
this.codingConvention = builder.compiler.getCodingConvention();
this.removeLocalVars = builder.removeLocalVars;
this.removeGlobals = builder.removeGlobals;
this.preserveFunctionExpressionNames = builder.preserveFunctionExpressionNames;
this.removeUnusedPrototypeProperties = builder.removeUnusedPrototypeProperties;
this.allowRemovalOfExternProperties = builder.allowRemovalOfExternProperties;
this.scopeCreator = new Es6SyntacticScopeCreator(builder.compiler);

// All Vars that are completely unremovable will share this VarInfo instance.
canonicalTotallyUnremovableVarInfo = new VarInfo();
canonicalTotallyUnremovableVarInfo.setIsExplicitlyNotRemovable();
canonicalUnremovableVarInfo = new VarInfo();
canonicalUnremovableVarInfo.setIsExplicitlyNotRemovable();
}

public static class Builder {
private final AbstractCompiler compiler;

private boolean removeLocalVars = false;
private boolean removeGlobals = false;
private boolean preserveFunctionExpressionNames = false;
private boolean removeUnusedPrototypeProperties = false;
Expand All @@ -156,6 +159,11 @@ public static class Builder {
this.compiler = compiler;
}

Builder removeLocalVars(boolean value) {
this.removeLocalVars = value;
return this;
}

Builder removeGlobals(boolean value) {
this.removeGlobals = value;
return this;
Expand Down Expand Up @@ -1085,7 +1093,8 @@ private void maybeRemoveUnusedTrailingParameters(Node argList, Scope fparamScope
*/
private VarInfo traverseVar(Var var) {
checkNotNull(var);
if (var.isArguments()) {
if (removeLocalVars && var.isArguments()) {
// If we are considering removing local variables, that includes parameters.
// If `arguments` is used in a function we must consider all parameters to be referenced.
Scope functionScope = var.getScope().getClosestHoistScope();
Node paramList = NodeUtil.getFunctionParameters(functionScope.getRootNode());
Expand All @@ -1104,7 +1113,7 @@ private VarInfo traverseVar(Var var) {
getVarInfo(paramVar).markAsReferenced();
}
// `arguments` is never removable.
return canonicalTotallyUnremovableVarInfo;
return canonicalUnremovableVarInfo;
} else {
return getVarInfo(var);
}
Expand All @@ -1119,26 +1128,28 @@ private VarInfo traverseVar(Var var) {
*/
private VarInfo getVarInfo(Var var) {
checkNotNull(var);
VarInfo varInfo = varInfoMap.get(var);
if (varInfo == null) {
boolean isGlobal = var.isGlobal();
if (isGlobal && !removeGlobals && !removeUnusedPrototypeProperties) {
varInfo = canonicalTotallyUnremovableVarInfo;
} else if (codingConvention.isExported(var.getName(), !isGlobal)) {
varInfo = canonicalTotallyUnremovableVarInfo;
} else if (var.isArguments()) {
varInfo = canonicalTotallyUnremovableVarInfo;
} else {
boolean isGlobal = var.isGlobal();
if (isGlobal && !removeGlobals) {
return canonicalUnremovableVarInfo;
} else if (!isGlobal && !removeLocalVars) {
return canonicalUnremovableVarInfo;
} else if (codingConvention.isExported(var.getName(), !isGlobal)) {
return canonicalUnremovableVarInfo;
} else if (var.isArguments()) {
return canonicalUnremovableVarInfo;
} else {
VarInfo varInfo = varInfoMap.get(var);
if (varInfo == null) {
varInfo = new VarInfo();
if (isGlobal && !removeGlobals) {
varInfo.setIsExplicitlyNotRemovable();
} else if (var.getParentNode().isParamList()) {
if (var.getParentNode().isParamList()) {
// We don't know where a parameter value comes from, so setting a property on it
// has unknown side effects and makes it not removable.
varInfo.propertyAssignmentsWillPreventRemoval = true;
}
varInfoMap.put(var, varInfo);
}
return varInfo;
}
return varInfo;
}

/**
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion test/com/google/javascript/jscomp/MultiPassTest.java
Expand Up @@ -425,7 +425,7 @@ private void addRemoveUnusedVars() {
new PassFactory("removeUnusedVars", false) {
@Override
protected CompilerPass create(AbstractCompiler compiler) {
return new RemoveUnusedCode.Builder(compiler).build();
return new RemoveUnusedCode.Builder(compiler).removeLocalVars(true).build();
}

@Override
Expand Down
6 changes: 5 additions & 1 deletion test/com/google/javascript/jscomp/OptimizeCallsTest.java
Expand Up @@ -50,7 +50,11 @@ public void process(Node externs, Node root) {
defFinder.process(externs, root);

new PureFunctionIdentifier(compiler, defFinder).process(externs, root);
new RemoveUnusedCode.Builder(compiler).removeGlobals(true).build().process(externs, root);
new RemoveUnusedCode.Builder(compiler)
.removeLocalVars(true)
.removeGlobals(true)
.build()
.process(externs, root);

final OptimizeCalls passes = new OptimizeCalls(compiler);
passes.addPass(new OptimizeReturns(compiler));
Expand Down

0 comments on commit 34616d9

Please sign in to comment.