Fixes issue #1989; JSNI references to instance fields/methods on uninstantiable types were causing ICEs when GenerateJavaAST would try to resolve them. Review by: bobv (postmortem) git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1911 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java index b76cede..271ef66 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
@@ -1,5 +1,5 @@ /* - * Copyright 2007 Google Inc. + * 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 @@ -97,7 +97,7 @@ "Could not find enum values() method"); } JsniMethodRef jsniMethodRef = new JsniMethodRef(program.program, null, - valuesMethod); + null, valuesMethod); call.getArgs().add(jsniMethodRef); } } else {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniFieldRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniFieldRef.java index 4480cc6..7245843 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniFieldRef.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniFieldRef.java
@@ -28,10 +28,17 @@ */ public class JsniFieldRef extends JFieldRef { - public JsniFieldRef(JProgram program, SourceInfo info, JField field, - JReferenceType enclosingType) { + private final String ident; + + public JsniFieldRef(JProgram program, SourceInfo info, String ident, + JField field, JReferenceType enclosingType) { super(program, info, field.isStatic() ? null : program.getLiteralNull(), field, enclosingType); + this.ident = ident; + } + + public String getIdent() { + return ident; } public void traverse(JVisitor visitor, Context ctx) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodRef.java index a0fd09b..d035c98 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodRef.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodRef.java
@@ -29,10 +29,18 @@ */ public class JsniMethodRef extends JMethodCall { - public JsniMethodRef(JProgram program, SourceInfo info, JMethod method) { + private final String ident; + + public JsniMethodRef(JProgram program, SourceInfo info, String ident, + JMethod method) { // Just use a null literal as the qualifier on a non-static method super(program, info, method.isStatic() ? null : program.getLiteralNull(), method); + this.ident = ident; + } + + public String getIdent() { + return ident; } @Override
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java index 5f56942..4880242 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -321,8 +321,8 @@ } // Normal: create a jsniRef. - JsniFieldRef fieldRef = new JsniFieldRef(program, info, field, - currentClass); + JsniFieldRef fieldRef = new JsniFieldRef(program, info, + nameRef.getIdent(), field, currentClass); nativeMethodBody.jsniFieldRefs.add(fieldRef); } @@ -338,7 +338,8 @@ + method.getName()); } - JsniMethodRef methodRef = new JsniMethodRef(program, info, method); + JsniMethodRef methodRef = new JsniMethodRef(program, info, + nameRef.getIdent(), method); nativeMethodBody.jsniMethodRefs.add(methodRef); }
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 043de05..e0257e7 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
@@ -17,6 +17,7 @@ import com.google.gwt.dev.jjs.ast.CanBeStatic; import com.google.gwt.dev.jjs.ast.Context; +import com.google.gwt.dev.jjs.ast.HasEnclosingType; import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension; import com.google.gwt.dev.jjs.ast.JArrayType; import com.google.gwt.dev.jjs.ast.JBinaryOperation; @@ -112,16 +113,6 @@ } } - @Override - public void endVisit(JMethod x, Context ctx) { - JType type = x.getType(); - if (type instanceof JReferenceType) { - if (!program.typeOracle.isInstantiatedType((JReferenceType) type)) { - x.setType(program.getTypeNull()); - } - } - } - public void endVisit(JLocalDeclarationStatement x, Context ctx) { // The variable may have been pruned. if (!referencedNonTypes.contains(x.getLocalRef().getTarget())) { @@ -142,6 +133,16 @@ } @Override + public void endVisit(JMethod x, Context ctx) { + JType type = x.getType(); + if (type instanceof JReferenceType) { + if (!program.typeOracle.isInstantiatedType((JReferenceType) type)) { + x.setType(program.getTypeNull()); + } + } + } + + @Override public void endVisit(JMethodCall x, Context ctx) { JMethod method = x.getTarget(); @@ -190,6 +191,38 @@ ctx.replaceMe(newCall); } } + + @Override + public void endVisit(JsniFieldRef x, Context ctx) { + if (isUninstantiable(x.getField())) { + String ident = x.getIdent(); + JField nullField = program.getNullField(); + program.jsniMap.put(ident, nullField); + JsniFieldRef nullFieldRef = new JsniFieldRef(program, + x.getSourceInfo(), ident, nullField, x.getEnclosingType()); + ctx.replaceMe(nullFieldRef); + } + } + + @Override + public void endVisit(JsniMethodRef x, Context ctx) { + // Redirect JSNI refs to uninstantiable types to the null method. + if (isUninstantiable(x.getTarget())) { + String ident = x.getIdent(); + JMethod nullMethod = program.getNullMethod(); + program.jsniMap.put(ident, nullMethod); + JsniMethodRef nullMethodRef = new JsniMethodRef(program, + x.getSourceInfo(), ident, nullMethod); + ctx.replaceMe(nullMethodRef); + } + } + + private <T extends HasEnclosingType & CanBeStatic> boolean isUninstantiable( + T node) { + JReferenceType enclosingType = node.getEnclosingType(); + return !node.isStatic() && enclosingType != null + && !program.typeOracle.isInstantiatedType(enclosingType); + } } /** @@ -831,10 +864,10 @@ return new Pruner(program, noSpecialTypes).execImpl(); } + private final Map<JMethod, ArrayList<JParameter>> methodToOriginalParamsMap = new HashMap<JMethod, ArrayList<JParameter>>(); private final JProgram program; private final Set<JNode> referencedNonTypes = new HashSet<JNode>(); private final Set<JReferenceType> referencedTypes = new HashSet<JReferenceType>(); - private final Map<JMethod, ArrayList<JParameter>> methodToOriginalParamsMap = new HashMap<JMethod, ArrayList<JParameter>>(); private final boolean saveCodeGenTypes; private JMethod stringValueOfChar = null;
diff --git a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java index 9a3533d..94ad4cf 100644 --- a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java
@@ -137,7 +137,7 @@ private static int sideEffectChecker; private static native void accessUninstantiableField(UninstantiableType u) /*-{ - u.@com.google.gwt.dev.jjs.test.CompilerTest$UninstantiableType::field; + u.@com.google.gwt.dev.jjs.test.CompilerTest$UninstantiableType::field.toString(); }-*/; private static native void accessUninstantiableMethod(UninstantiableType u) /*-{