Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.dev.jjs.impl;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JPostfixOperation;
import com.google.gwt.dev.jjs.ast.JPrefixOperation;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JValueLiteral;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Detects when same literal is passed as parameter value, and uses literal
* instead of parameter. The unused parameter will be removed by other analyses.
*/
// TODO: this optimization can mistakenly act on methods such as LongLib.fromInt
// since only one call is seen in LongLib itself.
public class SameParameterValueOptimizer {
/**
* Fill parameterValues map.
*/
private class AnalysisVisitor extends JVisitor {
@Override
public void endVisit(JBinaryOperation x, Context ctx) {
if (x.isAssignment() && x.getLhs() instanceof JParameterRef) {
parameterValues.put(((JParameterRef) x.getLhs()).getParameter(), null);
}
}
@Override
public void endVisit(JMethodCall x, Context ctx) {
JMethod method = x.getTarget();
// A quick check to reduce extra work needed otherwise...
if (isNotOptimizable(method)) {
return;
}
List arguments = x.getArgs();
List parameters = method.getParams();
for (int i = 0; i < arguments.size() && i < parameters.size(); i++) {
JParameter parameter = parameters.get(i);
JExpression argument = arguments.get(i);
if (!(argument instanceof JValueLiteral)) {
parameterValues.put(parameter, null);
continue;
}
if (!parameterValues.containsKey(parameter)) {
parameterValues.put(parameter, (JValueLiteral) argument);
continue;
}
JValueLiteral commonParamValue = parameterValues.get(parameter);
if (commonParamValue == null) {
continue;
}
if (!equalLiterals(commonParamValue, (JValueLiteral) argument)) {
parameterValues.put(parameter, null);
}
}
}
@Override
public void endVisit(JPostfixOperation x, Context ctx) {
if (x.getArg() instanceof JParameterRef) {
parameterValues.put(((JParameterRef) x.getArg()).getParameter(), null);
}
}
@Override
public void endVisit(JPrefixOperation x, Context ctx) {
if (x.getArg() instanceof JParameterRef) {
parameterValues.put(((JParameterRef) x.getArg()).getParameter(), null);
}
}
@Override
public void endVisit(JsniMethodBody x, Context ctx) {
for (JsniMethodRef methodRef : x.getJsniMethodRefs()) {
nonOptimizableMethods.add(methodRef.getTarget());
}
}
@Override
public boolean visit(JMethod x, Context ctx) {
if (isNotOptimizable(x)) {
nonOptimizableMethods.add(x);
}
return true;
}
private boolean isNotOptimizable(JMethod x) {
return x.needsDynamicDispatch() || x.canBeReferencedExternally();
}
private boolean equalLiterals(JValueLiteral l1, JValueLiteral l2) {
Object v1 = l1.getValueObj();
Object v2 = l2.getValueObj();
if (v1 == v2) {
return true;
}
if (v1 == null || v2 == null) {
return false;
}
return v1.equals(v2);
}
}
/**
* Substitute all parameter references with expression.
*/
private class SubstituteParameterVisitor extends JChangeTrackingVisitor {
private final CloneExpressionVisitor cloner;
public SubstituteParameterVisitor(OptimizerContext optimizerCtx) {
super(optimizerCtx);
cloner = new CloneExpressionVisitor();
}
@Override
public boolean enter(JMethod x, Context ctx) {
if (nonOptimizableMethods.contains(x)) {
return false;
}
for (JParameter parameter : x.getParams()) {
if (parameterValues.get(parameter) != null) {
return true;
}
}
return false;
}
@Override
public void endVisit(JParameterRef x, Context ctx) {
JParameter parameter = x.getParameter();
JLiteral value = parameterValues.get(parameter);
if (value != null) {
ctx.replaceMe(cloner.cloneExpression(Simplifier.cast(parameter.getType(), value)));
}
}
}
private static final String NAME = SameParameterValueOptimizer.class.getSimpleName();
@VisibleForTesting
static OptimizerStats exec(JProgram program) {
return exec(program, OptimizerContext.NULL_OPTIMIZATION_CONTEXT);
}
public static OptimizerStats exec(JProgram program, OptimizerContext optimizerCtx) {
Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "optimizer", NAME);
OptimizerStats stats = new SameParameterValueOptimizer(program).execImpl(program, optimizerCtx);
optimizerCtx.incOptimizationStep();
optimizeEvent.end("didChange", "" + stats.didChange());
return stats;
}
/**
* Parameter values.
*
* If doesn't contain a parameter, then its value is unknown. If contains
* parameter, and value is null - the parameter's value is not the same across
* all calls. If value is not null - the parameter's value is the same across
* all calls.
*/
private final Map parameterValues = Maps.newIdentityHashMap();
private final JProgram program;
/**
* These methods should not be tried to be optimized, either because they are polymorphic or we
* cannot see all the calls.
*/
private final Set nonOptimizableMethods = Sets.newHashSet();
private SameParameterValueOptimizer(JProgram program) {
this.program = program;
}
private OptimizerStats execImpl(JNode node, OptimizerContext optimizerCtx) {
OptimizerStats stats = new OptimizerStats(NAME);
new AnalysisVisitor().accept(node);
SubstituteParameterVisitor substituteParameterVisitor =
new SubstituteParameterVisitor(optimizerCtx);
substituteParameterVisitor.accept(node);
stats.recordModified(substituteParameterVisitor.getNumMods());
JavaAstVerifier.assertProgramIsConsistent(program);
return stats;
}
}