Rescue volatile fields that have a live assignment to them.  This is helpful
in test cases; you can now keep an expression live by assigning its result
to a volatile field.

Review by: scottb

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2985 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
index 6fb1a31..6ceec64 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
@@ -111,6 +111,7 @@
       }
     }
 
+    @Override
     public void endVisit(JDeclarationStatement x, Context ctx) {
       // The variable may have been pruned.
       if (!referencedNonTypes.contains(x.getVariableRef().getTarget())) {
@@ -485,8 +486,10 @@
         // Don't rescue variables that are merely assigned to and never read
         boolean doSkip = false;
         JExpression lhs = x.getLhs();
-        if (lhs.hasSideEffects()) {
-          // cannot skip
+        if (lhs.hasSideEffects() || isVolatileField(lhs)) {
+          // If the lhs has side effects, skipping it would lose the side effect.
+          // If the lhs is volatile, also keep it.  This behavior provides a useful
+          // idiom for test cases to prevent code from being pruned.
         } else if (lhs instanceof JLocalRef) {
           // locals are ok to skip
           doSkip = true;
@@ -554,6 +557,7 @@
       return false;
     }
 
+    @Override
     public boolean visit(JDeclarationStatement x, Context ctx) {
       /*
        * A declaration by itself doesn't rescue a local (even if it has an
@@ -750,6 +754,17 @@
       return true;
     }
 
+    private boolean isVolatileField(JExpression x) {
+      if (x instanceof JFieldRef) {
+        JFieldRef xFieldRef = (JFieldRef) x;
+        if (xFieldRef.getField().isVolatile()) {
+          return true;
+        }
+      }
+
+      return false;
+    }
+
     /**
      * Subclasses of JavaScriptObject are never instantiated directly. They are
      * created "magically" when a JSNI method passes a reference to an existing