[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ClassConstant support




I whipped this up today because I needed it, and thought it might be useful to others.
The attached code represents class constants (i.e. Class.forName("foo")) and
performs constant propagation and folding of, for instance,


Class.forName("foo") == Class.forName("foo")

There were a few simple changes necessary to get type checking to work, along with
modifications to jimple.toolkits.scalar.Evaluator to treat them as constants.


In my application, this eliminates all instances discovered as ClassConstants,
so I think there might be other changes needed to fully support this, particularly
when writing out bytecode. In particular, I think this change to ConstantPropagatorAndFolder
causes problems, because it propagates string and class constants into cases where they are
illegal, since they are references to objects? Perhaps someone from the soot group knows
the right way to do this?


if (defsOfUse.size() == 1) {
DefinitionStmt defStmt =
(DefinitionStmt) defsOfUse.get(0);
- if (defStmt.getRightOp() instanceof Constant) {
+ if (defStmt.getRightOp() instanceof NumericConstant) {
if (useBox.canContainValue(defStmt.getRightOp())) {
useBox.setValue(defStmt.getRightOp());
numPropagated++;


Steve

Attachment: ClassConstant.java
Description: Binary data

diff -aur vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/scalar/ConstantPropagatorAndFolder.java soot/jimple/toolkits/scalar/ConstantPropagatorAndFolder.java
--- vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/scalar/ConstantPropagatorAndFolder.java	2003-07-25 15:02:28.891675800 -0700
+++ soot/jimple/toolkits/scalar/ConstantPropagatorAndFolder.java	2003-11-06 16:47:12.661607900 -0800
@@ -79,7 +79,7 @@
                     if (defsOfUse.size() == 1) {
                         DefinitionStmt defStmt =
                             (DefinitionStmt) defsOfUse.get(0);
-                        if (defStmt.getRightOp() instanceof NumericConstant) {
+                        if (defStmt.getRightOp() instanceof Constant) {
                             if (useBox.canContainValue(defStmt.getRightOp())) {
                                 useBox.setValue(defStmt.getRightOp());
                                 numPropagated++;


diff -aur vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/scalar/Evaluator.java soot/jimple/toolkits/scalar/Evaluator.java
--- vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/scalar/Evaluator.java	2003-07-25 15:02:28.511117200 -0700
+++ soot/jimple/toolkits/scalar/Evaluator.java	2003-11-06 16:53:05.199077300 -0800
@@ -37,7 +37,10 @@
 public class Evaluator {
 
     public static boolean isValueConstantValued(Value op) {
-
+        
+        if (op instanceof ClassConstant) {
+            return true;
+        } else
         if (op instanceof Constant)
             return true;
         else if ((op instanceof UnopExpr)) {
@@ -68,6 +71,15 @@
             if (isValueConstantValued(((BinopExpr)op).getOp1()) &&
                 isValueConstantValued(((BinopExpr)op).getOp2()))
                 return true;
+        } else if (op instanceof StaticInvokeExpr) {
+            StaticInvokeExpr expr = (StaticInvokeExpr)op;
+            SootMethod method = (SootMethod)expr.getMethod();
+            if(method.getSignature().equals(
+                       "<java.lang.Class: java.lang.Class forName(java.lang.String)>")) {
+                if (isValueConstantValued(expr.getArg(0))) {
+                    return true;
+                }
+            }
         }
         return false;
     } // isValueConstantValued
@@ -102,7 +114,18 @@
                 return ((NumericConstant)c1).remainder((NumericConstant)c2);
             else if (op instanceof EqExpr || op instanceof NeExpr)
             {
-                if (c1 instanceof NumericConstant)
+                if (c1 instanceof ClassConstant)
+                {
+                    boolean equality = ((ClassConstant)c1).equals
+                        ((ClassConstant)c2);
+
+                    boolean truth = (op instanceof EqExpr) ? equality :
+                        !equality;
+
+                    // Yeah, this variable name sucks, but I couldn't resist.
+                    IntConstant beauty = IntConstant.v(truth ? 1 : 0);
+                    return beauty;
+                } else if (c1 instanceof NumericConstant)
                 {
                     if (op instanceof EqExpr)
                         return ((NumericConstant)c1).equalEqual
@@ -171,6 +194,15 @@
             }
             else
                 throw new RuntimeException("unknown binop: " + op);
+        } else if (op instanceof StaticInvokeExpr) {
+            StaticInvokeExpr expr = (StaticInvokeExpr)op;
+            SootMethod method = (SootMethod)expr.getMethod();
+            if(method.getSignature().equals(
+                       "<java.lang.Class: java.lang.Class forName(java.lang.String)>")) {
+                StringConstant name = 
+                    (StringConstant)getConstantValueOf(expr.getArg(0));
+                return ClassConstant.v(name.toString());
+            }
         }
 
         throw new RuntimeException("couldn't getConstantValueOf of: " + op);

diff -aur vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/typing/ConstraintChecker.java soot/jimple/toolkits/typing/ConstraintChecker.java
--- vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/typing/ConstraintChecker.java	2003-07-25 15:02:30.554116000 -0700
+++ soot/jimple/toolkits/typing/ConstraintChecker.java	2003-11-06 16:22:10.867896300 -0800
@@ -425,6 +425,13 @@
 	    error("Type Error(26)");
 	  }
       }
+    else if(r instanceof ClassConstant)
+      {
+	if(!left.hasDescendantOrSelf(hierarchy.typeNode(RefType.v("java.lang.Class"))))
+	  {
+	    error("Type Error(27a)");
+	  }
+      }
     else if(r instanceof BinopExpr)
       {
 	//******** BINOP EXPR ********
@@ -466,6 +473,11 @@
 	  {
 	    lop = hierarchy.typeNode(RefType.v("java.lang.String"));
 	  }
+        else if(lv instanceof ClassConstant)
+            {
+                lop = hierarchy.typeNode(RefType.v("java.lang.Class"));
+
+            }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
@@ -500,6 +512,10 @@
 	  {
 	    rop = hierarchy.typeNode(RefType.v("java.lang.String"));
 	  }
+        else if(rv instanceof ClassConstant)
+            {
+                rop = hierarchy.typeNode(RefType.v("java.lang.Class"));
+            }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
@@ -894,6 +910,10 @@
       {
 	lop = hierarchy.typeNode(RefType.v("java.lang.String"));
       }
+    else if(lv instanceof ClassConstant)
+        {
+	    lop = hierarchy.typeNode(RefType.v("java.lang.Class"));
+        }
     else
       {
 	throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
@@ -928,6 +948,10 @@
       {
 	rop = hierarchy.typeNode(RefType.v("java.lang.String"));
       }
+    else if(rv instanceof ClassConstant)
+        {
+	    rop = hierarchy.typeNode(RefType.v("java.lang.Class"));
+        }
     else
       {
 	throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());

diff -aur vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/typing/ConstraintCollector.java soot/jimple/toolkits/typing/ConstraintCollector.java
--- vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/typing/ConstraintCollector.java	2003-07-25 15:02:30.383866100 -0700
+++ soot/jimple/toolkits/typing/ConstraintCollector.java	2003-11-06 16:16:53.049678100 -0800
@@ -285,6 +285,10 @@
       {
 	right = resolver.typeVariable(RefType.v("java.lang.String"));
       }
+    else if(r instanceof ClassConstant)
+        {
+	    right = resolver.typeVariable(RefType.v("java.lang.Class"));
+        }
     else if(r instanceof BinopExpr)
       {
 	//******** BINOP EXPR ********
@@ -326,6 +330,10 @@
 	  {
 	    lop = resolver.typeVariable(RefType.v("java.lang.String"));
 	  }
+	else if(lv instanceof ClassConstant)
+	  {
+	    lop = resolver.typeVariable(RefType.v("java.lang.Class"));
+	  }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
@@ -360,6 +368,10 @@
 	  {
 	    rop = resolver.typeVariable(RefType.v("java.lang.String"));
 	  }
+	else if(rv instanceof ClassConstant)
+	  {
+	    rop = resolver.typeVariable(RefType.v("java.lang.Class"));
+	  }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
@@ -675,6 +687,10 @@
 	  {
 	    lop = resolver.typeVariable(RefType.v("java.lang.String"));
 	  }
+	else if(lv instanceof ClassConstant)
+	  {
+	    lop = resolver.typeVariable(RefType.v("java.lang.Class"));
+	  }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
@@ -709,6 +725,10 @@
 	  {
 	    rop = resolver.typeVariable(RefType.v("java.lang.String"));
 	  }
+	else if(rv instanceof ClassConstant)
+	  {
+	    rop = resolver.typeVariable(RefType.v("java.lang.Class"));
+	  }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());

diff -aur vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/typing/integer/ConstraintChecker.java soot/jimple/toolkits/typing/integer/ConstraintChecker.java
--- vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/typing/integer/ConstraintChecker.java	2003-07-25 15:02:30.453969000 -0700
+++ soot/jimple/toolkits/typing/integer/ConstraintChecker.java	2003-11-06 16:31:25.202852700 -0800
@@ -369,6 +369,9 @@
     else if(r instanceof StringConstant)
       {
       }
+    else if(r instanceof ClassConstant)
+      {
+      }
     else if(r instanceof BinopExpr)
       {
 	//******** BINOP EXPR ********
@@ -441,6 +444,9 @@
 	else if(lv instanceof StringConstant)
 	  {
 	  }
+    else if(lv instanceof ClassConstant)
+      {
+      }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
@@ -506,6 +512,9 @@
 	else if(rv instanceof StringConstant)
 	  {
 	  }
+    else if(rv instanceof ClassConstant)
+      {
+      }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
@@ -998,6 +1007,9 @@
     else if(lv instanceof StringConstant)
       {
       }
+    else if(lv instanceof ClassConstant)
+      {
+      }
     else
       {
 	throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
@@ -1063,6 +1075,9 @@
     else if(rv instanceof StringConstant)
       {
       }
+    else if(rv instanceof ClassConstant)
+      {
+      }
     else
       {
 	throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());

diff -aur vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/typing/integer/ConstraintCollector.java soot/jimple/toolkits/typing/integer/ConstraintCollector.java
--- vendors/soot/2.0.1/soot/src/soot/jimple/toolkits/typing/integer/ConstraintCollector.java	2003-07-25 15:02:30.413910200 -0700
+++ soot/jimple/toolkits/typing/integer/ConstraintCollector.java	2003-11-06 16:30:49.700741200 -0800
@@ -306,6 +306,9 @@
     else if(r instanceof StringConstant)
       {
       }
+    else if(r instanceof ClassConstant)
+      {
+      }
     else if(r instanceof BinopExpr)
       {
 	//******** BINOP EXPR ********
@@ -378,6 +381,9 @@
 	else if(lv instanceof StringConstant)
 	  {
 	  }
+    else if(lv instanceof ClassConstant)
+      {
+      }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
@@ -443,6 +449,9 @@
 	else if(rv instanceof StringConstant)
 	  {
 	  }
+    else if(rv instanceof ClassConstant)
+      {
+      }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
@@ -824,11 +833,14 @@
 	  {
 	  }
 	else if(lv instanceof StringConstant)
-	  {
-	  }
+            {
+            }
+        else if(lv instanceof ClassConstant)
+            {
+            }
 	else
-	  {
-	    throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
+            {
+                throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
 	  }
 	
 	//******** RIGHT ********
@@ -891,6 +903,9 @@
 	else if(rv instanceof StringConstant)
 	  {
 	  }
+    else if(rv instanceof ClassConstant)
+      {
+      }
 	else
 	  {
 	    throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());