Revision: 10190
Author: sco...@google.com
Date: Tue May 17 05:22:26 2011
Log: Salvage useful bits from overrides work.
http://gwt-code-reviews.appspot.com/1436801/
Review by: jbrosenb...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=10190
Deleted:
/trunk/dev/core/src/com/google/gwt/core/ext/soyc/HasOverrides.java
Modified:
/trunk/dev/core/src/com/google/gwt/core/ext/soyc/ClassMember.java
/trunk/dev/core/src/com/google/gwt/core/ext/soyc/MethodMember.java
/trunk/dev/core/src/com/google/gwt/core/ext/soyc/impl/StandardMethodMember.java
/trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
/trunk/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java
=======================================
--- /trunk/dev/core/src/com/google/gwt/core/ext/soyc/HasOverrides.java Thu
May 5 06:03:58 2011
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may
not
- * use this file except in compliance with the License. You may obtain a
copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
under
- * the License.
- */
-/**
- *
- */
-package com.google.gwt.core.ext.soyc;
-
-import java.util.SortedSet;
-
-/**
- * A tag interface for Members to indicate that they override or extend
another
- * Member.
- *
- * @param <T> the type of Member that is overridden or extended
- */
-public interface HasOverrides<T extends Member> {
- /**
- * Returns the complete set of overridden members. For example, if
- * <code>C</code> extends <code>B</code> extends <code>A</code>, then
- * <code>C</code> would return the set <code>[A, B]</code>.
- */
- SortedSet<T> getOverrides();
-}
=======================================
--- /trunk/dev/core/src/com/google/gwt/core/ext/soyc/ClassMember.java Thu
May 5 06:03:58 2011
+++ /trunk/dev/core/src/com/google/gwt/core/ext/soyc/ClassMember.java Tue
May 17 05:22:26 2011
@@ -24,8 +24,8 @@
* {@link #getMethods()} may be incomplete when compared to the original
Java
* type.
*/
-public interface ClassMember extends HasDependencies,
- HasOverrides<ClassMember>, Member {
+public interface ClassMember extends HasDependencies, Member {
+
/**
* Returns the fields of the ClassMember that have been retained in the
* compiled output.
=======================================
--- /trunk/dev/core/src/com/google/gwt/core/ext/soyc/MethodMember.java Thu
May 5 06:03:58 2011
+++ /trunk/dev/core/src/com/google/gwt/core/ext/soyc/MethodMember.java Tue
May 17 05:22:26 2011
@@ -12,15 +12,11 @@
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
under
* the License.
- */
-/**
- *
*/
package com.google.gwt.core.ext.soyc;
/**
* Represents compiled JS code derived from a Java method.
*/
-public interface MethodMember extends HasDependencies, HasEnclosing,
- HasOverrides<MethodMember>, Member {
-}
+public interface MethodMember extends HasDependencies, HasEnclosing,
Member {
+}
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/ext/soyc/impl/StandardMethodMember.java
Thu May 5 06:03:58 2011
+++
/trunk/dev/core/src/com/google/gwt/core/ext/soyc/impl/StandardMethodMember.java
Tue May 17 05:22:26 2011
@@ -16,15 +16,10 @@
package com.google.gwt.core.ext.soyc.impl;
import com.google.gwt.core.ext.soyc.ClassMember;
-import com.google.gwt.core.ext.soyc.Member;
import com.google.gwt.core.ext.soyc.MethodMember;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JType;
-import java.util.Collections;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
/**
* An implementation of MethodMember.
*/
@@ -32,7 +27,6 @@
implements MethodMember {
private final ClassMember enclosing;
private final String sourceName;
- private final SortedSet<MethodMember> overridesView;
/**
* Constructed by {@link MemberFactory#get(JMethod)}.
@@ -49,22 +43,11 @@
sb.append(")");
sb.append(method.getOriginalReturnType().getJsniSignatureName());
this.sourceName = sb.toString();
-
- SortedSet<MethodMember> overrides = new TreeSet<MethodMember>(
- Member.SOURCE_NAME_COMPARATOR);
- for (JMethod override : method.getOverrides()) {
- overrides.add(factory.get(override));
- }
- overridesView = Collections.unmodifiableSortedSet(overrides);
}
public ClassMember getEnclosing() {
return enclosing;
}
-
- public SortedSet<MethodMember> getOverrides() {
- return overridesView;
- }
@Override
public String getSourceName() {
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java Thu
May 5 06:03:58 2011
+++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java Tue May
17 05:22:26 2011
@@ -17,10 +17,12 @@
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.impl.HasNameSort;
+import com.google.gwt.dev.util.collect.HashMap;
import com.google.gwt.dev.util.collect.IdentityHashMap;
import com.google.gwt.dev.util.collect.IdentityHashSet;
import com.google.gwt.dev.util.collect.IdentitySets;
import com.google.gwt.dev.util.collect.Lists;
+import com.google.gwt.dev.util.collect.Maps;
import java.io.Serializable;
import java.util.ArrayList;
@@ -187,6 +189,8 @@
}
return true;
}
+
+ private JDeclaredType baseArrayType;
/**
* A map of all interfaces to the set of classes that could theoretically
@@ -287,6 +291,12 @@
private final Map<JMethod, Map<JClassType, Set<JMethod>>>
virtualUpRefMap =
new IdentityHashMap<JMethod, Map<JClassType, Set<JMethod>>>();
+ /**
+ * An index of all polymorphic methods for each class.
+ */
+ private final Map<JClassType, Map<String, JMethod>> polyClassMethodMap =
+ new IdentityHashMap<JClassType, Map<String, JMethod>>();
+
public JTypeOracle(JProgram program) {
this.program = program;
}
@@ -417,7 +427,7 @@
}
}
- if (qType == javaIoSerializable || qType == javaLangCloneable) {
+ if (qType == javaIoSerializable || qType == javaLangCloneable ||
qType == baseArrayType) {
return true;
}
} else if (type instanceof JClassType) {
@@ -455,6 +465,7 @@
}
public void computeBeforeAST() {
+ baseArrayType = program.getIndexedType("Array");
javaLangObject = program.getTypeJavaLangObject();
javaIoSerializable =
program.getFromTypeMap(Serializable.class.getName());
javaLangCloneable = program.getFromTypeMap(Cloneable.class.getName());
@@ -526,44 +537,12 @@
}
}
}
-
- public Set<JMethod> getAllOverrides(JMethod method) {
- return getAllOverrides(method, instantiatedTypes);
- }
/**
* References to any methods which this method implementation might
override
- * or implement in any instantiable class.
- */
- public Set<JMethod> getAllOverrides(JMethod method, Set<JReferenceType>
instantiatedTypes) {
- Set<JMethod> results = new IdentityHashSet<JMethod>();
- getAllRealOverrides(method, results);
- getAllVirtualOverrides(method, instantiatedTypes, results);
- return results;
- }
-
- /**
- * References to any methods which this method directly overrides. This
should
- * be an EXHAUSTIVE list, that is, if C overrides B overrides A, then C's
- * overrides list will contain both A and B.
- */
- public Set<JMethod> getAllRealOverrides(JMethod method) {
- Set<JMethod> results = new IdentityHashSet<JMethod>();
- getAllRealOverrides(method, results);
- return results;
- }
-
- public Set<JClassType> getAllSubClasses(JReferenceType type) {
- return subClassMap.get(type);
- }
-
- /**
- * Returns the set of methods the given method virtually overrides. A
virtual
- * override is an association between a concrete method and an unrelated
- * interface method with the exact same name and signature. The
association
- * occurs if and only if some subclass extends the concrete method's
- * containing class and implements the interface method's containing
- * interface. Example:
+ * or implement in any instantiable class, including strange cases where
there
+ * is no direct relationship between the methods except in a subclass
that
+ * inherits one and implements the other. Example:
*
* <pre>
* interface IFoo {
@@ -579,11 +558,16 @@
* In this case, <code>Unrelated.foo()</code> virtually implements
* <code>IFoo.foo()</code> in subclass <code>Foo</code>.
*/
- public Set<JMethod> getAllVirtualOverrides(JMethod method) {
+ public Set<JMethod> getAllOverrides(JMethod method) {
Set<JMethod> results = new IdentityHashSet<JMethod>();
- getAllVirtualOverrides(method, instantiatedTypes, results);
+ getAllRealOverrides(method, results);
+ getAllVirtualOverrides(method, results);
return results;
}
+
+ public JMethod getPolyMethod(JClassType type, String signature) {
+ return getOrCreatePolyMap(type).get(signature);
+ }
public JClassType getSingleJsoImpl(JReferenceType maybeSingleJsoIntf) {
return jsoSingleImpls.get(maybeSingleJsoIntf.getUnderlyingType());
@@ -606,8 +590,43 @@
}
}
+ /**
+ * Determine whether a type is instantiated.
+ */
+ public boolean isInstantiatedType(JDeclaredType type) {
+ return instantiatedTypes == null || instantiatedTypes.contains(type);
+ }
+
+ /**
+ * Determine whether a type is instantiated.
+ */
public boolean isInstantiatedType(JReferenceType type) {
- return isInstantiatedType(type, instantiatedTypes);
+ type = type.getUnderlyingType();
+ if (instantiatedTypes == null || instantiatedTypes.contains(type)) {
+ return true;
+ }
+
+ if (type.isExternal()) {
+ // TODO(tobyr) I don't know under what situations it is safe to
assume
+ // that an external type won't be instantiated. For example, if we
+ // assumed that an external exception weren't instantiated, because
we
+ // didn't see it constructed in our code, dead code elimination would
+ // incorrectly elide any catch blocks for that exception.
+ //
+ // We should see how this effects optimization and if we can limit
its
+ // impact if necessary.
+ return true;
+ }
+
+ if (type instanceof JNullType) {
+ return true;
+ } else if (type instanceof JArrayType) {
+ JArrayType arrayType = (JArrayType) type;
+ if (arrayType.getLeafType() instanceof JNullType) {
+ return true;
+ }
+ }
+ return false;
}
public boolean isSameOrSuper(JClassType type, JClassType qType) {
@@ -665,8 +684,8 @@
}
public void setInstantiatedTypes(Set<JReferenceType> instantiatedTypes) {
- this.instantiatedTypes = new IdentityHashSet<JReferenceType>();
- this.instantiatedTypes.addAll(instantiatedTypes);
+ this.instantiatedTypes = instantiatedTypes;
+ polyClassMethodMap.keySet().retainAll(instantiatedTypes);
}
private <K, V> void add(Map<K, Set<V>> map, K key, V value) {
@@ -891,13 +910,12 @@
}
}
- private void getAllVirtualOverrides(JMethod method, Set<JReferenceType>
instantiatedTypes,
- Set<JMethod> results) {
+ private void getAllVirtualOverrides(JMethod method, Set<JMethod>
results) {
Map<JClassType, Set<JMethod>> overrideMap =
virtualUpRefMap.get(method);
if (overrideMap != null) {
for (Map.Entry<JClassType, Set<JMethod>> entry :
overrideMap.entrySet()) {
JClassType classType = entry.getKey();
- if (isInstantiatedType(classType, instantiatedTypes)) {
+ if (isInstantiatedType(classType)) {
results.addAll(entry.getValue());
}
}
@@ -921,6 +939,27 @@
}
return map2;
}
+
+ private Map<String, JMethod> getOrCreatePolyMap(JClassType type) {
+ Map<String, JMethod> polyMap = polyClassMethodMap.get(type);
+ if (polyMap == null) {
+ JClassType superClass = type.getSuperClass();
+ if (superClass == null) {
+ polyMap = new HashMap<String, JMethod>();
+ } else {
+ Map<String, JMethod> superPolyMap =
getOrCreatePolyMap(type.getSuperClass());
+ polyMap = new HashMap<String, JMethod>(superPolyMap);
+ }
+ for (JMethod method : type.getMethods()) {
+ if (method.canBePolymorphic()) {
+ polyMap.put(method.getSignature(), method);
+ }
+ }
+ polyMap = Maps.normalize(polyMap);
+ polyClassMethodMap.put(type, polyMap);
+ }
+ return polyMap;
+ }
/**
* Returns true if type implements the interface represented by qType,
either
@@ -929,48 +968,6 @@
private boolean implementsInterface(JClassType type, JInterfaceType
qType) {
return get(implementsMap, type).contains(qType);
}
-
- /**
- * Determine whether a type is instantiated, given an assumed list of
- * instantiated types.
- *
- * @param type any type
- * @param instantiatedTypes a set of types assumed to be instantiated. If
- * <code>null</code>, then there are no assumptions about which
types
- * are instantiated.
- * @return whether the type is instantiated
- */
- private boolean isInstantiatedType(JReferenceType type,
Set<JReferenceType> instantiatedTypes) {
- type = type.getUnderlyingType();
-
- if (type.isExternal()) {
- // TODO(tobyr) I don't know under what situations it is safe to
assume
- // that an external type won't be instantiated. For example, if we
- // assumed that an external exception weren't instantiated, because
we
- // didn't see it constructed in our code, dead code elimination would
- // incorrectly elide any catch blocks for that exception.
- //
- // We should see how this effects optimization and if we can limit
its
- // impact if necessary.
- return true;
- }
-
- if (instantiatedTypes == null) {
- return true;
- }
-
- if (type instanceof JNullType) {
- return true;
- }
-
- if (type instanceof JArrayType) {
- JArrayType arrayType = (JArrayType) type;
- if (arrayType.getLeafType() instanceof JNullType) {
- return true;
- }
- }
- return instantiatedTypes.contains(type);
- }
/**
* Record the all of my super classes (and myself as a subclass of them).
=======================================
---
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
Tue May 10 05:59:20 2011
+++
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
Tue May 17 05:22:26 2011
@@ -146,6 +146,7 @@
import com.google.gwt.dev.util.collect.IdentityHashSet;
import com.google.gwt.dev.util.collect.Maps;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
@@ -198,7 +199,7 @@
recordSymbol(x, jsName);
} else {
JsName jsName;
- if (belongsToSpecialObfuscatedType(x)) {
+ if (specialObfuscatedFields.containsKey(x)) {
jsName = peek().declareName(mangleNameSpecialObfuscate(x));
jsName.setObfuscatable(false);
} else {
@@ -319,13 +320,14 @@
String name = x.getName();
if (x.needsVtable()) {
if (polymorphicNames.get(x) == null) {
- String mangleName = mangleNameForPoly(x);
JsName polyName;
- if (belongsToSpecialObfuscatedType(x)) {
+ if (x.isPrivate()) {
+ polyName =
interfaceScope.declareName(mangleNameForPrivatePoly(x), name);
+ } else if
(specialObfuscatedMethodSigs.containsKey(x.getSignature())) {
polyName =
interfaceScope.declareName(mangleNameSpecialObfuscate(x));
polyName.setObfuscatable(false);
} else {
- polyName = interfaceScope.declareName(mangleName, name);
+ polyName = interfaceScope.declareName(mangleNameForPoly(x),
name);
}
polymorphicNames.put(x, polyName);
}
@@ -2032,20 +2034,14 @@
private final JProgram program;
/**
- * All of the fields and polymorphic methods in String.
- *
- * Because we modify String's prototype, all fields and polymorphic
methods on
- * String's super types need special handling.
+ * All of the fields in String and Array need special handling for
interop.
*/
- private final Map<String, String> specialObfuscatedIdents = new
HashMap<String, String>();
+ private final Map<JField, String> specialObfuscatedFields = new
HashMap<JField, String>();
/**
- * All of the super types of String.
- *
- * Because we modify String's prototype, all fields and polymorphic
methods on
- * String's super types need special handling.
+ * All of the methods in String and Array need special handling for
interop.
*/
- private final Set<JDeclaredType> specialObfuscatedTypes = new
HashSet<JDeclaredType>();
+ private final Map<String, String> specialObfuscatedMethodSigs = new
HashMap<String, String>();
/**
* If true, polymorphic functions are made anonymous vtable declarations
and
@@ -2084,54 +2080,54 @@
this.stripStack =
JsStackEmulator.getStackMode(propertyOracles) ==
JsStackEmulator.StackMode.STRIP;
+
/*
- * Because we modify String's prototype, all fields and polymorphic
methods
- * on String's super types need special handling.
+ * Because we modify the JavaScript String prototype, all fields and
+ * polymorphic methods on String and super types need special handling.
*/
- specialObfuscatedTypes.add(program.getIndexedType("Comparable"));
- specialObfuscatedTypes.add(program.getIndexedType("CharSequence"));
- specialObfuscatedTypes.add(program.getTypeJavaLangObject());
- specialObfuscatedTypes.add(program.getTypeJavaLangString());
- specialObfuscatedTypes.add(program.getIndexedType("Array"));
// Object polymorphic
- specialObfuscatedIdents.put("getClass", "gC");
- specialObfuscatedIdents.put("hashCode", "hC");
- specialObfuscatedIdents.put("equals", "eQ");
- specialObfuscatedIdents.put("toString", "tS");
- specialObfuscatedIdents.put("finalize", "fZ");
-
- // Object fields
- specialObfuscatedIdents.put("expando", "eX");
- specialObfuscatedIdents.put("typeMarker", "tM");
- specialObfuscatedIdents.put("castableTypeMap", "cM");
-
+ Map<String, String> namesToIdents = new HashMap<String, String>();
+ namesToIdents.put("getClass", "gC");
+ namesToIdents.put("hashCode", "hC");
+ namesToIdents.put("equals", "eQ");
+ namesToIdents.put("toString", "tS");
+ namesToIdents.put("finalize", "fZ");
// String polymorphic
- specialObfuscatedIdents.put("charAt", "cA");
- specialObfuscatedIdents.put("compareTo", "cT");
- specialObfuscatedIdents.put("length", "lN");
- specialObfuscatedIdents.put("subSequence", "sS");
-
+ namesToIdents.put("charAt", "cA");
+ namesToIdents.put("compareTo", "cT");
+ namesToIdents.put("length", "lN");
+ namesToIdents.put("subSequence", "sS");
+
+ List<JMethod> methods = new
ArrayList<JMethod>(program.getTypeJavaLangObject().getMethods());
+ methods.addAll(program.getIndexedType("Comparable").getMethods());
+ methods.addAll(program.getIndexedType("CharSequence").getMethods());
+ for (JMethod method : methods) {
+ if (method.canBePolymorphic()) {
+ String ident = namesToIdents.get(method.getName());
+ assert ident != null;
+ specialObfuscatedMethodSigs.put(method.getSignature(), ident);
+ }
+ }
+
+ namesToIdents.clear();
+ // Object fields
+ namesToIdents.put("expando", "eX");
+ namesToIdents.put("typeMarker", "tM");
+ namesToIdents.put("castableTypeMap", "cM");
// Array magic field
- specialObfuscatedIdents.put("arrayClass", "aC");
- specialObfuscatedIdents.put("queryId", "qI");
- }
-
- boolean belongsToSpecialObfuscatedType(JField x) {
- return specialObfuscatedTypes.contains(x.getEnclosingType());
- }
-
- boolean belongsToSpecialObfuscatedType(JMethod x) {
- if (specialObfuscatedTypes.contains(x.getEnclosingType())) {
- return true;
- }
- for (Object element : x.getOverrides()) {
- JMethod override = (JMethod) element;
- if (specialObfuscatedTypes.contains(override.getEnclosingType())) {
- return true;
+ namesToIdents.put("arrayClass", "aC");
+ namesToIdents.put("queryId", "qI");
+
+ List<JField> fields = new
ArrayList<JField>(program.getTypeJavaLangObject().getFields());
+ fields.addAll(program.getIndexedType("Array").getFields());
+ for (JField field : fields) {
+ if (!field.isStatic()) {
+ String ident = namesToIdents.get(field.getName());
+ assert ident != null;
+ specialObfuscatedFields.put(field, ident);
}
}
- return false;
}
String getNameString(HasName hasName) {
@@ -2155,30 +2151,29 @@
}
String mangleNameForPoly(JMethod x) {
- if (x.getOverrides().isEmpty()) {
- return mangleNameForPolyImpl(x);
- } else {
- for (JMethod override : x.getOverrides()) {
- if (override.getOverrides().isEmpty()) {
- return mangleNameForPolyImpl(override);
- }
- }
- }
- throw new InternalCompilerException("Cycle in overrides???");
+ assert !x.isPrivate() && !x.isStatic();
+ StringBuffer sb = new StringBuffer();
+ sb.append(getNameString(x));
+ sb.append("__");
+ for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
+ JType type = x.getOriginalParamTypes().get(i);
+ sb.append(type.getJavahSignatureName());
+ }
+ sb.append(x.getOriginalReturnType().getJavahSignatureName());
+ return sb.toString();
}
- String mangleNameForPolyImpl(JMethod x) {
+ String mangleNameForPrivatePoly(JMethod x) {
+ assert x.isPrivate() && !x.isStatic();
StringBuffer sb = new StringBuffer();
- if (x.isPrivate() && !x.isStatic()) {
- /*
- * Private instance methods in different classes should not override
each
- * other, so they must have distinct polymorphic names. Therefore,
add the
- * class name to the mangled name.
- */
- sb.append("private$");
- sb.append(getNameString(x.getEnclosingType()));
- sb.append("$");
- }
+ /*
+ * Private instance methods in different classes should not override
each
+ * other, so they must have distinct polymorphic names. Therefore, add
the
+ * class name to the mangled name.
+ */
+ sb.append("private$");
+ sb.append(getNameString(x.getEnclosingType()));
+ sb.append("$");
sb.append(getNameString(x));
sb.append("__");
for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
@@ -2190,10 +2185,10 @@
}
String mangleNameSpecialObfuscate(JField x) {
- assert (specialObfuscatedIdents.containsKey(x.getName()));
+ assert (specialObfuscatedFields.containsKey(x));
switch (output) {
case OBFUSCATED:
- return specialObfuscatedIdents.get(x.getName());
+ return specialObfuscatedFields.get(x);
case PRETTY:
return x.getName() + "$";
case DETAILED:
@@ -2203,10 +2198,10 @@
}
String mangleNameSpecialObfuscate(JMethod x) {
- assert (specialObfuscatedIdents.containsKey(x.getName()));
+ assert (specialObfuscatedMethodSigs.containsKey(x.getSignature()));
switch (output) {
case OBFUSCATED:
- return specialObfuscatedIdents.get(x.getName());
+ return specialObfuscatedMethodSigs.get(x.getSignature());
case PRETTY:
return x.getName() + "$";
case DETAILED:
=======================================
---
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
Thu May 5 06:03:58 2011
+++
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
Tue May 17 05:22:26 2011
@@ -16,16 +16,12 @@
package com.google.gwt.dev.jjs.impl;
import com.google.gwt.dev.jjs.ast.Context;
-import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JClassType;
-import com.google.gwt.dev.jjs.ast.JExpression;
-import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNewInstance;
import com.google.gwt.dev.jjs.ast.JNode;
-import com.google.gwt.dev.jjs.ast.JNullType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
@@ -49,54 +45,35 @@
@Override
public void endVisit(JMethodCall x, Context ctx) {
- JMethod method = x.getTarget();
- JExpression instance = x.getInstance();
-
// The method call is already known statically
if (!x.canBePolymorphic()) {
return;
}
- JReferenceType instanceType = ((JReferenceType)
instance.getType()).getUnderlyingType();
- JReferenceType enclosingType = method.getEnclosingType();
-
- if (instanceType == enclosingType || instanceType instanceof
JInterfaceType) {
- // This method call is as tight as it can be for the type of the
- // qualifier
+ JReferenceType instanceType =
+ ((JReferenceType) x.getInstance().getType()).getUnderlyingType();
+ if (!(instanceType instanceof JClassType)) {
+ // Cannot tighten.
return;
}
- if (instanceType instanceof JArrayType) {
- // shouldn't get here; arrays don't have extra methods
+ JMethod method = x.getTarget();
+ if (instanceType == method.getEnclosingType()) {
+ // Cannot tighten.
return;
}
- if (instanceType instanceof JNullType) {
- // TypeTightener will handle this case
+ JMethod foundMethod =
+ program.typeOracle.getPolyMethod((JClassType) instanceType,
method.getSignature());
+ if (foundMethod == null) {
+ // The declared instance type is abstract and doesn't have the
method.
return;
}
-
- assert (instanceType instanceof JClassType);
-
- /*
- * Search myself and all my super types to find a tighter
implementation
- * of the called method, if possible.
- */
- JMethod foundMethod = null;
- JClassType type;
- outer : for (type = (JClassType) instanceType; type != null &&
type != enclosingType; type =
- type.getSuperClass()) {
- for (JMethod methodIt : type.getMethods()) {
- if (methodOverrides(methodIt, method)) {
- foundMethod = methodIt;
- break outer;
- }
- }
- }
-
- if (foundMethod == null) {
+ if (foundMethod == method) {
+ // The instance type doesn't override the method.
return;
}
+ assert foundMethod.canBePolymorphic();
/*
* Replace the call to the original method with a call to the same
method
@@ -111,30 +88,6 @@
public void endVisit(JNewInstance x, Context ctx) {
// Do not tighten new operations.
}
-
- /**
- * Check whether <code>subMethod</code> overrides
<code>supMethod</code>.
- * For the purposes of this method, indirect overrides are considered
- * overrides. For example, if method A.m overrides B.m, and B.m
overrides
- * C.m, then A.m is considered to override C.m. Additionally,
implementing
- * an interface is considered <q>overriding</q> for the purposes of
this
- * method.
- *
- */
- private boolean methodOverrides(JMethod subMethod, JMethod supMethod) {
- if (subMethod.getParams().size() != supMethod.getParams().size()) {
- // short cut: check the number of parameters
- return false;
- }
-
- if (!subMethod.getName().equals(supMethod.getName())) {
- // short cut: check the method names
- return false;
- }
-
- // long way: get all overrides and see if supMethod is included
- return
program.typeOracle.getAllOverrides(subMethod).contains(supMethod);
- }
}
public static final String NAME =
MethodCallTightener.class.getSimpleName();
=======================================
--- /trunk/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java Thu May 5
06:03:58 2011
+++ /trunk/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java Tue May 17
05:22:26 2011
@@ -26,8 +26,6 @@
import junit.framework.TestCase;
-import org.eclipse.jdt.core.compiler.CharOperation;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -238,6 +236,7 @@
classObject = createClass("java.lang.Object", null, false, false);
classString = createClass("java.lang.String", classObject, false,
true);
+ createClass("com.google.gwt.lang.Array", classObject, false, true);
classJso = createClass("com.google.gwt.core.client.JavaScriptObject",
classObject, false, false);
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors