I was talking to Scott about the same optimization, recognizing chains of
methods returning this and inlining them as a block.  I haven't looked into
what's involved, though, and promise not to until Thursday at least....



On Mon, Jun 15, 2009 at 9:11 PM, Brian Stoler <[email protected]> wrote:

>
> Hi gwtc,
>
> I was playing with using super-source to emulate some existing code
> that uses a builder pattern and make it efficient in GWT as a
> JavaScriptObject. I was hoping that the I could make the Builder just
> compile away, but that doesn't seem to be happening. I started
> debugging in JsInliner but started to get a bit lost. This is using
> svn r5557 on trunk FYI (very recent).
>
> What I am seeing is that if you use a chaining call pattern, the
> inliner doesn't realize some of the optimization it can do.
>
> Example usage code:
>
>    void example() {
>        MyData myData = MyData.Builder.create()
>            .setBar("a")
>            .setFoo("b").build();
>
>        Window.alert(myData.getBar());
>        Window.alert(myData.getFoo());
>    }
>
>
> Output I get (extraneous bits removed, PRETTY mode):
>
>    function init(){
>      var myData;
>      myData = $setFoo($setBar(new Object(), 'a'), 'b');
>      $wnd.alert(myData.bar);
>      $wnd.alert(myData.foo);
>    }
>
>    function $setBar(this$static, s){
>      this$static.bar = s;
>      return this$static;
>    }
>
>    function $setFoo(this$static, s){
>      this$static.foo = s;
>      return this$static;
>    }
>
>
> However, with this similar code:
>
>    void example2() {
>        MyData.Builder builder = MyData.Builder.create();
>        builder.setBar("a");
>        builder.setFoo("b");
>
>        MyData myData = builder.build();
>
>        Window.alert(myData.getBar());
>        Window.alert(myData.getFoo());
>    }
>
>
> The code compiles better (no setters):
>
>      builder = new Object();
>      builder.bar = 'a';
>      builder.foo = 'b';
>      myData = builder;
>      $wnd.alert(myData.bar);
>      $wnd.alert(myData.foo);
>
>
> The biggest issue seemed to be that the inliner didn't introduce a
> local variable for "new Object()", and because of that, it correctly
> concluded it couldn't keep copying that expression around. (I traced
> through it having issues due to "new" having side effects.) Even if I
> manually create a variable for the Builder at the outset, it still
> doesn't help. (FYI, I am using new Object() instead of {} to work
> around http://code.google.com/p/google-web-toolkit/issues/detail?id=3568)
>
> I was going to try to dig some more in to the inliner, but any ideas
> how to improve this?
>
> Will a later pass remove useless variable aliasing? (Seems like not
> from my other example?) If so, I was thinking it might work to have
> the inliner introduce a local all the time when it is trying to inline
> a non-void function. Smarter methods are of course possible, but I
> thought that might be worth a shot.
>
> Any other ideas welcome. MyData class attached below. I tried a
> variety of small tweaks to the MyData class and nothing made a
> difference.
>
> FYI, my eventual goal is:
>
> var myData = {bar:'a',foo:'b'};
>
> But that seems like an orthogonal optimization (and perhaps
> generically useful).
>
> Thanks for your interest, if you read this far,
> -brian
>
> PS: I am open to any changes to the MyData code below that a) preserve
> the JSO-ness and b) leave the external API the same.
>
>  public static interface MyData {
>    String getFoo();
>    String getBar();
>
>    public static final class Builder extends JavaScriptObject
> implements MyData {
>      protected Builder() {}
>
>      public static native Builder create() /*-{
>        return new Object();
>      }-*/;
>
>      public native String getFoo() /*-{
>        return this.foo;
>      }-*/;
>
>      public native String getBar() /*-{
>        return this.bar;
>      }-*/;
>
>      public Builder setFoo(String s) {
>        setFooImpl(s);
>        return this;
>      }
>
>      private native void setFooImpl(String s) /*-{
>        this.foo = s;
>      }-*/;
>
>      public Builder setBar(String s) {
>        setBarImpl(s);
>        return this;
>      }
>
>      private native void setBarImpl(String s) /*-{
>        this.bar = s;
>      }-*/;
>
>      public MyData build() {
>        return this;
>      }
>    }
>  }
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to