/*
* Copyright ( C ) 2007 The Android Open Source Project
*
* 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.android.dx.ssa;
import com.android.dx.rop.code.RopMethod;
import com.android.dx.rop.code.TranslationAdvice;
import com.android.dx.ssa.back.LivenessAnalyzer;
import com.android.dx.ssa.back.SsaToRop;
import java.util.EnumSet;
/**
* Runs a method through the SSA form conversion , any optimization algorithms ,
* and returns it to rop form .
*/
public class Optimizer {
private static boolean preserveLocals = true ;
private static TranslationAdvice advice;
/** optional optimizer steps */
public enum OptionalStep {
MOVE_PARAM_COMBINER, SCCP, LITERAL_UPGRADE, CONST_COLLECTOR,
ESCAPE_ANALYSIS
}
/**
* @ return true if local variable information should be preserved , even
* at code size / register size cost
*/
public static boolean getPreserveLocals() {
return preserveLocals;
}
/**
* @ return { @ code non - null ; } translation advice
*/
public static TranslationAdvice getAdvice() {
return advice;
}
/**
* Runs optimization algorthims over this method , and returns a new
* instance of RopMethod with the changes .
*
* @ param rmeth method to process
* @ param paramWidth the total width , in register - units , of this method ' s
* parameters
* @ param isStatic true if this method has no ' this ' pointer argument .
* @ param inPreserveLocals true if local variable info should be preserved ,
* at the cost of some registers and insns
* @ param inAdvice { @ code non - null ; } translation advice
* @ return optimized method
*/
public static RopMethod optimize(RopMethod rmeth, int paramWidth,
boolean isStatic, boolean inPreserveLocals,
TranslationAdvice inAdvice) {
return optimize(rmeth, paramWidth, isStatic, inPreserveLocals, inAdvice,
EnumSet.allOf(OptionalStep.class ));
}
/**
* Runs optimization algorthims over this method , and returns a new
* instance of RopMethod with the changes .
*
* @ param rmeth method to process
* @ param paramWidth the total width , in register - units , of this method ' s
* parameters
* @ param isStatic true if this method has no ' this ' pointer argument .
* @ param inPreserveLocals true if local variable info should be preserved ,
* at the cost of some registers and insns
* @ param inAdvice { @ code non - null ; } translation advice
* @ param steps set of optional optimization steps to run
* @ return optimized method
*/
public static RopMethod optimize(RopMethod rmeth, int paramWidth,
boolean isStatic, boolean inPreserveLocals,
TranslationAdvice inAdvice, EnumSet<OptionalStep> steps) {
SsaMethod ssaMeth = null ;
preserveLocals = inPreserveLocals;
advice = inAdvice;
ssaMeth = SsaConverter.convertToSsaMethod(rmeth, paramWidth, isStatic);
runSsaFormSteps(ssaMeth, steps);
RopMethod resultMeth = SsaToRop.convertToRopMethod(ssaMeth, false );
if (resultMeth.getBlocks().getRegCount()
> advice.getMaxOptimalRegisterCount()) {
// Try to see if we can squeeze it under the register count bar
resultMeth = optimizeMinimizeRegisters(rmeth, paramWidth, isStatic,
steps);
}
return resultMeth;
}
/**
* Runs the optimizer with a strategy to minimize the number of rop - form
* registers used by the end result . Dex bytecode does not have instruction
* forms that take register numbers larger than 15 for all instructions .
* If we ' ve produced a method that uses more than 16 registers , try again
* with a different strategy to see if we can get under the bar . The end
* result will be much more efficient .
*
* @ param rmeth method to process
* @ param paramWidth the total width , in register - units , of this method ' s
* parameters
* @ param isStatic true if this method has no ' this ' pointer argument .
* @ param steps set of optional optimization steps to run
* @ return optimized method
*/
private static RopMethod optimizeMinimizeRegisters(RopMethod rmeth,
int paramWidth, boolean isStatic,
EnumSet<OptionalStep> steps) {
SsaMethod ssaMeth;
RopMethod resultMeth;
ssaMeth = SsaConverter.convertToSsaMethod(
rmeth, paramWidth, isStatic);
EnumSet<OptionalStep> newSteps = steps.clone();
/*
* CONST_COLLECTOR trades insns for registers , which is not an
* appropriate strategy here .
*/
newSteps.remove(OptionalStep.CONST_COLLECTOR);
runSsaFormSteps(ssaMeth, newSteps);
resultMeth = SsaToRop.convertToRopMethod(ssaMeth, true );
return resultMeth;
}
private static void runSsaFormSteps(SsaMethod ssaMeth,
EnumSet<OptionalStep> steps) {
boolean needsDeadCodeRemover = true ;
if (steps.contains(OptionalStep.MOVE_PARAM_COMBINER)) {
MoveParamCombiner.process(ssaMeth);
}
if (steps.contains(OptionalStep.SCCP)) {
SCCP.process(ssaMeth);
DeadCodeRemover.process(ssaMeth);
needsDeadCodeRemover = false ;
}
if (steps.contains(OptionalStep.LITERAL_UPGRADE)) {
LiteralOpUpgrader.process(ssaMeth);
DeadCodeRemover.process(ssaMeth);
needsDeadCodeRemover = false ;
}
/*
* ESCAPE_ANALYSIS impacts debuggability , so left off by default
*/
steps.remove(OptionalStep.ESCAPE_ANALYSIS);
if (steps.contains(OptionalStep.ESCAPE_ANALYSIS)) {
EscapeAnalysis.process(ssaMeth);
DeadCodeRemover.process(ssaMeth);
needsDeadCodeRemover = false ;
}
if (steps.contains(OptionalStep.CONST_COLLECTOR)) {
ConstCollector.process(ssaMeth);
DeadCodeRemover.process(ssaMeth);
needsDeadCodeRemover = false ;
}
// dead code remover must be run before phi type resolver
if (needsDeadCodeRemover) {
DeadCodeRemover.process(ssaMeth);
}
PhiTypeResolver.process(ssaMeth);
}
public static SsaMethod debugEdgeSplit(RopMethod rmeth, int paramWidth,
boolean isStatic, boolean inPreserveLocals,
TranslationAdvice inAdvice) {
preserveLocals = inPreserveLocals;
advice = inAdvice;
return SsaConverter.testEdgeSplit(rmeth, paramWidth, isStatic);
}
public static SsaMethod debugPhiPlacement(RopMethod rmeth, int paramWidth,
boolean isStatic, boolean inPreserveLocals,
TranslationAdvice inAdvice) {
preserveLocals = inPreserveLocals;
advice = inAdvice;
return SsaConverter.testPhiPlacement(rmeth, paramWidth, isStatic);
}
public static SsaMethod debugRenaming(RopMethod rmeth, int paramWidth,
boolean isStatic, boolean inPreserveLocals,
TranslationAdvice inAdvice) {
preserveLocals = inPreserveLocals;
advice = inAdvice;
return SsaConverter.convertToSsaMethod(rmeth, paramWidth, isStatic);
}
public static SsaMethod debugDeadCodeRemover(RopMethod rmeth,
int paramWidth, boolean isStatic, boolean inPreserveLocals,
TranslationAdvice inAdvice) {
SsaMethod ssaMeth;
preserveLocals = inPreserveLocals;
advice = inAdvice;
ssaMeth = SsaConverter.convertToSsaMethod(rmeth, paramWidth, isStatic);
DeadCodeRemover.process(ssaMeth);
return ssaMeth;
}
public static SsaMethod debugNoRegisterAllocation(RopMethod rmeth,
int paramWidth, boolean isStatic, boolean inPreserveLocals,
TranslationAdvice inAdvice, EnumSet<OptionalStep> steps) {
SsaMethod ssaMeth;
preserveLocals = inPreserveLocals;
advice = inAdvice;
ssaMeth = SsaConverter.convertToSsaMethod(rmeth, paramWidth, isStatic);
runSsaFormSteps(ssaMeth, steps);
LivenessAnalyzer.constructInterferenceGraph(ssaMeth);
return ssaMeth;
}
}
Messung V0.5 in Prozent C=98 H=97 G=97
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-27)
¤
*© Formatika GbR, Deutschland