Added the ability to staticify a method call based on the concrete type of the qualifier, even in cases where the target method is not globally final.
Review by: knorton
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2249 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethodCall.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethodCall.java
index 6ae7b88..a02025c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethodCall.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethodCall.java
@@ -25,6 +25,7 @@
public class JMethodCall extends JExpression {
private ArrayList<JExpression> args = new ArrayList<JExpression>();
+ private boolean cannotBePolymorphic = false;
private JExpression instance;
private final JMethod method;
private final JType overrideReturnType;
@@ -41,6 +42,15 @@
this.overrideReturnType = null;
}
+ public JMethodCall(JProgram program, SourceInfo info, JExpression instance,
+ JMethod method, boolean staticDispatchOnly) {
+ super(program, info);
+ this.instance = instance;
+ this.method = method;
+ this.staticDispatchOnly = staticDispatchOnly;
+ this.overrideReturnType = null;
+ }
+
/**
* Create a method call whose type is overridden to the specified type,
* ignoring the return type of the target method. This constructor is used
@@ -61,17 +71,9 @@
this.overrideReturnType = overrideReturnType;
}
- public JMethodCall(JProgram program, SourceInfo info, JExpression instance,
- JMethod method, boolean staticDispatchOnly) {
- super(program, info);
- this.instance = instance;
- this.method = method;
- this.staticDispatchOnly = staticDispatchOnly;
- this.overrideReturnType = null;
- }
-
public boolean canBePolymorphic() {
- return !staticDispatchOnly && !method.isFinal() && !method.isStatic();
+ return !cannotBePolymorphic && !staticDispatchOnly && !method.isFinal()
+ && !method.isStatic();
}
public ArrayList<JExpression> getArgs() {
@@ -104,6 +106,10 @@
return staticDispatchOnly;
}
+ public void setCannotBePolymorphic() {
+ this.cannotBePolymorphic = true;
+ }
+
public void setStaticDispatchOnly() {
this.staticDispatchOnly = true;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
index 4d815eb..2f81641 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
@@ -182,6 +182,9 @@
public boolean visit(JMethodCall x, Context ctx) {
JMethodCall newMethodCall = new JMethodCall(program, x.getSourceInfo(),
cloneExpression(x.getInstance()), x.getTarget());
+ if (!x.canBePolymorphic()) {
+ newMethodCall.setCannotBePolymorphic();
+ }
for (JExpression arg : x.getArgs()) {
newMethodCall.getArgs().add(cloneExpression(arg));
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 b58a5ce..bd60b0d 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
@@ -141,6 +141,9 @@
JMethodCall newCall = new JMethodCall(program, x.getSourceInfo(),
x.getInstance(), method);
+ if (!x.canBePolymorphic()) {
+ newCall.setCannotBePolymorphic();
+ }
ArrayList<JExpression> args = x.getArgs();
ArrayList<JParameter> originalParams = methodToOriginalParamsMap.get(method);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
index ef6f251..7707f0b 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
@@ -567,13 +567,33 @@
*/
@Override
public void endVisit(JMethodCall x, Context ctx) {
- JMethod concreteMethod = getSingleConcreteMethod(x.getTarget());
+ JMethod target = x.getTarget();
+ JMethod concreteMethod = getSingleConcreteMethod(target);
if (concreteMethod != null) {
JMethodCall newCall = new JMethodCall(program, x.getSourceInfo(),
x.getInstance(), concreteMethod);
newCall.getArgs().addAll(x.getArgs());
-
ctx.replaceMe(newCall);
+ target = concreteMethod;
+ x = newCall;
+ }
+
+ if (x.canBePolymorphic()) {
+ // See if we can remove virtualization from this call.
+ JExpression instance = x.getInstance();
+ assert (instance != null);
+ JReferenceType instanceType = (JReferenceType) instance.getType();
+ Set<JMethod> myOverriders = overriders.get(target);
+ for (JMethod override : myOverriders) {
+ JReferenceType overrideType = override.getEnclosingType();
+ if (program.typeOracle.canTheoreticallyCast(instanceType, overrideType)) {
+ // This call is truly polymorphic.
+ // TODO: composite types! :)
+ return;
+ }
+ }
+ x.setCannotBePolymorphic();
+ didChange = true;
}
}