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) /*-{