diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java index c244972375..cba3b79218 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java @@ -134,6 +134,22 @@ public void endVisit(JMethodCall x, Context ctx) { return; } + JMethod.Specialization specialization = getCurrentMethod().getSpecialization(); + // If we have a specialization, don't inline that away - specializations must be called + // so they aren't pruned or type tightened into uselessness. + if (specialization != null) { + if (specialization.getTargetMethod() == method) { + return; + } + // We might have had a static impl that in turn will have a specialization - ensure we + // also don't inline that specialization away. Note that this check looks for it "backwards" + // by checking if the inlinable method has an instance method, since current method might + // have once had a static method, but it was already removed. + if (specialization.getTargetMethod() == program.instanceMethodForStaticImpl(method)) { + return; + } + } + if (tryInlineMethodCall(x, ctx) == InlineResult.BLACKLIST) { // Do not try to inline this method again cannotInline.add(method); diff --git a/user/super/com/google/gwt/emul/java/util/EnumSet.java b/user/super/com/google/gwt/emul/java/util/EnumSet.java index 6badd313ea..9d3c147226 100644 --- a/user/super/com/google/gwt/emul/java/util/EnumSet.java +++ b/user/super/com/google/gwt/emul/java/util/EnumSet.java @@ -21,6 +21,7 @@ import static javaemul.internal.InternalPreconditions.checkState; import javaemul.internal.ArrayHelper; +import javaemul.internal.JsUtils; import javaemul.internal.annotations.SpecializeMethod; /** @@ -136,7 +137,7 @@ public EnumSet clone() { @SpecializeMethod(params = Enum.class, target = "containsEnum") @Override public boolean contains(Object o) { - return (o instanceof Enum) && containsEnum((Enum) o); + return (o instanceof Enum) && containsEnum(JsUtils.uncheckedCast(o)); } private boolean containsEnum(Enum e) { @@ -151,7 +152,7 @@ public Iterator iterator() { @SpecializeMethod(params = Enum.class, target = "removeEnum") @Override public boolean remove(Object o) { - return (o instanceof Enum) && removeEnum((Enum) o); + return (o instanceof Enum) && removeEnum(JsUtils.uncheckedCast(o)); } private boolean removeEnum(Enum e) { diff --git a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java index 077e50c4ed..3fb5826c72 100644 --- a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java +++ b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java @@ -82,9 +82,9 @@ public static native boolean unsafeCastToBoolean(Object bool) /*-{ }-*/; @UncheckedCast - public static native T uncheckedCast(@DoNotAutobox Object o) /*-{ - return o; - }-*/; + public static T uncheckedCast(@DoNotAutobox Object o) { + return (T) o; + } @UncheckedCast public static native T getProperty(Object map, String key) /*-{ diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java index ddab6cdf97..68a7d4eac9 100644 --- a/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java +++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java @@ -22,6 +22,10 @@ * An annotation to mark a given method as being specialized. If the specified * parameters and return context match of a JMethodCall, then the call * is retargeted at the specialized version. + *

+ * The annotated method must call the target method directly, and the compiler + * must not inline the target method to prevent it from being pruned while it + * still might be used. */ @Target(ElementType.METHOD) @CompilerHint