[gwt-contrib] [google-web-toolkit] r9362 committed - Partial fix for http://code.google.com/p/google-web-toolkit/issues/det...

2010-12-06 Thread codesite-noreply

Revision: 9362
Author: gwt.mirror...@gmail.com
Date: Mon Dec  6 14:51:53 2010
Log: Partial fix for  
http://code.google.com/p/google-web-toolkit/issues/detail?id=5707


Modify JsInliner to avoid propagating expressions incorrectly.

in EvaluationOrderVisitor, two changes were made. First of all, a clinit()  
call

is treated as violating order, the same as any other invocation.

Secondly, a JsNameRef that can be affected by side effects (a global,  
non-param,
non-local) that is visited when there are still expressions that need  
evaluation

first, is treated as violating order.

This fixes the showcase issue, but is still insufficient. Side-effect  
inducing
expressions (assignment, post/prefix increment ops) are still not handled.  
The

exemption of JsNameRefs that are locals is also insufficient, since a side
effect inducing parameter value may be aliased to the same object as this  
local.

After your review, I may remove it and just ban any non-param reference from
occuring while there are still params to be evaluated.

I tested this and it seems to fix the problem.

Review by: sco...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=9362

Modified:
 /trunk/dev/core/src/com/google/gwt/dev/js/JsInliner.java
 /trunk/dev/core/test/com/google/gwt/dev/js/JsInlinerTest.java

===
--- /trunk/dev/core/src/com/google/gwt/dev/js/JsInliner.java	Mon Sep 20  
06:50:17 2010
+++ /trunk/dev/core/src/com/google/gwt/dev/js/JsInliner.java	Mon Dec  6  
14:51:53 2010

@@ -611,12 +611,37 @@
 private boolean maintainsOrder = true;
 private final ListJsName toEvaluate;
 private final ListJsName unevaluated;
-
-public EvaluationOrderVisitor(ListJsName toEvaluate) {
+private final SetJsName paramsOrLocals = new HashSetJsName();
+
+public EvaluationOrderVisitor(ListJsName toEvaluate, JsFunction  
callee) {

   this.toEvaluate = toEvaluate;
   this.unevaluated = new ArrayListJsName(toEvaluate);
+  // collect params and locals from callee function
+  new JsVisitor() {
+@Override
+public void endVisit(JsParameter x, JsContextJsParameter ctx) {
+  paramsOrLocals.add(x.getName());
+}
+
+@Override
+public boolean visit(JsVar x, JsContextJsVar ctx) {
+  // record this before visiting initializer
+  paramsOrLocals.add(x.getName());
+  return true;
+}
+  }.accept(callee);
 }

+/**
+ * Referencing an array breaks order if there are unevaluated  
arguments.

+ */
+@Override
+public void endVisit(JsArrayAccess x, JsContextJsExpression ctx) {
+  if (unevaluated.size()  0) {
+maintainsOrder = false;
+  }
+}
+
 @Override
 public void endVisit(JsBinaryOperation x, JsContextJsExpression ctx)  
{

   JsBinaryOperator op = x.getOperator();
@@ -669,12 +694,7 @@
  */
 @Override
 public void endVisit(JsInvocation x, JsContextJsExpression ctx) {
-  /*
-   * The check for isExecuteOnce() is potentially incorrect here,  
however

-   * the original Java semantics of the clinit would have made the code
-   * incorrect anyway.
-   */
-  if ((isExecuteOnce(x) == null)  unevaluated.size()  0) {
+  if (unevaluated.size()  0) {
 maintainsOrder = false;
   }
 }
@@ -710,11 +730,35 @@
   return maintainsOrder  unevaluated.size() == 0;
 }

+/**
+ * Check to see if the evaluation of this JsName will break program  
order assumptions given

+ * the parameters left to be substituted.
+ *
+ * The cases are as follows:
+ * 1) JsName is a function parameter name which has side effects or is  
affected by side effects

+ * (hereafter called 'volatile'), so it will be in 'toEvaluate'
+ * 2) JsName is a function parameter which is not volatile (not in  
toEvaluate)

+ * 3) JsName is a reference to a global variable
+ * 4) JsName is a reference to a local variable
+ *
+ * A reference to a global while there are still parameters left to  
evaluate / substitute

+ * implies an order volation.
+ *
+ * A reference to a volatile parameter is ok if it if is the next  
parameter in sequence to
+ * be evaluated (beginning of unevaluated list). Else, it is either  
being evaluated out of
+ * order with respect to other parameters, or it is being evaluated  
more than once.

+ */
 private void checkName(JsName name) {
   if (!toEvaluate.contains(name)) {
+// if the name is a non-local/non-parameter (e.g. global) and  
there are params left to eval

+if (!paramsOrLocals.contains(name)  unevaluated.size()  0) {
+  maintainsOrder = false;
+}
+// else this may be a local, or all volatile params have already  
been evaluated, so it's ok.

 return;
   }

+  // either this param is being evaled twice, or out of order
   if (unevaluated.size() == 0 || 

Re: [gwt-contrib] [google-web-toolkit] r9362 committed - Partial fix for http://code.google.com/p/google-web-toolkit/issues/det...

2010-12-06 Thread Ray Cromwell
I forgot to edit the log description before I submitted, this isn't a
partial fix, it's a complete fix, although it is more conservative
than it needs to be (an inliner could substitute and propagate
expressions if it did better dataflow analysis). It can be made more
optimal later.

-Ray

On Mon, Dec 6, 2010 at 2:52 PM,  codesite-nore...@google.com wrote:
 Revision: 9362
 Author: gwt.mirror...@gmail.com
 Date: Mon Dec  6 14:51:53 2010
 Log: Partial fix for
 http://code.google.com/p/google-web-toolkit/issues/detail?id=5707

 Modify JsInliner to avoid propagating expressions incorrectly.

 in EvaluationOrderVisitor, two changes were made. First of all, a clinit()
 call
 is treated as violating order, the same as any other invocation.

 Secondly, a JsNameRef that can be affected by side effects (a global,
 non-param,
 non-local) that is visited when there are still expressions that need
 evaluation
 first, is treated as violating order.

 This fixes the showcase issue, but is still insufficient. Side-effect
 inducing
 expressions (assignment, post/prefix increment ops) are still not handled.
 The
 exemption of JsNameRefs that are locals is also insufficient, since a side
 effect inducing parameter value may be aliased to the same object as this
 local.
 After your review, I may remove it and just ban any non-param reference from
 occuring while there are still params to be evaluated.

 I tested this and it seems to fix the problem.

 Review by: sco...@google.com
 http://code.google.com/p/google-web-toolkit/source/detail?r=9362

 Modified:
  /trunk/dev/core/src/com/google/gwt/dev/js/JsInliner.java
  /trunk/dev/core/test/com/google/gwt/dev/js/JsInlinerTest.java

 ===
 --- /trunk/dev/core/src/com/google/gwt/dev/js/JsInliner.java    Mon Sep 20
 06:50:17 2010
 +++ /trunk/dev/core/src/com/google/gwt/dev/js/JsInliner.java    Mon Dec  6
 14:51:53 2010
 @@ -611,12 +611,37 @@
     private boolean maintainsOrder = true;
     private final ListJsName toEvaluate;
     private final ListJsName unevaluated;
 -
 -    public EvaluationOrderVisitor(ListJsName toEvaluate) {
 +    private final SetJsName paramsOrLocals = new HashSetJsName();
 +
 +    public EvaluationOrderVisitor(ListJsName toEvaluate, JsFunction
 callee) {
       this.toEvaluate = toEvaluate;
       this.unevaluated = new ArrayListJsName(toEvaluate);
 +      // collect params and locals from callee function
 +      new JsVisitor() {
 +       �...@override
 +        public void endVisit(JsParameter x, JsContextJsParameter ctx) {
 +          paramsOrLocals.add(x.getName());
 +        }
 +
 +       �...@override
 +        public boolean visit(JsVar x, JsContextJsVar ctx) {
 +          // record this before visiting initializer
 +          paramsOrLocals.add(x.getName());
 +          return true;
 +        }
 +      }.accept(callee);
     }

 +    /**
 +     * Referencing an array breaks order if there are unevaluated
 arguments.
 +     */
 +   �...@override
 +    public void endVisit(JsArrayAccess x, JsContextJsExpression ctx) {
 +      if (unevaluated.size()  0) {
 +        maintainsOrder = false;
 +      }
 +    }
 +
     @Override
     public void endVisit(JsBinaryOperation x, JsContextJsExpression ctx) {
       JsBinaryOperator op = x.getOperator();
 @@ -669,12 +694,7 @@
      */
     @Override
     public void endVisit(JsInvocation x, JsContextJsExpression ctx) {
 -      /*
 -       * The check for isExecuteOnce() is potentially incorrect here,
 however
 -       * the original Java semantics of the clinit would have made the code
 -       * incorrect anyway.
 -       */
 -      if ((isExecuteOnce(x) == null)  unevaluated.size()  0) {
 +      if (unevaluated.size()  0) {
         maintainsOrder = false;
       }
     }
 @@ -710,11 +730,35 @@
       return maintainsOrder  unevaluated.size() == 0;
     }

 +    /**
 +     * Check to see if the evaluation of this JsName will break program
 order assumptions given
 +     * the parameters left to be substituted.
 +     *
 +     * The cases are as follows:
 +     * 1) JsName is a function parameter name which has side effects or is
 affected by side effects
 +     * (hereafter called 'volatile'), so it will be in 'toEvaluate'
 +     * 2) JsName is a function parameter which is not volatile (not in
 toEvaluate)
 +     * 3) JsName is a reference to a global variable
 +     * 4) JsName is a reference to a local variable
 +     *
 +     * A reference to a global while there are still parameters left to
 evaluate / substitute
 +     * implies an order volation.
 +     *
 +     * A reference to a volatile parameter is ok if it if is the next
 parameter in sequence to
 +     * be evaluated (beginning of unevaluated list). Else, it is either
 being evaluated out of
 +     * order with respect to other parameters, or it is being evaluated
 more than once.
 +     */
     private void checkName(JsName name) {
       if (!toEvaluate.contains(name)) {
 +        // if the name is a