More method dispatch simplifications.

Change-Id: I11207f18e2b3f0e41c474751e1eaf9d33e7c2d42
Review-Link: https://gwt-review.googlesource.com/#/c/13572/
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
index 331388c..d01a2f0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
@@ -41,13 +41,25 @@
 public class JMethod extends JNode implements JMember, CanBeAbstract, CanBeNative {
 
   /**
-   * Indicates whether a JsProperty method is a getter or setter. Getters come with names like isX()
-   * and getX() while setters have signatures like setX(int a). If the property doesn't match these
-   * patterns, then it will marked as {@code UNDEFINED} to be later signaled as error in
-   * {@link com.google.gwt.dev.jjs.impl.JsInteropRestrictionChecker}.
+   * Indicates whether a method is a JsProperty accessor.
    */
   public enum JsPropertyAccessorType {
-    GETTER, SETTER, UNDEFINED;
+    /**
+     * Not a property accessor.
+     */
+    NONE,
+    /**
+     * A getter property accessor. Usually in the form of getX()/isX().
+     */
+    GETTER,
+    /**
+     * A setter property accessor. Usually in the form of setX(x).
+     */
+    SETTER,
+    /**
+     * A property accessor but doesn't match setter/getter patterns.
+     */
+    UNDEFINED,
   }
 
   public static final Comparator<JMethod> BY_SIGNATURE_COMPARATOR = new Comparator<JMethod>() {
@@ -60,7 +72,7 @@
   private String jsName;
   private boolean exported;
   private String jsNamespace;
-  private JsPropertyAccessorType jsPropertyType;
+  private JsPropertyAccessorType jsPropertyType = JsPropertyAccessorType.NONE;
   private Specialization specialization;
   private InliningMode inliningMode = InliningMode.NORMAL;
   private boolean preventDevirtualization = false;
@@ -193,23 +205,11 @@
         return overriddenMethod.jsPropertyType;
       }
     }
-    return null;
+    return JsPropertyAccessorType.NONE;
   }
 
   public boolean isJsPropertyAccessor() {
-    return jsPropertyType != null;
-  }
-
-  public boolean isOrOverridesJsPropertyAccessor() {
-    if (isJsPropertyAccessor()) {
-      return true;
-    }
-    for (JMethod overriddenMethod : getOverriddenMethods()) {
-      if (overriddenMethod.isJsPropertyAccessor()) {
-        return true;
-      }
-    }
-    return false;
+    return jsPropertyType != JsPropertyAccessorType.NONE;
   }
 
   private boolean isJsFunctionMethod() {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index d77975a..d24ae56 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -67,7 +67,6 @@
 import com.google.gwt.dev.jjs.ast.JLocalRef;
 import com.google.gwt.dev.jjs.ast.JMember;
 import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.JMethod.JsPropertyAccessorType;
 import com.google.gwt.dev.jjs.ast.JMethodBody;
 import com.google.gwt.dev.jjs.ast.JMethodCall;
 import com.google.gwt.dev.jjs.ast.JNameOf;
@@ -1323,24 +1322,20 @@
         result = dispatchToStatic(x, method, args);
       } else if (x.isStaticDispatchOnly()) {
         result = dispatchToSuper(x, method, args);
-      } else if (method.isOrOverridesJsPropertyAccessor()) {
-        result = dispatchToJsProperty(x, method, args);
-      } else if (method.isOrOverridesJsMethod()) {
-        result = dispatchToJsMethod(x, method, args);
       } else if (method.isOrOverridesJsFunctionMethod()) {
-        result = dispatchToJsFunction(x, args);
+        result = dispatchToJsFunction(args, x.getSourceInfo());
       } else {
-        // Dispatch polymorphically (normal case).
-        JsNameRef methodName = polymorphicNames.get(method).makeRef(x.getSourceInfo());
-        methodName.setQualifier((JsExpression) pop()); // instance
-        result = new JsInvocation(x.getSourceInfo(), methodName, args);
+        result = dispatchToInstanceMethod(method, args, x.getSourceInfo());
       }
 
       push(result);
     }
 
     private JsExpression dispatchToStatic(JMethodCall x, JMethod method, List<JsExpression> args) {
-      JsNameRef methodName = names.get(method).makeRef(x.getSourceInfo());
+      JsNameRef methodName =
+          method.isJsNative()
+              ? createJsQualifier(method.getQualifiedJsName(), x.getSourceInfo())
+              : names.get(method).makeRef(x.getSourceInfo());
       JsExpression result = new JsInvocation(x.getSourceInfo(), methodName, args);
       if (x.getInstance() != null) {
         JsExpression unnecessaryQualifier = pop();
@@ -1400,24 +1395,26 @@
       return jsInvocation;
     }
 
-    private JsExpression dispatchToJsProperty(
-        JMethodCall x, JMethod method, List<JsExpression> args) {
-      JsNameRef propertyReference = new JsNameRef(x.getSourceInfo(), method.getJsName());
-      propertyReference.setQualifier((JsExpression) pop()); // instance
-      if (method.getJsPropertyAccessorType() == JsPropertyAccessorType.SETTER) {
-        return createAssignment(propertyReference, args.get(0));
+    private JsExpression dispatchToJsFunction(List<JsExpression> args, SourceInfo sourceInfo) {
+      return new JsInvocation(sourceInfo, (JsExpression) pop(), args);
+    }
+
+    private JsExpression dispatchToInstanceMethod(
+        JMethod method, List<JsExpression> args, SourceInfo sourceInfo) {
+      JsNameRef reference =
+          method.isOrOverridesJsMethod()
+              ? new JsNameRef(sourceInfo, method.getJsName())
+              : polymorphicNames.get(method).makeRef(sourceInfo);
+      reference.setQualifier((JsExpression) pop()); // instance
+
+      switch (method.getJsPropertyAccessorType()) {
+        case SETTER:
+          return createAssignment(reference, args.get(0));
+        case GETTER:
+          return reference;
+        default:
+          return new JsInvocation(sourceInfo, reference, args);
       }
-      return propertyReference;
-    }
-
-    private JsExpression dispatchToJsMethod(JMethodCall x, JMethod method, List<JsExpression> args) {
-      JsNameRef methodName = new JsNameRef(x.getSourceInfo(), method.getJsName());
-      methodName.setQualifier((JsExpression) pop()); // instance
-      return new JsInvocation(x.getSourceInfo(), methodName, args);
-    }
-
-    private JsExpression dispatchToJsFunction(JMethodCall x, List<JsExpression> args) {
-      return new JsInvocation(x.getSourceInfo(), (JsExpression) pop(), args);
     }
 
     @Override