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.
package soot.dava.toolkits.base.AST.transformations;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2006 Nomair A. Naeem ([email protected])
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import soot.BooleanType;
import soot.ByteType;
import soot.CharType;
import soot.DoubleType;
import soot.FloatType;
import soot.IntType;
import soot.LongType;
import soot.Scene;
import soot.ShortType;
import soot.SootClass;
import soot.SootField;
import soot.SootMethod;
import soot.Type;
import soot.Value;
import soot.ValueBox;
import soot.dava.DavaBody;
import soot.dava.internal.AST.ASTAggregatedCondition;
import soot.dava.internal.AST.ASTBinaryCondition;
import soot.dava.internal.AST.ASTCondition;
import soot.dava.internal.AST.ASTDoWhileNode;
import soot.dava.internal.AST.ASTForLoopNode;
import soot.dava.internal.AST.ASTIfElseNode;
import soot.dava.internal.AST.ASTIfNode;
import soot.dava.internal.AST.ASTMethodNode;
import soot.dava.internal.AST.ASTNode;
import soot.dava.internal.AST.ASTStatementSequenceNode;
import soot.dava.internal.AST.ASTSwitchNode;
import soot.dava.internal.AST.ASTSynchronizedBlockNode;
import soot.dava.internal.AST.ASTWhileNode;
import soot.dava.internal.asg.AugmentedStmt;
import soot.dava.internal.javaRep.DStaticFieldRef;
import soot.dava.toolkits.base.AST.analysis.DepthFirstAdapter;
import soot.jimple.DoubleConstant;
import soot.jimple.FloatConstant;
import soot.jimple.IntConstant;
import soot.jimple.LongConstant;
import soot.jimple.Stmt;
import soot.jimple.StringConstant;
import soot.tagkit.DoubleConstantValueTag;
import soot.tagkit.FloatConstantValueTag;
import soot.tagkit.IntegerConstantValueTag;
import soot.tagkit.LongConstantValueTag;
import soot.tagkit.StringConstantValueTag;
import soot.util.Chain;
//import soot.jimple.internal.*;
//import soot.grimp.internal.*;
//import soot.dava.toolkits.base.AST.traversals.*;
//import soot.dava.toolkits.base.AST.structuredAnalysis.*;
/**
* Maintained by: Nomair A. Naeem
*/
/**
* CHANGE LOG: 2nd February 2006:
*
*/
/*
* Both static and non-static BUT FINAL fields if initialized with constants get inlined A final initialized with an object
* (even if its a string) is NOT inlined e.g. public static final String temp = "hello"; //use of temp will get inlined
* public static final String temp1 = new String("hello"); //use of temp will NOT get inlined
*
*
* If its a static field we can get the info from a tag in the case of a non static we cant decide since the field is
* initialized inside a constructor and depending on different constructors there coul dbe different
* values...conservative....
*
*
* Need to be very clear when a SootField can be used It can be used in the following places:
*
* a, NOT used inside a Synchronized Block ........ HOWEVER ADD IT SINCE I DONT SEE WHY THIS RESTRICTION EXISTS!!! TICK b,
* CAN BE USED in a condition TICK c, CAN BE USED in the for init for update TICK d, CAN BE USED in a switch TICK e, CAN BE
* USED in a stmt TICK
*
* These are the exact places to look for constants...a constant is StringConstant DoubleConstant FloatConstant IntConstant
* (shortype, booltype, charType intType, byteType LongConstant
*/
public class DeInliningFinalFields extends DepthFirstAdapter {
SootClass sootClass = null;
SootMethod sootMethod = null;
DavaBody davaBody = null;
HashMap finalFields;
// ASTParentNodeFinder parentFinder;
public DeInliningFinalFields() {
}
public DeInliningFinalFields(boolean verbose) {
super(verbose);
}
public void inASTMethodNode(ASTMethodNode node) {
DavaBody davaBody = node.getDavaBody();
sootMethod = davaBody.getMethod();
// System.out.println("Deiniling method: "+sootMethod.getName());
sootClass = sootMethod.getDeclaringClass();
finalFields = new HashMap();
ArrayList fieldChain = new ArrayList();
Chain appClasses = Scene.v().getApplicationClasses();
Iterator it = appClasses.iterator();
while (it.hasNext()) {
SootClass tempClass = (SootClass) it.next();
// System.out.println("DeInlining"+tempClass.getName());
Chain tempChain = tempClass.getFields();
Iterator tempIt = tempChain.iterator();
while (tempIt.hasNext()) {
fieldChain.add(tempIt.next());
}
}
// Iterator fieldIt = sootClass.getFields().iterator();
Iterator fieldIt = fieldChain.iterator();
while (fieldIt.hasNext()) {
SootField f = (SootField) fieldIt.next();
if (f.isFinal()) {
// check for constant value tags
Type fieldType = f.getType();
if (fieldType instanceof DoubleType && f.hasTag("DoubleConstantValueTag")) {
double val = ((DoubleConstantValueTag) f.getTag("DoubleConstantValueTag")).getDoubleValue();
finalFields.put(new Double(val), f);
} else if (fieldType instanceof FloatType && f.hasTag("FloatConstantValueTag")) {
float val = ((FloatConstantValueTag) f.getTag("FloatConstantValueTag")).getFloatValue();
finalFields.put(new Float(val), f);
} else if (fieldType instanceof LongType && f.hasTag("LongConstantValueTag")) {
long val = ((LongConstantValueTag) f.getTag("LongConstantValueTag")).getLongValue();
finalFields.put(new Long(val), f);
} else if (fieldType instanceof CharType && f.hasTag("IntegerConstantValueTag")) {
int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue();
finalFields.put(new Integer(val), f);
} else if (fieldType instanceof BooleanType && f.hasTag("IntegerConstantValueTag")) {
int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue();
if (val == 0) {
finalFields.put(new Boolean(false), f);
} else {
finalFields.put(new Boolean(true), f);
}
} else if ((fieldType instanceof IntType || fieldType instanceof ByteType || fieldType instanceof ShortType)
&& f.hasTag("IntegerConstantValueTag")) {
int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue();
finalFields.put(new Integer(val), f);
} else if (f.hasTag("StringConstantValueTag")) {
String val = ((StringConstantValueTag) f.getTag("StringConstantValueTag")).getStringValue();
// System.out.println("adding string constant"+val);
finalFields.put(val, f);
}
} // end if final
} // going through fields
}
/*
* StringConstant DoubleConstant FloatConstant IntConstant (shortype, booltype, charType intType, byteType LongConstant
*/
private boolean isConstant(Value val) {
if (val instanceof StringConstant || val instanceof DoubleConstant || val instanceof FloatConstant
|| val instanceof IntConstant || val instanceof LongConstant) {
return true;
}
return false;
}
/*
* Notice as things stand synchblocks cant have the use of a SootField
*/
public void inASTSynchronizedBlockNode(ASTSynchronizedBlockNode node) {
// hence nothing is implemented here
}
public void checkAndSwitch(ValueBox valBox) {
Value val = valBox.getValue();
Object finalField = check(val);
if (finalField != null) {
// System.out.println("Final field with this value exists"+finalField);
/*
* If the final field belongs to the same class then we should supress declaring class
*/
SootField field = (SootField) finalField;
if (sootClass.declaresField(field.getName(), field.getType())) {
// this field is of this class so supress the declaring class
if (valBox.canContainValue(new DStaticFieldRef(field.makeRef(), true))) {
valBox.setValue(new DStaticFieldRef(field.makeRef(), true));
}
} else {
if (valBox.canContainValue(new DStaticFieldRef(field.makeRef(), true))) {
valBox.setValue(new DStaticFieldRef(field.makeRef(), false));
}
}
}
// else
// System.out.println("Final field not found");
}
public Object check(Value val) {
Object finalField = null;
if (isConstant(val)) {
// System.out.println("Found constant in code"+val);
// can be a byte or short or char......or an int ...in the case of
// int you also have to check for Booleans
if (val instanceof StringConstant) {
String myString = ((StringConstant) val).toString();
myString = myString.substring(1, myString.length() - 1);
// System.out.println("looking for:"+myString);
finalField = finalFields.get(myString);
} else if (val instanceof DoubleConstant) {
String myString = ((DoubleConstant) val).toString();
finalField = finalFields.get(new Double(myString));
} else if (val instanceof FloatConstant) {
String myString = ((FloatConstant) val).toString();
finalField = finalFields.get(new Float(myString));
} else if (val instanceof LongConstant) {
String myString = ((LongConstant) val).toString();
finalField = finalFields.get(new Long(myString.substring(0, myString.length() - 1)));
} else if (val instanceof IntConstant) {
String myString = ((IntConstant) val).toString();
if (myString.length() == 0) {
return null;
}
Type valType = ((IntConstant) val).getType();
Integer myInt = null;
try {
if (myString.charAt(0) == '\'') {
// character
if (myString.length() < 2) {
return null;
}
myInt = new Integer(myString.charAt(1));
} else {
myInt = new Integer(myString);
}
} catch (Exception e) {
// System.out.println("exception occured...gracefully exitting method..string was"+myString);
return finalField;
}
if (valType instanceof ByteType) {
finalField = finalFields.get(myInt);
} else if (valType instanceof IntType) {
if (myString.equals("false")) {
finalField = finalFields.get(new Boolean(false));
} else if (myString.equals("true")) {
finalField = finalFields.get(new Boolean(true));
} else {
finalField = finalFields.get(myInt);
}
} else if (valType instanceof ShortType) {
finalField = finalFields.get(myInt);
}
}
}
return finalField;
}
/*
* The key in a switch stmt can be a local or a SootField or a value which can contain constant
*
* Hence the some what indirect approach........notice we will work with valueBoxes so that by changing the value in the
* value box we can deInline any field
*/
public void inASTSwitchNode(ASTSwitchNode node) {
Value val = node.get_Key();
if (isConstant(val)) {
// find if there is a SootField with this constant
// System.out.println("Found constant as key to switch");
checkAndSwitch(node.getKeyBox());
return;
}
// val is not a constant but it might have other constants in it
Iterator it = val.getUseBoxes().iterator();
while (it.hasNext()) {
ValueBox tempBox = (ValueBox) it.next();
// System.out.println("Checking useBox of switch key");
checkAndSwitch(tempBox);
}
}
public void inASTStatementSequenceNode(ASTStatementSequenceNode node) {
for (AugmentedStmt as : node.getStatements()) {
Stmt s = as.get_Stmt();
Iterator tempIt = s.getUseBoxes().iterator();
while (tempIt.hasNext()) {
ValueBox tempBox = (ValueBox) tempIt.next();
// System.out.println("Checking useBox of stmt");
checkAndSwitch(tempBox);
}
}
}
public void inASTForLoopNode(ASTForLoopNode node) {
// checking uses in init
for (AugmentedStmt as : node.getInit()) {
Stmt s = as.get_Stmt();
Iterator tempIt = s.getUseBoxes().iterator();
while (tempIt.hasNext()) {
ValueBox tempBox = (ValueBox) tempIt.next();
// System.out.println("Checking useBox of init stmt");
checkAndSwitch(tempBox);
}
}
// checking uses in condition
ASTCondition cond = node.get_Condition();
checkConditionalUses(cond, node);
// checking uses in update
for (AugmentedStmt as : node.getUpdate()) {
Stmt s = as.get_Stmt();
Iterator tempIt = s.getUseBoxes().iterator();
while (tempIt.hasNext()) {
ValueBox tempBox = (ValueBox) tempIt.next();
// System.out.println("Checking useBox of update stmt");
checkAndSwitch(tempBox);
}
}
}
/*
* checking for unary conditions doesnt matter since this was definetly lost.
*/
public void checkConditionalUses(Object cond, ASTNode node) {
if (cond instanceof ASTAggregatedCondition) {
checkConditionalUses((((ASTAggregatedCondition) cond).getLeftOp()), node);
checkConditionalUses(((ASTAggregatedCondition) cond).getRightOp(), node);
return;
} else if (cond instanceof ASTBinaryCondition) {
// get uses from binaryCondition
Value val = ((ASTBinaryCondition) cond).getConditionExpr();
Iterator tempIt = val.getUseBoxes().iterator();
while (tempIt.hasNext()) {
ValueBox tempBox = (ValueBox) tempIt.next();
// System.out.println("Checking useBox of binary condition");
checkAndSwitch(tempBox);
}
}
}
/*
* The condition of an if node can use a local
*/
public void inASTIfNode(ASTIfNode node) {
ASTCondition cond = node.get_Condition();
checkConditionalUses(cond, node);
}
/*
* The condition of an ifElse node can use a local
*/
public void inASTIfElseNode(ASTIfElseNode node) {
ASTCondition cond = node.get_Condition();
checkConditionalUses(cond, node);
}
/*
* The condition of a while node can use a local
*/
public void inASTWhileNode(ASTWhileNode node) {
ASTCondition cond = node.get_Condition();
checkConditionalUses(cond, node);
}
/*
* The condition of a doWhile node can use a local
*/
public void inASTDoWhileNode(ASTDoWhileNode node) {
ASTCondition cond = node.get_Condition();
checkConditionalUses(cond, node);
}
}